From 5c73b565455d5748b8be745268e14974203d64ab Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Thu, 19 Jun 2014 16:26:03 -0700 Subject: [PATCH 001/881] DO NOT MERGE Don't tear down based on NetworkFactory input. NetworkFactory only indicates if we're interested in new connections. It shouldn't be used to tear down existing connections (they have unwanted callbacks for that). Supports linger properly as well as dealing with tie scores. bug:15612739 Change-Id: Ib3dfe673d3645b9dc4756c176958409a64ec32e4 (cherry picked from commit ed75bcf13a0b416843cf8d8e349a3340ae270f9d) --- .../ethernet/EthernetNetworkFactory.java | 51 +++++++++---------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 483f983fb7..b1b98d2692 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -114,7 +114,6 @@ class EthernetNetworkFactory { onRequestNetwork(); } protected void stopNetwork() { - onCancelRequest(); } } @@ -202,13 +201,13 @@ class EthernetNetworkFactory { return; Log.d(TAG, "Stopped tracking interface " + iface); - onCancelRequest(); synchronized (this) { mIface = ""; mHwAddr = null; mNetworkInfo.setExtraInfo(null); mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); mLinkProperties = new LinkProperties(); + updateAgent(); } } @@ -283,6 +282,10 @@ class EthernetNetworkFactory { } synchronized(EthernetNetworkFactory.this) { + if (mNetworkAgent != null) { + Log.e(TAG, "Already have a NetworkAgent - aborting new request"); + return; + } mLinkProperties = linkProperties; mNetworkInfo.setIsAvailable(true); mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); @@ -292,7 +295,25 @@ class EthernetNetworkFactory { NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, NETWORK_SCORE) { public void unwanted() { - EthernetNetworkFactory.this.onCancelRequest(); + synchronized(EthernetNetworkFactory.this) { + if (this == mNetworkAgent) { + NetworkUtils.stopDhcp(mIface); + + mLinkProperties.clear(); + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, + mHwAddr); + updateAgent(); + mNetworkAgent = null; + try { + mNMService.clearInterfaceAddresses(mIface); + } catch (Exception e) { + Log.e(TAG, "Failed to clear addresses or disable ipv6" + e); + } + } else { + Log.d(TAG, "Ignoring unwanted as we have a more modern " + + "instance"); + } + } }; }; } @@ -301,28 +322,6 @@ class EthernetNetworkFactory { dhcpThread.start(); } - /** - * Clears layer 3 properties and reports disconnect. - * Does not touch interface state variables such as link state and MAC address. - * Called when the tracked interface loses link or disappears. - */ - public void onCancelRequest() { - NetworkUtils.stopDhcp(mIface); - - synchronized(this) { - mLinkProperties.clear(); - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - updateAgent(); - mNetworkAgent = null; - } - - try { - mNMService.clearInterfaceAddresses(mIface); - } catch (Exception e) { - Log.e(TAG, "Failed to clear addresses or disable ipv6" + e); - } - } - /** * Begin monitoring connectivity */ @@ -379,12 +378,12 @@ class EthernetNetworkFactory { } public synchronized void stop() { - onCancelRequest(); mIface = ""; mHwAddr = null; mLinkUp = false; mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); mLinkProperties = new LinkProperties(); + updateAgent(); mFactory.unregister(); } From ed59a4eeb1355ac6c5e941dea665eafc3213e505 Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Wed, 6 Aug 2014 22:27:17 -0700 Subject: [PATCH 002/881] Add tcp buffer size data for ethernet bug: 16549611 Change-Id: I61d29bb88b9e58c50e03c39570f3ebb7712e4f37 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index b1b98d2692..3f0037cccf 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -247,6 +247,9 @@ class EthernetNetworkFactory { } } + private static final String TCP_BUFFER_SIZES_ETHERNET = + "524288,1048576,3145728,524288,1048576,2097152"; + /* Called by the NetworkFactory on the handler thread. */ public void onRequestNetwork() { // TODO: Handle DHCP renew. @@ -281,6 +284,8 @@ class EthernetNetworkFactory { linkProperties.setHttpProxy(config.linkProperties.getHttpProxy()); } + linkProperties.setTcpBufferSizes(TCP_BUFFER_SIZES_ETHERNET); + synchronized(EthernetNetworkFactory.this) { if (mNetworkAgent != null) { Log.e(TAG, "Already have a NetworkAgent - aborting new request"); From a24d7203da9a1bbd878c20bcc8248a89208759c2 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 12 Aug 2014 10:49:39 +0900 Subject: [PATCH 003/881] Stop using LinkProperties for static configuration. Also make static IP configuration more robust (e.g., tear down our NetworkAgent when we switch between static and DHCP). Bug: 16114392 Bug: 16893413 Change-Id: Ib33f35c004e30b6067bb20235ffa43c247d174df --- .../server/ethernet/EthernetConfigStore.java | 3 +- .../ethernet/EthernetNetworkFactory.java | 64 +++++++++++-------- .../server/ethernet/EthernetServiceImpl.java | 7 +- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java index 7a428a8b32..676bc99d8a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java +++ b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java @@ -19,7 +19,6 @@ package com.android.server.ethernet; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; -import android.net.LinkProperties; import android.os.Environment; import android.util.Log; import android.util.SparseArray; @@ -44,7 +43,7 @@ public class EthernetConfigStore extends IpConfigStore { if (networks.size() == 0) { Log.w(TAG, "No Ethernet configuration found. Using default."); - return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, new LinkProperties()); + return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); } if (networks.size() > 1) { diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 3f0037cccf..c65a5b20f5 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -33,6 +33,7 @@ import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; import android.net.EthernetManager; +import android.net.StaticIpConfiguration; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; @@ -211,24 +212,23 @@ class EthernetNetworkFactory { } } - private void setStaticIpAddress(LinkProperties linkProperties) { - Log.i(TAG, "Applying static IPv4 configuration to " + mIface + ": " + mLinkProperties); - try { - InterfaceConfiguration config = mNMService.getInterfaceConfig(mIface); - for (LinkAddress address: linkProperties.getLinkAddresses()) { - // IPv6 uses autoconfiguration. - if (address.getAddress() instanceof Inet4Address) { - config.setLinkAddress(address); - // This API only supports one IPv4 address. - mNMService.setInterfaceConfig(mIface, config); - break; - } + private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) { + if (staticConfig.ipAddress != null && + staticConfig.gateway != null && + staticConfig.dnsServers.size() > 0) { + try { + Log.i(TAG, "Applying static IPv4 configuration to " + mIface + ": " + staticConfig); + InterfaceConfiguration config = mNMService.getInterfaceConfig(mIface); + config.setLinkAddress(staticConfig.ipAddress); + mNMService.setInterfaceConfig(mIface, config); + return true; + } catch(RemoteException|IllegalStateException e) { + Log.e(TAG, "Setting static IP address failed: " + e.getMessage()); } - } catch(RemoteException e) { - Log.e(TAG, "Setting static IP address failed: " + e.getMessage()); - } catch(IllegalStateException e) { - Log.e(TAG, "Setting static IP address failed: " + e.getMessage()); + } else { + Log.e(TAG, "Invalid static IP configuration."); } + return false; } public void updateAgent() { @@ -260,9 +260,12 @@ class EthernetNetworkFactory { IpConfiguration config = mEthernetManager.getConfiguration(); - if (config.ipAssignment == IpAssignment.STATIC) { - linkProperties = config.linkProperties; - setStaticIpAddress(linkProperties); + if (config.getIpAssignment() == IpAssignment.STATIC) { + if (!setStaticIpAddress(config.getStaticIpConfiguration())) { + // We've already logged an error. + return; + } + linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); } else { mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); @@ -277,11 +280,11 @@ class EthernetNetworkFactory { mFactory.setScoreFilter(-1); return; } - linkProperties = dhcpResults.linkProperties; - linkProperties.setInterfaceName(mIface); + linkProperties = dhcpResults.toLinkProperties(mIface); } - if (config.proxySettings == ProxySettings.STATIC) { - linkProperties.setHttpProxy(config.linkProperties.getHttpProxy()); + if (config.getProxySettings() == ProxySettings.STATIC || + config.getProxySettings() == ProxySettings.PAC) { + linkProperties.setHttpProxy(config.getHttpProxy()); } linkProperties.setTcpBufferSizes(TCP_BUFFER_SIZES_ETHERNET); @@ -383,12 +386,21 @@ class EthernetNetworkFactory { } public synchronized void stop() { + NetworkUtils.stopDhcp(mIface); + // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object + // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: + // that sets the state to IDLE, and ConnectivityService will still think we're connected. + // + // TODO: stop using explicit comparisons to DISCONNECTED / SUSPENDED in ConnectivityService, + // and instead use isConnectedOrConnecting(). + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); + mLinkUp = false; + updateAgent(); + mLinkProperties = new LinkProperties(); + mNetworkAgent = null; mIface = ""; mHwAddr = null; - mLinkUp = false; mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); - mLinkProperties = new LinkProperties(); - updateAgent(); mFactory.unregister(); } diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 08a2e9afce..1534aabe3e 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -25,11 +25,11 @@ import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; -import android.net.LinkProperties; import android.net.NetworkAgent; import android.net.NetworkInfo; import android.net.NetworkRequest; import android.net.RouteInfo; +import android.net.StaticIpConfiguration; import android.os.Binder; import android.os.IBinder; import android.os.Handler; @@ -143,10 +143,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { // TODO: this does not check proxy settings, gateways, etc. // Fix this by making IpConfiguration a complete representation of static configuration. if (!config.equals(mIpConfiguration)) { - mIpConfiguration.ipAssignment = config.ipAssignment; - mIpConfiguration.proxySettings = config.proxySettings; - mIpConfiguration.linkProperties = new LinkProperties(config.linkProperties); - + mIpConfiguration = new IpConfiguration(config); mTracker.stop(); mTracker.start(mContext, mHandler); } From f4e94371f1bf76e5e4afaa7310eea8199e0a28b7 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 19 Aug 2014 11:45:46 -0700 Subject: [PATCH 004/881] Actually provide useful output in Ethernet service dump. Bug: 17133859 Change-Id: Ic8424004e48712e4dd906d5bb6a48ce7d38ff9d8 --- .../ethernet/EthernetNetworkFactory.java | 20 +++++++++++++++++++ .../server/ethernet/EthernetServiceImpl.java | 10 ++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index c65a5b20f5..26e8264a56 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -45,8 +45,11 @@ import android.os.ServiceManager; import android.text.TextUtils; import android.util.Log; +import com.android.internal.util.IndentingPrintWriter; import com.android.server.net.BaseNetworkObserver; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.net.Inet4Address; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -413,4 +416,21 @@ class EthernetNetworkFactory { mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000); mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000); } + + synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { + if (!TextUtils.isEmpty(mIface)) { + pw.println("Tracking interface: " + mIface); + pw.increaseIndent(); + pw.println("MAC address: " + mHwAddr); + pw.println("Link state: " + (mLinkUp ? "up" : "down")); + pw.decreaseIndent(); + } else { + pw.println("Not tracking any interface"); + } + + pw.println(); + pw.println("NetworkInfo: " + mNetworkInfo); + pw.println("LinkProperties: " + mLinkProperties); + pw.println("NetworkAgent: " + mNetworkAgent); + } } diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 1534aabe3e..42d98f65c8 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -67,7 +67,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { private Handler mHandler; private NetworkInfo mNetworkInfo; - private EthernetNetworkFactory mTracker; + private final EthernetNetworkFactory mTracker; public EthernetServiceImpl(Context context) { mContext = context; @@ -160,8 +160,14 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { + ", uid=" + Binder.getCallingUid()); return; } - pw.println("Stored Ethernet configuration: "); + pw.println("Current Ethernet state: "); + pw.increaseIndent(); + mTracker.dump(fd, pw, args); + pw.decreaseIndent(); + + pw.println(); + pw.println("Stored Ethernet configuration: "); pw.increaseIndent(); pw.println(mIpConfiguration); pw.decreaseIndent(); From 92c045615efbe3cd9b4d0c2f228b0647288c978b Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Thu, 21 Aug 2014 16:28:18 -0700 Subject: [PATCH 005/881] Use config resource for tcp buffer size bug:16549611 Change-Id: I48426f6b746e4bd9729bdd529d81b163ff5112a9 --- .../android/server/ethernet/EthernetNetworkFactory.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 26e8264a56..83a3fa7be0 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -250,9 +250,6 @@ class EthernetNetworkFactory { } } - private static final String TCP_BUFFER_SIZES_ETHERNET = - "524288,1048576,3145728,524288,1048576,2097152"; - /* Called by the NetworkFactory on the handler thread. */ public void onRequestNetwork() { // TODO: Handle DHCP renew. @@ -290,7 +287,11 @@ class EthernetNetworkFactory { linkProperties.setHttpProxy(config.getHttpProxy()); } - linkProperties.setTcpBufferSizes(TCP_BUFFER_SIZES_ETHERNET); + String tcpBufferSizes = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_tcp_buffers); + if (TextUtils.isEmpty(tcpBufferSizes) == false) { + linkProperties.setTcpBufferSizes(tcpBufferSizes); + } synchronized(EthernetNetworkFactory.this) { if (mNetworkAgent != null) { From 8de2ac37c19ff117f8c2036fa88c62d501718123 Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Wed, 10 Sep 2014 10:06:32 -0700 Subject: [PATCH 006/881] Don't accept score below 0. Network Factories are allowed to go below, but networks need to be constrained. Allowing the network to go below 0 meant that -1 could sometimes leak through and foul the logic. bug:17361330 Change-Id: Ife34ca0f9c233dd3c3df80f6fea580af43afcdeb --- .../android/server/ethernet/EthernetNetworkFactory.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 83a3fa7be0..a4711548cb 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -140,6 +140,9 @@ class EthernetNetworkFactory { mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); } updateAgent(); + // set our score lower than any network could go + // so we get dropped. TODO - just unregister the factory + // when link goes down. mFactory.setScoreFilter(up ? NETWORK_SCORE : -1); } } @@ -246,7 +249,8 @@ class EthernetNetworkFactory { mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); mNetworkAgent.sendNetworkInfo(mNetworkInfo); mNetworkAgent.sendLinkProperties(mLinkProperties); - mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : -1); + // never set the network score below 0. + mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); } } @@ -277,6 +281,8 @@ class EthernetNetworkFactory { // noticing. if (!NetworkUtils.runDhcp(mIface, dhcpResults)) { Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); + // set our score lower than any network could go + // so we get dropped. mFactory.setScoreFilter(-1); return; } From 0a9e33f5b9583e4ac7104f861e5b9ac0155eb368 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 1 Oct 2014 13:52:40 +0900 Subject: [PATCH 007/881] Clear all Ethernet state when our interface goes away. Previously we did not stop DHCP or try to force a disconnect. This made it impossible to reconnect by unplugging and replugging an USB Ethernet adapter. Bug: 17736828 Change-Id: Idd8576a96b063b5ca726ee9149800bdcb0f62bd1 --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index a4711548cb..2d0a95728b 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -208,13 +208,18 @@ class EthernetNetworkFactory { return; Log.d(TAG, "Stopped tracking interface " + iface); + // TODO: Unify this codepath with stop(). synchronized (this) { + NetworkUtils.stopDhcp(mIface); mIface = ""; mHwAddr = null; mNetworkInfo.setExtraInfo(null); + mLinkUp = false; + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); + updateAgent(); + mNetworkAgent = null; mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); mLinkProperties = new LinkProperties(); - updateAgent(); } } From e14ee540d6accf3468367f2a25a4540fd3e08051 Mon Sep 17 00:00:00 2001 From: Jaewan Kim Date: Mon, 20 Oct 2014 12:03:46 +0900 Subject: [PATCH 008/881] Add an API to check availability of Ethernet interface. Bug: 18045481 Change-Id: I3fb517c3e7fa807e2937fda92026301e312be986 --- .../ethernet/EthernetNetworkFactory.java | 61 +++++++++++------ .../server/ethernet/EthernetServiceImpl.java | 67 ++++++++++++------- 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 2d0a95728b..bbb99d8c98 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -19,27 +19,25 @@ package com.android.server.ethernet; import android.content.Context; import android.net.ConnectivityManager; import android.net.DhcpResults; +import android.net.EthernetManager; +import android.net.IEthernetServiceListener; import android.net.InterfaceConfiguration; -import android.net.NetworkUtils; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; -import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkAgent; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; -import android.net.NetworkRequest; -import android.net.EthernetManager; +import android.net.NetworkUtils; import android.net.StaticIpConfiguration; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Looper; -import android.os.Message; -import android.os.Messenger; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceManager; import android.text.TextUtils; @@ -50,9 +48,6 @@ import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.net.Inet4Address; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; /** @@ -96,6 +91,9 @@ class EthernetNetworkFactory { /** Product-dependent regular expression of interface names we track. */ private static String mIfaceMatch = ""; + /** To notify Ethernet status. */ + private final RemoteCallbackList mListeners; + /** Data members. All accesses to these must be synchronized(this). */ private static String mIface = ""; private String mHwAddr; @@ -103,10 +101,11 @@ class EthernetNetworkFactory { private NetworkInfo mNetworkInfo; private LinkProperties mLinkProperties; - EthernetNetworkFactory() { + EthernetNetworkFactory(RemoteCallbackList listeners) { mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); mLinkProperties = new LinkProperties(); initNetworkCapabilities(); + mListeners = listeners; } private class LocalNetworkFactory extends NetworkFactory { @@ -177,9 +176,8 @@ class EthernetNetworkFactory { } synchronized (this) { - if (mIface.isEmpty()) { - mIface = iface; - mHwAddr = config.getHardwareAddress(); + if (!isTrackingInterface()) { + setInterfaceInfoLocked(iface, config.getHardwareAddress()); mNetworkInfo.setIsAvailable(true); mNetworkInfo.setExtraInfo(mHwAddr); } else { @@ -195,7 +193,7 @@ class EthernetNetworkFactory { private boolean maybeTrackInterface(String iface) { // If we don't already have an interface, and if this interface matches // our regex, start tracking it. - if (!iface.matches(mIfaceMatch) || !mIface.isEmpty()) + if (!iface.matches(mIfaceMatch) || isTrackingInterface()) return false; Log.d(TAG, "Started tracking interface " + iface); @@ -211,8 +209,7 @@ class EthernetNetworkFactory { // TODO: Unify this codepath with stop(). synchronized (this) { NetworkUtils.stopDhcp(mIface); - mIface = ""; - mHwAddr = null; + setInterfaceInfoLocked("", null); mNetworkInfo.setExtraInfo(null); mLinkUp = false; mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); @@ -413,8 +410,7 @@ class EthernetNetworkFactory { updateAgent(); mLinkProperties = new LinkProperties(); mNetworkAgent = null; - mIface = ""; - mHwAddr = null; + setInterfaceInfoLocked("", null); mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); mFactory.unregister(); } @@ -429,8 +425,35 @@ class EthernetNetworkFactory { mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000); } + public synchronized boolean isTrackingInterface() { + return !TextUtils.isEmpty(mIface); + } + + /** + * Set interface information and notify listeners if availability is changed. + * This should be called with the lock held. + */ + private void setInterfaceInfoLocked(String iface, String hwAddr) { + boolean oldAvailable = isTrackingInterface(); + mIface = iface; + mHwAddr = hwAddr; + boolean available = isTrackingInterface(); + + if (oldAvailable != available) { + int n = mListeners.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mListeners.getBroadcastItem(i).onAvailabilityChanged(available); + } catch (RemoteException e) { + // Do nothing here. + } + } + mListeners.finishBroadcast(); + } + } + synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { - if (!TextUtils.isEmpty(mIface)) { + if (isTrackingInterface()) { pw.println("Tracking interface: " + mIface); pw.increaseIndent(); pw.println("MAC address: " + mHwAddr); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 42d98f65c8..bb1cc514e4 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -18,37 +18,25 @@ package com.android.server.ethernet; import android.content.Context; import android.content.pm.PackageManager; -import com.android.internal.util.IndentingPrintWriter; -import android.net.ConnectivityManager; import android.net.IEthernetManager; +import android.net.IEthernetServiceListener; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; -import android.net.LinkAddress; -import android.net.NetworkAgent; -import android.net.NetworkInfo; -import android.net.NetworkRequest; -import android.net.RouteInfo; -import android.net.StaticIpConfiguration; import android.os.Binder; -import android.os.IBinder; import android.os.Handler; import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; -import android.os.INetworkManagementService; +import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.ServiceManager; -import android.text.TextUtils; import android.util.Log; import android.util.PrintWriterPrinter; +import com.android.internal.util.IndentingPrintWriter; + import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.concurrent.atomic.AtomicBoolean; - /** * EthernetServiceImpl handles remote Ethernet operation requests by implementing * the IEthernetManager interface. @@ -60,14 +48,13 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { private final Context mContext; private final EthernetConfigStore mEthernetConfigStore; - private final INetworkManagementService mNMService; private final AtomicBoolean mStarted = new AtomicBoolean(false); private IpConfiguration mIpConfiguration; - private ConnectivityManager mCM; private Handler mHandler; - private NetworkInfo mNetworkInfo; private final EthernetNetworkFactory mTracker; + private final RemoteCallbackList mListeners = + new RemoteCallbackList(); public EthernetServiceImpl(Context context) { mContext = context; @@ -77,10 +64,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Log.i(TAG, "Read stored IP configuration: " + mIpConfiguration); - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNMService = INetworkManagementService.Stub.asInterface(b); - - mTracker = new EthernetNetworkFactory(); + mTracker = new EthernetNetworkFactory(mListeners); } private void enforceAccessPermission() { @@ -103,7 +87,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { public void start() { Log.i(TAG, "Starting Ethernet service"); - mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); HandlerThread handlerThread = new HandlerThread("EthernetServiceThread"); handlerThread.start(); @@ -118,6 +101,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { * Get Ethernet configuration * @return the Ethernet Configuration, contained in {@link IpConfiguration}. */ + @Override public IpConfiguration getConfiguration() { enforceAccessPermission(); @@ -129,6 +113,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { /** * Set Ethernet configuration */ + @Override public void setConfiguration(IpConfiguration config) { if (!mStarted.get()) { Log.w(TAG, "System isn't ready enough to change ethernet configuration"); @@ -150,6 +135,40 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { } } + /** + * Indicates whether the system currently has one or more + * Ethernet interfaces. + */ + @Override + public boolean isAvailable() { + enforceAccessPermission(); + return mTracker.isTrackingInterface(); + } + + /** + * Addes a listener. + * @param listener A {@link IEthernetServiceListener} to add. + */ + public void addListener(IEthernetServiceListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + enforceAccessPermission(); + mListeners.register(listener); + } + + /** + * Removes a listener. + * @param listener A {@link IEthernetServiceListener} to remove. + */ + public void removeListener(IEthernetServiceListener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + enforceAccessPermission(); + mListeners.unregister(listener); + } + @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); From f22c4081b3a34ba28bebf2ae422ccbc4a317cab2 Mon Sep 17 00:00:00 2001 From: Pierre Couillaud Date: Wed, 11 Feb 2015 08:55:29 -0800 Subject: [PATCH 009/881] eth: make sure dhcp is stopped before bringing up interface. Signed-off-by: Pierre Couillaud Signed-off-by: Blair Prescott --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 2d0a95728b..2de3cea1bf 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -167,6 +167,7 @@ class EthernetNetworkFactory { private void setInterfaceUp(String iface) { // Bring up the interface so we get link status indications. try { + NetworkUtils.stopDhcp(iface); mNMService.setInterfaceUp(iface); String hwAddr = null; InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); From cc8d7219b3255ea4715b418b4ca2d30efe56f1c2 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 4 Aug 2015 13:27:28 +0900 Subject: [PATCH 010/881] Stop DHCP if it times out. This was not necessary in L, but it is necessary after https://partner-android-review.googlesource.com/#/c/205415/ . Bug: 22936203 Change-Id: I24a96c33e5bb375f36217a1c2cec2076eb5ac8b4 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 0c4f57d6aa..4503197fc6 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -262,7 +262,7 @@ class EthernetNetworkFactory { // TODO: Handle DHCP renew. Thread dhcpThread = new Thread(new Runnable() { public void run() { - if (DBG) Log.i(TAG, "dhcpThread(+" + mIface + "): mNetworkInfo=" + mNetworkInfo); + if (DBG) Log.i(TAG, "dhcpThread(" + mIface + "): mNetworkInfo=" + mNetworkInfo); LinkProperties linkProperties; IpConfiguration config = mEthernetManager.getConfiguration(); @@ -287,6 +287,9 @@ class EthernetNetworkFactory { // set our score lower than any network could go // so we get dropped. mFactory.setScoreFilter(-1); + // If DHCP timed out (as opposed to failing), the DHCP client will still be + // running, because in M we changed its timeout to infinite. Stop it now. + NetworkUtils.stopDhcp(mIface); return; } linkProperties = dhcpResults.toLinkProperties(mIface); From 36deb5cccad9a07b7c9a6ba3a8b1490046cb4811 Mon Sep 17 00:00:00 2001 From: Billy Lau Date: Sat, 1 Aug 2015 18:20:04 +0100 Subject: [PATCH 011/881] Bug: 21588539 Move CHANGE_NETWORK_STATE to be in SYSTEM_SETTINGS Replaced the method where we used to enforce static permission CHANGE_NETWORK_STATE to method calls that also check for WRITE_SETTINGS. This is due to the merging of CHANGE_NETWORK_STATE permission with WRITE_SETTINGS in M. Change-Id: I104ac41733663b4f6b5cd30e7314574ec4acdc07 --- .../com/android/server/ethernet/EthernetServiceImpl.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index bb1cc514e4..0c84befbcd 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -28,6 +28,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; import android.util.PrintWriterPrinter; @@ -74,9 +75,9 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { } private void enforceChangePermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CHANGE_NETWORK_STATE, - "EthernetService"); + int uid = Binder.getCallingUid(); + Settings.checkAndNoteChangeNetworkStateOperation(mContext, uid, Settings + .getPackageNameForUid(mContext, uid), true); } private void enforceConnectivityInternalPermission() { From e31781fcc2dcdd23c8084fec8b85f81f59dc8102 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 8 Sep 2015 16:21:52 +0900 Subject: [PATCH 012/881] Don't crash on startup if we can't fetch the interface list. The intent of the code was to catch exceptions, but it wasn't actually doing that because when a netd command fails we get an IllegalStateException, not a RemoteException. Bug: 23581852 Change-Id: I66c7c33bdc7b0d0de4fa5cd92dff054797cf860f --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 4503197fc6..6074dda6e0 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -396,7 +396,7 @@ class EthernetNetworkFactory { } } } - } catch (RemoteException e) { + } catch (RemoteException|IllegalStateException e) { Log.e(TAG, "Could not get list of interfaces " + e); } } From 5c3ae179e3b4895ca17722f34c545de2cf5bcd0c Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 15 Oct 2015 16:59:07 +0900 Subject: [PATCH 013/881] Stop requiring CHANGE_NETWORK_STATE to change Ethernet config. Requiring CHANGE_NETWORK_STATE is pointless, since immediately after doing that we require CONNECTIVITY_INTERNAL, which is a system-only permission. Bug: 23597341 Change-Id: If4c8ecbb319e547c2c81d2dcc3c7bbb63e0bc2af --- .../com/android/server/ethernet/EthernetServiceImpl.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 0c84befbcd..42996d6826 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -74,12 +74,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { "EthernetService"); } - private void enforceChangePermission() { - int uid = Binder.getCallingUid(); - Settings.checkAndNoteChangeNetworkStateOperation(mContext, uid, Settings - .getPackageNameForUid(mContext, uid), true); - } - private void enforceConnectivityInternalPermission() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_INTERNAL, @@ -120,7 +114,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Log.w(TAG, "System isn't ready enough to change ethernet configuration"); } - enforceChangePermission(); enforceConnectivityInternalPermission(); synchronized (mIpConfiguration) { From 011ccfe51492abb6052df2ab19c7be6a9f91e042 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Thu, 11 Feb 2016 22:06:48 +0900 Subject: [PATCH 014/881] Use IpManager on Ethernet Bug: 17733693 Bug: 26991160 Change-Id: Idaee8c64bf452e58b93031d8d7ad666edb0c82ae --- .../ethernet/EthernetNetworkFactory.java | 118 ++++++++++++++---- 1 file changed, 95 insertions(+), 23 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 6074dda6e0..3c230fb38a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -31,8 +31,8 @@ import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; -import android.net.NetworkUtils; import android.net.StaticIpConfiguration; +import android.net.ip.IpManager; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; @@ -100,6 +100,8 @@ class EthernetNetworkFactory { private static boolean mLinkUp; private NetworkInfo mNetworkInfo; private LinkProperties mLinkProperties; + private IpManager mIpManager; + private Thread mIpProvisioningThread; EthernetNetworkFactory(RemoteCallbackList listeners) { mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); @@ -120,6 +122,21 @@ class EthernetNetworkFactory { } } + private void stopIpManagerLocked() { + if (mIpManager != null) { + mIpManager.shutdown(); + mIpManager = null; + } + } + + private void stopIpProvisioningThreadLocked() { + stopIpManagerLocked(); + + if (mIpProvisioningThread != null) { + mIpProvisioningThread.interrupt(); + mIpProvisioningThread = null; + } + } /** * Updates interface state variables. @@ -137,6 +154,7 @@ class EthernetNetworkFactory { if (!up) { // Tell the agent we're disconnected. It will call disconnect(). mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); + stopIpProvisioningThreadLocked(); } updateAgent(); // set our score lower than any network could go @@ -166,7 +184,6 @@ class EthernetNetworkFactory { private void setInterfaceUp(String iface) { // Bring up the interface so we get link status indications. try { - NetworkUtils.stopDhcp(iface); mNMService.setInterfaceUp(iface); String hwAddr = null; InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); @@ -209,7 +226,7 @@ class EthernetNetworkFactory { Log.d(TAG, "Stopped tracking interface " + iface); // TODO: Unify this codepath with stop(). synchronized (this) { - NetworkUtils.stopDhcp(mIface); + stopIpProvisioningThreadLocked(); setInterfaceInfoLocked("", null); mNetworkInfo.setExtraInfo(null); mLinkUp = false; @@ -257,12 +274,52 @@ class EthernetNetworkFactory { } } + private class IpManagerCallback extends IpManager.Callback { + private LinkProperties mCallbackLinkProperties; + + public LinkProperties waitForProvisioning() { + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) {} + return mCallbackLinkProperties; + } + } + + @Override + public void onProvisioningSuccess(LinkProperties newLp) { + synchronized (this) { + mCallbackLinkProperties = newLp; + notify(); + } + } + + @Override + public void onProvisioningFailure(LinkProperties newLp) { + synchronized (this) { + mCallbackLinkProperties = null; + notify(); + } + } + } + + /* Called by the NetworkFactory on the handler thread. */ public void onRequestNetwork() { + synchronized(EthernetNetworkFactory.this) { + if (mIpProvisioningThread != null) { + return; + } + } + // TODO: Handle DHCP renew. - Thread dhcpThread = new Thread(new Runnable() { + final Thread ipProvisioningThread = new Thread(new Runnable() { public void run() { - if (DBG) Log.i(TAG, "dhcpThread(" + mIface + "): mNetworkInfo=" + mNetworkInfo); + if (DBG) { + Log.d(TAG, String.format("starting ipProvisioningThread(%s): mNetworkInfo=%s", + mIface, mNetworkInfo)); + } + LinkProperties linkProperties; IpConfiguration config = mEthernetManager.getConfiguration(); @@ -275,39 +332,41 @@ class EthernetNetworkFactory { linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); } else { mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); - - DhcpResults dhcpResults = new DhcpResults(); - // TODO: Handle DHCP renewals better. - // In general runDhcp handles DHCP renewals for us, because - // the dhcp client stays running, but if the renewal fails, - // we will lose our IP address and connectivity without - // noticing. - if (!NetworkUtils.runDhcp(mIface, dhcpResults)) { - Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); + IpManagerCallback blockingCallback = new IpManagerCallback(); + synchronized(EthernetNetworkFactory.this) { + stopIpManagerLocked(); + mIpManager = new IpManager(mContext, mIface, blockingCallback); + mIpManager.startProvisioning(); + } + linkProperties = blockingCallback.waitForProvisioning(); + if (linkProperties == null) { + Log.e(TAG, "IP provisioning error"); // set our score lower than any network could go // so we get dropped. mFactory.setScoreFilter(-1); - // If DHCP timed out (as opposed to failing), the DHCP client will still be - // running, because in M we changed its timeout to infinite. Stop it now. - NetworkUtils.stopDhcp(mIface); + synchronized(EthernetNetworkFactory.this) { + stopIpManagerLocked(); + } return; } - linkProperties = dhcpResults.toLinkProperties(mIface); } + if (config.getProxySettings() == ProxySettings.STATIC || config.getProxySettings() == ProxySettings.PAC) { linkProperties.setHttpProxy(config.getHttpProxy()); } - String tcpBufferSizes = mContext.getResources().getString( + final String tcpBufferSizes = mContext.getResources().getString( com.android.internal.R.string.config_ethernet_tcp_buffers); - if (TextUtils.isEmpty(tcpBufferSizes) == false) { + if (!TextUtils.isEmpty(tcpBufferSizes)) { linkProperties.setTcpBufferSizes(tcpBufferSizes); } synchronized(EthernetNetworkFactory.this) { if (mNetworkAgent != null) { Log.e(TAG, "Already have a NetworkAgent - aborting new request"); + stopIpManagerLocked(); + mIpProvisioningThread = null; return; } mLinkProperties = linkProperties; @@ -321,7 +380,7 @@ class EthernetNetworkFactory { public void unwanted() { synchronized(EthernetNetworkFactory.this) { if (this == mNetworkAgent) { - NetworkUtils.stopDhcp(mIface); + stopIpManagerLocked(); mLinkProperties.clear(); mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, @@ -340,10 +399,23 @@ class EthernetNetworkFactory { } }; }; + + mIpProvisioningThread = null; + } + + if (DBG) { + Log.d(TAG, String.format("exiting ipProvisioningThread(%s): mNetworkInfo=%s", + mIface, mNetworkInfo)); } } }); - dhcpThread.start(); + + synchronized(EthernetNetworkFactory.this) { + if (mIpProvisioningThread == null) { + mIpProvisioningThread = ipProvisioningThread; + mIpProvisioningThread.start(); + } + } } /** @@ -402,7 +474,7 @@ class EthernetNetworkFactory { } public synchronized void stop() { - NetworkUtils.stopDhcp(mIface); + stopIpProvisioningThreadLocked(); // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: // that sets the state to IDLE, and ConnectivityService will still think we're connected. From 57955ea0bf7ff82e25b709dae4c5d9b6fffabd2d Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Mon, 22 Feb 2016 11:11:38 +0900 Subject: [PATCH 015/881] Use more IpManager features - WaitForProvisioningCallback - setHttpProxy - setTcpBufferSizes Bug: 26991160 Change-Id: I5e02039a35006f0466fb40c43805f0443cd758c2 --- .../ethernet/EthernetNetworkFactory.java | 71 +++++++------------ 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 3c230fb38a..718686344d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -33,6 +33,7 @@ import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.StaticIpConfiguration; import android.net.ip.IpManager; +import android.net.ip.IpManager.WaitForProvisioningCallback; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; @@ -274,36 +275,6 @@ class EthernetNetworkFactory { } } - private class IpManagerCallback extends IpManager.Callback { - private LinkProperties mCallbackLinkProperties; - - public LinkProperties waitForProvisioning() { - synchronized (this) { - try { - wait(); - } catch (InterruptedException e) {} - return mCallbackLinkProperties; - } - } - - @Override - public void onProvisioningSuccess(LinkProperties newLp) { - synchronized (this) { - mCallbackLinkProperties = newLp; - notify(); - } - } - - @Override - public void onProvisioningFailure(LinkProperties newLp) { - synchronized (this) { - mCallbackLinkProperties = null; - notify(); - } - } - } - - /* Called by the NetworkFactory on the handler thread. */ public void onRequestNetwork() { synchronized(EthernetNetworkFactory.this) { @@ -332,13 +303,36 @@ class EthernetNetworkFactory { linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); } else { mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); - IpManagerCallback blockingCallback = new IpManagerCallback(); + WaitForProvisioningCallback ipmCallback = new WaitForProvisioningCallback() { + @Override + public void onLinkPropertiesChange(LinkProperties newLp) { + synchronized(EthernetNetworkFactory.this) { + if (mNetworkAgent != null && mNetworkInfo.isConnected()) { + mNetworkAgent.sendLinkProperties(newLp); + } + } + } + }; + synchronized(EthernetNetworkFactory.this) { stopIpManagerLocked(); - mIpManager = new IpManager(mContext, mIface, blockingCallback); + mIpManager = new IpManager(mContext, mIface, ipmCallback); + + if (config.getProxySettings() == ProxySettings.STATIC || + config.getProxySettings() == ProxySettings.PAC) { + mIpManager.setHttpProxy(config.getHttpProxy()); + } + + final String tcpBufferSizes = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_tcp_buffers); + if (!TextUtils.isEmpty(tcpBufferSizes)) { + mIpManager.setTcpBufferSizes(tcpBufferSizes); + } + mIpManager.startProvisioning(); } - linkProperties = blockingCallback.waitForProvisioning(); + + linkProperties = ipmCallback.waitForProvisioning(); if (linkProperties == null) { Log.e(TAG, "IP provisioning error"); // set our score lower than any network could go @@ -351,17 +345,6 @@ class EthernetNetworkFactory { } } - if (config.getProxySettings() == ProxySettings.STATIC || - config.getProxySettings() == ProxySettings.PAC) { - linkProperties.setHttpProxy(config.getHttpProxy()); - } - - final String tcpBufferSizes = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_tcp_buffers); - if (!TextUtils.isEmpty(tcpBufferSizes)) { - linkProperties.setTcpBufferSizes(tcpBufferSizes); - } - synchronized(EthernetNetworkFactory.this) { if (mNetworkAgent != null) { Log.e(TAG, "Already have a NetworkAgent - aborting new request"); From f485d9add1bd836d294d2331840be37210e01194 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 28 Apr 2016 01:24:21 +0900 Subject: [PATCH 016/881] Disable the IpManager timeout on Ethernet. This fixes a longstanding bug where after a DHCP timeout, we would never restart the DHCP client and get an IP address until the link bounced. Also, two minor improvements: 1. Dump IpManager info when dump() is called. 2. When onLinkPropertiesChange is called, also update mLinkProperties. We were already sending the updated LinkProperties to the NetworkAgent, so this is really only useful for dump(), but it's just one line and safe because onLinkPropertiesChange already grabs the lock. Bug: 17733693 Change-Id: I42c3319cb4bc151c547ed721baf5e83f97e23862 --- .../server/ethernet/EthernetNetworkFactory.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 718686344d..0b091f26b1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -33,6 +33,7 @@ import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.StaticIpConfiguration; import android.net.ip.IpManager; +import android.net.ip.IpManager.ProvisioningConfiguration; import android.net.ip.IpManager.WaitForProvisioningCallback; import android.os.Handler; import android.os.IBinder; @@ -283,7 +284,6 @@ class EthernetNetworkFactory { } } - // TODO: Handle DHCP renew. final Thread ipProvisioningThread = new Thread(new Runnable() { public void run() { if (DBG) { @@ -308,6 +308,7 @@ class EthernetNetworkFactory { public void onLinkPropertiesChange(LinkProperties newLp) { synchronized(EthernetNetworkFactory.this) { if (mNetworkAgent != null && mNetworkInfo.isConnected()) { + mLinkProperties = newLp; mNetworkAgent.sendLinkProperties(newLp); } } @@ -329,7 +330,11 @@ class EthernetNetworkFactory { mIpManager.setTcpBufferSizes(tcpBufferSizes); } - mIpManager.startProvisioning(); + final ProvisioningConfiguration provisioningConfiguration = + mIpManager.buildProvisioningConfiguration() + .withProvisioningTimeoutMs(0) + .build(); + mIpManager.startProvisioning(provisioningConfiguration); } linkProperties = ipmCallback.waitForProvisioning(); @@ -526,5 +531,11 @@ class EthernetNetworkFactory { pw.println("NetworkInfo: " + mNetworkInfo); pw.println("LinkProperties: " + mLinkProperties); pw.println("NetworkAgent: " + mNetworkAgent); + if (mIpManager != null) { + pw.println("IpManager:"); + pw.increaseIndent(); + mIpManager.dump(fd, pw, args); + pw.decreaseIndent(); + } } } From b9feffd1dd1b5abaf5699f2deeea99aa2da78300 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 29 Mar 2017 10:47:59 -0700 Subject: [PATCH 017/881] Change reserveSecurityParameterIndex() to take a remoteAddress To make the SPI reservation more semantically consistent with the transform creation API, and to ensure that we always create SPI reservations relative to a well-known remote, we should take the SPI request relative to a remote (rather than to a destination). This necessitates that we now consider direction separately, which is used for keying the SA-Id. Bug: 36073210 Test: compilation Change-Id: I81e955c20128c1f8e04fd68eb26669561f827a78 (cherry picked from commit 909d66e80a6d2170cbb5dee36f0e63bf0175c931) --- core/java/android/net/IpSecManager.java | 26 ++++++++++------------- core/java/android/net/IpSecTransform.java | 4 ++-- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 93a76dfbb4..83f4cc97b8 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -81,7 +81,7 @@ public final class IpSecManager { public static final class SecurityParameterIndex implements AutoCloseable { private final IIpSecService mService; - private final InetAddress mDestinationAddress; + private final InetAddress mRemoteAddress; private final CloseGuard mCloseGuard = CloseGuard.get(); private int mSpi; @@ -91,10 +91,10 @@ public final class IpSecManager { } private SecurityParameterIndex( - IIpSecService service, InetAddress destinationAddress, int spi) + IIpSecService service, int direction, InetAddress remoteAddress, int spi) throws ResourceUnavailableException, SpiUnavailableException { mService = service; - mDestinationAddress = destinationAddress; + mRemoteAddress = remoteAddress; mSpi = spi; mCloseGuard.open("open"); } @@ -102,13 +102,9 @@ public final class IpSecManager { /** * Release an SPI that was previously reserved. * - *

Release an SPI for use by other users in the system. This will fail if the SPI is - * currently in use by an IpSecTransform. - * - * @param destinationAddress SPIs must be unique for each combination of SPI and destination - * address. Thus, the destinationAddress to which the SPI will communicate must be - * supplied. - * @param spi the previously reserved SPI to be freed. + *

Release an SPI for use by other users in the system. If a SecurityParameterIndex is + * applied to an IpSecTransform, it will become unusable for future transforms but should + * still be closed to ensure system resources are released. */ @Override public void close() { @@ -134,13 +130,13 @@ public final class IpSecManager { public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; /** - * Reserve an SPI for traffic bound towards the specified destination address. + * Reserve an SPI for traffic bound towards the specified remote address. * *

If successful, this SPI is guaranteed available until released by a call to {@link * SecurityParameterIndex#close()}. * - * @param destinationAddress SPIs must be unique for each combination of SPI and destination - * address. + * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} + * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress. * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. * @return the reserved SecurityParameterIndex * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated @@ -148,9 +144,9 @@ public final class IpSecManager { * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved */ public SecurityParameterIndex reserveSecurityParameterIndex( - InetAddress destinationAddress, int requestedSpi) + int direction, InetAddress remoteAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { - return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); + return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi); } /** diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index d6dd28bec3..5c0bbe6a14 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -307,7 +307,7 @@ public final class IpSecTransform implements AutoCloseable { *

Care should be chosen when selecting an SPI to ensure that is is as unique as * possible. Random number generation is a reasonable approach to selecting an SPI. For * outbound SPIs, they must be reserved by calling {@link - * IpSecManager#reserveSecurityParameterIndex(InetAddress, int)}. Otherwise, Transforms will + * IpSecManager#reserveSecurityParameterIndex(int, InetAddress, int)}. Otherwise, Transforms will * fail to build. * *

Unless an SPI is set for a given direction, traffic in that direction will be @@ -329,7 +329,7 @@ public final class IpSecTransform implements AutoCloseable { *

Care should be chosen when selecting an SPI to ensure that is is as unique as * possible. Random number generation is a reasonable approach to selecting an SPI. For * outbound SPIs, they must be reserved by calling {@link - * IpSecManager#reserveSecurityParameterIndex(InetAddress, int)}. Otherwise, Transforms will + * IpSecManager#reserveSecurityParameterIndex(int, InetAddress, int)}. Otherwise, Transforms will * fail to activate. * *

Unless an SPI is set for a given direction, traffic in that direction will be From 4ee4a82e7ddbf90d3ad573af5d104c4152b937fc Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 30 Mar 2017 11:01:37 -0700 Subject: [PATCH 018/881] IpSecManager and IpSecTransform API Cleanup -Remove Int-based SPI usage from the IpSecTransform.Builder This is essentially a less-safe method overload, and it is both unnecessary and difficult to implement: the cross-validation between SPI and Transform is actually useful, and the kernel requires two different mechanisms to use an unreserved vs a reserved (alloc'd) SPI: CREATESA vs UPDATESA, which makes this hard to support. API Council has questioned the value of this, and they are right: everything points to "remove this". In the future, if we find that SPI reservation is overhead, we can always add it back. -Hiding the TunnelMode builder method and application/remove methods. These will not land by the time the next API stabilizes, so better to hide them now that this is a near-certainty. Expectation is to un-hide them in the subsequent API bump. Bug: 36073210 Test: Compilation, verified nobody is calling these stubs Change-Id: Ic1a3f2cf7128633318ac175d6b56b45eb8d21cab (cherry picked from commit 48b566557d5a66d4476008b3c59b815eb78cb373) --- core/java/android/net/IpSecManager.java | 2 -- core/java/android/net/IpSecTransform.java | 30 +++-------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 83f4cc97b8..3fcdb7e28c 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -197,7 +197,6 @@ public final class IpSecManager { * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform. * @hide */ - @SystemApi public void applyTunnelModeTransform(Network net, IpSecTransform transform) {} /** @@ -242,7 +241,6 @@ public final class IpSecManager { * network * @hide */ - @SystemApi public void removeTunnelModeTransform(Network net, IpSecTransform transform) {} /** diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 5c0bbe6a14..74d60106c0 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -305,32 +305,9 @@ public final class IpSecTransform implements AutoCloseable { * given destination address. * *

Care should be chosen when selecting an SPI to ensure that is is as unique as - * possible. Random number generation is a reasonable approach to selecting an SPI. For - * outbound SPIs, they must be reserved by calling {@link - * IpSecManager#reserveSecurityParameterIndex(int, InetAddress, int)}. Otherwise, Transforms will - * fail to build. - * - *

Unless an SPI is set for a given direction, traffic in that direction will be - * sent/received without any IPsec applied. - * - * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} - * @param spi a unique 32-bit integer to identify transformed traffic - */ - public IpSecTransform.Builder setSpi(@TransformDirection int direction, int spi) { - mConfig.flow[direction].spi = spi; - return this; - } - - /** - * Set the SPI, which uniquely identifies a particular IPsec session from others. Because - * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a - * given destination address. - * - *

Care should be chosen when selecting an SPI to ensure that is is as unique as - * possible. Random number generation is a reasonable approach to selecting an SPI. For - * outbound SPIs, they must be reserved by calling {@link - * IpSecManager#reserveSecurityParameterIndex(int, InetAddress, int)}. Otherwise, Transforms will - * fail to activate. + * possible. To reserve a value call {@link IpSecManager#reserveSecurityParameterIndex(int, + * InetAddress, int)}. Otherwise, SPI collisions would prevent a transform from being + * activated. IpSecManager#reserveSecurityParameterIndex(int, InetAddres$s, int)}. * *

Unless an SPI is set for a given direction, traffic in that direction will be * sent/received without any IPsec applied. @@ -447,7 +424,6 @@ public final class IpSecTransform implements AutoCloseable { * properties is invalid. * @hide */ - @SystemApi public IpSecTransform buildTunnelModeTransform( InetAddress localAddress, InetAddress remoteAddress) { //FIXME: argument validation here From 2af3baeddc5f43ba6602e25101a3f1593a66dd95 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 7 Mar 2017 13:23:36 -0800 Subject: [PATCH 019/881] Add Initial IPsec APIs to IpSecService -Plumb IpSecManager APIs to NetD -Add Resource Management to IpSecService Bug: 30984788 Test: b/34812052, b/34811227 Change-Id: Ic43965c6158f28cac53810adbf5cf50d2c54f920 (cherry picked from commit 93962f34ce21f5aac825afbcebf2f3e8c7a30910) --- core/java/android/net/IIpSecService.aidl | 22 + core/java/android/net/IpSecAlgorithm.java | 2 + core/java/android/net/IpSecConfig.java | 70 ++-- core/java/android/net/IpSecManager.java | 112 ++++- core/java/android/net/IpSecTransform.java | 141 ++++--- .../java/com/android/server/IpSecService.java | 396 +++++++++++++++++- 6 files changed, 619 insertions(+), 124 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index b8737fef72..0aa3ce66eb 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -16,9 +16,31 @@ package android.net; +import android.net.Network; +import android.net.IpSecConfig; +import android.os.Bundle; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; + /** * @hide */ interface IIpSecService { + Bundle reserveSecurityParameterIndex( + int direction, in String remoteAddress, int requestedSpi, in IBinder binder); + + void releaseSecurityParameterIndex(int resourceId); + + Bundle openUdpEncapsulationSocket(int port, in IBinder binder); + + void closeUdpEncapsulationSocket(in ParcelFileDescriptor socket); + + Bundle createTransportModeTransform(in IpSecConfig c, in IBinder binder); + + void deleteTransportModeTransform(int transformId); + + void applyTransportModeTransform(in ParcelFileDescriptor socket, int transformId); + + void removeTransportModeTransform(in ParcelFileDescriptor socket, int transformId); } diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index da5cb37961..7fea4a25ca 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -164,6 +164,8 @@ public final class IpSecAlgorithm implements Parcelable { private static boolean isTruncationLengthValid(String algo, int truncLenBits) { switch (algo) { + case ALGO_CRYPT_AES_CBC: + return (truncLenBits == 128 || truncLenBits == 192 || truncLenBits == 256); case ALGO_AUTH_HMAC_MD5: return (truncLenBits >= 96 && truncLenBits <= 128); case ALGO_AUTH_HMAC_SHA1: diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index b58bf421a8..13dc19f685 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -23,7 +23,7 @@ import java.net.UnknownHostException; /** @hide */ public final class IpSecConfig implements Parcelable { - private static final String TAG = IpSecConfig.class.getSimpleName(); + private static final String TAG = "IpSecConfig"; //MODE_TRANSPORT or MODE_TUNNEL int mode; @@ -43,13 +43,13 @@ public final class IpSecConfig implements Parcelable { int spi; // Encryption Algorithm - IpSecAlgorithm encryptionAlgo; + IpSecAlgorithm encryption; // Authentication Algorithm - IpSecAlgorithm authenticationAlgo; + IpSecAlgorithm authentication; } - Flow[] flow = new Flow[2]; + Flow[] flow = new Flow[] {new Flow(), new Flow()}; // For tunnel mode IPv4 UDP Encapsulation // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE @@ -57,17 +57,15 @@ public final class IpSecConfig implements Parcelable { int encapLocalPort; int encapRemotePort; - // An optional protocol to match with the selector - int selectorProto; - - // A bitmask of FEATURE_* indicating which of the fields - // of this class are valid. - long features; - // An interval, in seconds between the NattKeepalive packets int nattKeepaliveInterval; - public InetAddress getLocalIp() { + // Transport or Tunnel + public int getMode() { + return mode; + } + + public InetAddress getLocalAddress() { return localAddress; } @@ -75,19 +73,19 @@ public final class IpSecConfig implements Parcelable { return flow[direction].spi; } - public InetAddress getRemoteIp() { + public InetAddress getRemoteAddress() { return remoteAddress; } - public IpSecAlgorithm getEncryptionAlgo(int direction) { - return flow[direction].encryptionAlgo; + public IpSecAlgorithm getEncryption(int direction) { + return flow[direction].encryption; } - public IpSecAlgorithm getAuthenticationAlgo(int direction) { - return flow[direction].authenticationAlgo; + public IpSecAlgorithm getAuthentication(int direction) { + return flow[direction].authentication; } - Network getNetwork() { + public Network getNetwork() { return network; } @@ -103,18 +101,10 @@ public final class IpSecConfig implements Parcelable { return encapRemotePort; } - public int getSelectorProto() { - return selectorProto; - } - - int getNattKeepaliveInterval() { + public int getNattKeepaliveInterval() { return nattKeepaliveInterval; } - public boolean hasProperty(int featureBits) { - return (features & featureBits) == featureBits; - } - // Parcelable Methods @Override @@ -124,31 +114,25 @@ public final class IpSecConfig implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - out.writeLong(features); // TODO: Use a byte array or other better method for storing IPs that can also include scope out.writeString((localAddress != null) ? localAddress.getHostAddress() : null); // TODO: Use a byte array or other better method for storing IPs that can also include scope out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null); out.writeParcelable(network, flags); out.writeInt(flow[IpSecTransform.DIRECTION_IN].spi); - out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryptionAlgo, flags); - out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authenticationAlgo, flags); + out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags); + out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags); out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spi); - out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryptionAlgo, flags); - out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authenticationAlgo, flags); + out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags); + out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags); out.writeInt(encapType); out.writeInt(encapLocalPort); out.writeInt(encapRemotePort); - out.writeInt(selectorProto); } // Package Private: Used by the IpSecTransform.Builder; // there should be no public constructor for this object - IpSecConfig() { - flow[IpSecTransform.DIRECTION_IN].spi = 0; - flow[IpSecTransform.DIRECTION_OUT].spi = 0; - nattKeepaliveInterval = 0; //FIXME constant - } + IpSecConfig() {} private static InetAddress readInetAddressFromParcel(Parcel in) { String addrString = in.readString(); @@ -164,24 +148,22 @@ public final class IpSecConfig implements Parcelable { } private IpSecConfig(Parcel in) { - features = in.readLong(); localAddress = readInetAddressFromParcel(in); remoteAddress = readInetAddressFromParcel(in); network = (Network) in.readParcelable(Network.class.getClassLoader()); flow[IpSecTransform.DIRECTION_IN].spi = in.readInt(); - flow[IpSecTransform.DIRECTION_IN].encryptionAlgo = + flow[IpSecTransform.DIRECTION_IN].encryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_IN].authenticationAlgo = + flow[IpSecTransform.DIRECTION_IN].authentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); flow[IpSecTransform.DIRECTION_OUT].spi = in.readInt(); - flow[IpSecTransform.DIRECTION_OUT].encryptionAlgo = + flow[IpSecTransform.DIRECTION_OUT].encryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_OUT].authenticationAlgo = + flow[IpSecTransform.DIRECTION_OUT].authentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); encapType = in.readInt(); encapLocalPort = in.readInt(); encapRemotePort = in.readInt(); - selectorProto = in.readInt(); } public static final Parcelable.Creator CREATOR = diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 3fcdb7e28c..6852beb065 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -17,8 +17,11 @@ package android.net; import static com.android.internal.util.Preconditions.checkNotNull; -import android.annotation.SystemApi; +import android.annotation.NonNull; +import android.os.Binder; +import android.os.Bundle; import android.os.ParcelFileDescriptor; +import android.os.RemoteException; import android.util.AndroidException; import dalvik.system.CloseGuard; import java.io.FileDescriptor; @@ -38,6 +41,29 @@ import java.net.Socket; public final class IpSecManager { private static final String TAG = "IpSecManager"; + /** + * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index. + * + *

No IPsec packet may contain an SPI of 0. + */ + public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; + + /** @hide */ + public interface Status { + public static final int OK = 0; + public static final int RESOURCE_UNAVAILABLE = 1; + public static final int SPI_UNAVAILABLE = 2; + } + + /** @hide */ + public static final String KEY_STATUS = "status"; + /** @hide */ + public static final String KEY_RESOURCE_ID = "resourceId"; + /** @hide */ + public static final String KEY_SPI = "spi"; + /** @hide */ + public static final int INVALID_RESOURCE_ID = 0; + /** * Indicates that the combination of remote InetAddress and SPI was non-unique for a given * request. If encountered, selection of a new SPI is required before a transform may be @@ -83,22 +109,14 @@ public final class IpSecManager { private final IIpSecService mService; private final InetAddress mRemoteAddress; private final CloseGuard mCloseGuard = CloseGuard.get(); - private int mSpi; + private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; + private int mResourceId; /** Return the underlying SPI held by this object */ public int getSpi() { return mSpi; } - private SecurityParameterIndex( - IIpSecService service, int direction, InetAddress remoteAddress, int spi) - throws ResourceUnavailableException, SpiUnavailableException { - mService = service; - mRemoteAddress = remoteAddress; - mSpi = spi; - mCloseGuard.open("open"); - } - /** * Release an SPI that was previously reserved. * @@ -108,7 +126,7 @@ public final class IpSecManager { */ @Override public void close() { - mSpi = INVALID_SECURITY_PARAMETER_INDEX; // TODO: Invalid SPI + mSpi = INVALID_SECURITY_PARAMETER_INDEX; mCloseGuard.close(); } @@ -120,14 +138,52 @@ public final class IpSecManager { close(); } - } - /** - * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index. - * - *

No IPsec packet may contain an SPI of 0. - */ - public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; + private SecurityParameterIndex( + @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi) + throws ResourceUnavailableException, SpiUnavailableException { + mService = service; + mRemoteAddress = remoteAddress; + try { + Bundle result = + mService.reserveSecurityParameterIndex( + direction, remoteAddress.getHostAddress(), spi, new Binder()); + + if (result == null) { + throw new NullPointerException("Received null response from IpSecService"); + } + + int status = result.getInt(KEY_STATUS); + switch (status) { + case Status.OK: + break; + case Status.RESOURCE_UNAVAILABLE: + throw new ResourceUnavailableException( + "No more SPIs may be allocated by this requester."); + case Status.SPI_UNAVAILABLE: + throw new SpiUnavailableException("Requested SPI is unavailable", spi); + default: + throw new RuntimeException( + "Unknown status returned by IpSecService: " + status); + } + mSpi = result.getInt(KEY_SPI); + mResourceId = result.getInt(KEY_RESOURCE_ID); + + if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) { + throw new RuntimeException("Invalid SPI returned by IpSecService: " + status); + } + + if (mResourceId == INVALID_RESOURCE_ID) { + throw new RuntimeException( + "Invalid Resource ID returned by IpSecService: " + status); + } + + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + mCloseGuard.open("open"); + } + } /** * Reserve an SPI for traffic bound towards the specified remote address. @@ -184,7 +240,13 @@ public final class IpSecManager { } /* Call down to activate a transform */ - private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {} + private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { + try { + mService.applyTransportModeTransform(pfd, transform.getResourceId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } /** * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to @@ -228,7 +290,13 @@ public final class IpSecManager { } /* Call down to activate a transform */ - private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) {} + private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { + try { + mService.removeTransportModeTransform(pfd, transform.getResourceId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } /** * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of @@ -255,7 +323,7 @@ public final class IpSecManager { private final IIpSecService mService; private final CloseGuard mCloseGuard = CloseGuard.get(); - private UdpEncapsulationSocket(IIpSecService service, int port) + private UdpEncapsulationSocket(@NonNull IIpSecService service, int port) throws ResourceUnavailableException { mService = service; mCloseGuard.open("constructor"); diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 74d60106c0..801e98c7b1 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -15,11 +15,21 @@ */ package android.net; +import static android.net.IpSecManager.INVALID_RESOURCE_ID; +import static android.net.IpSecManager.KEY_RESOURCE_ID; +import static android.net.IpSecManager.KEY_STATUS; + import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.Context; -import android.system.ErrnoException; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; +import com.android.internal.util.Preconditions; import dalvik.system.CloseGuard; import java.io.IOException; import java.lang.annotation.Retention; @@ -86,39 +96,64 @@ public final class IpSecTransform implements AutoCloseable { @Retention(RetentionPolicy.SOURCE) public @interface EncapType {} - /** - * Sentinel for an invalid transform (means that this transform is inactive). - * - * @hide - */ - public static final int INVALID_TRANSFORM_ID = -1; - private IpSecTransform(Context context, IpSecConfig config) { mContext = context; mConfig = config; - mTransformId = INVALID_TRANSFORM_ID; + mResourceId = INVALID_RESOURCE_ID; + } + + private IIpSecService getIpSecService() { + IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE); + if (b == null) { + throw new RemoteException("Failed to connect to IpSecService") + .rethrowAsRuntimeException(); + } + + return IIpSecService.Stub.asInterface(b); + } + + private void checkResultStatusAndThrow(int status) + throws IOException, IpSecManager.ResourceUnavailableException, + IpSecManager.SpiUnavailableException { + switch (status) { + case IpSecManager.Status.OK: + return; + // TODO: Pass Error string back from bundle so that errors can be more specific + case IpSecManager.Status.RESOURCE_UNAVAILABLE: + throw new IpSecManager.ResourceUnavailableException( + "Failed to allocate a new IpSecTransform"); + case IpSecManager.Status.SPI_UNAVAILABLE: + Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved"); + // Fall through + default: + throw new IllegalStateException( + "Failed to Create a Transform with status code " + status); + } } private IpSecTransform activate() throws IOException, IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException { - int transformId; synchronized (this) { - //try { - transformId = INVALID_TRANSFORM_ID; - //} catch (RemoteException e) { - // throw e.rethrowFromSystemServer(); - //} + try { + IIpSecService svc = getIpSecService(); + Bundle result = svc.createTransportModeTransform(mConfig, new Binder()); + int status = result.getInt(KEY_STATUS); + checkResultStatusAndThrow(status); + mResourceId = result.getInt(KEY_RESOURCE_ID, INVALID_RESOURCE_ID); - if (transformId < 0) { - throw new ErrnoException("addTransform", -transformId).rethrowAsIOException(); + /* Keepalive will silently fail if not needed by the config; but, if needed and + * it fails to start, we need to bail because a transform will not be reliable + * to use if keepalive is expected to offload and fails. + */ + // FIXME: if keepalive fails, we need to fail spectacularly + startKeepalive(mContext); + Log.d(TAG, "Added Transform with Id " + mResourceId); + mCloseGuard.open("build"); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); } - - startKeepalive(mContext); // Will silently fail if not required - mTransformId = transformId; - Log.d(TAG, "Added Transform with Id " + transformId); } - mCloseGuard.open("build"); return this; } @@ -133,21 +168,27 @@ public final class IpSecTransform implements AutoCloseable { * transform is no longer needed. */ public void close() { - Log.d(TAG, "Removing Transform with Id " + mTransformId); + Log.d(TAG, "Removing Transform with Id " + mResourceId); // Always safe to attempt cleanup - if (mTransformId == INVALID_TRANSFORM_ID) { + if (mResourceId == INVALID_RESOURCE_ID) { + mCloseGuard.close(); return; } - //try { - stopKeepalive(); - //} catch (RemoteException e) { - // transform.setTransformId(transformId); - // throw e.rethrowFromSystemServer(); - //} finally { - mTransformId = INVALID_TRANSFORM_ID; - //} - mCloseGuard.close(); + try { + /* Order matters here because the keepalive is best-effort but could fail in some + * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we + * still want to clear out the transform. + */ + IIpSecService svc = getIpSecService(); + svc.deleteTransportModeTransform(mResourceId); + stopKeepalive(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); + } } @Override @@ -164,7 +205,7 @@ public final class IpSecTransform implements AutoCloseable { } private final IpSecConfig mConfig; - private int mTransformId; + private int mResourceId; private final Context mContext; private final CloseGuard mCloseGuard = CloseGuard.get(); private ConnectivityManager.PacketKeepalive mKeepalive; @@ -200,6 +241,7 @@ public final class IpSecTransform implements AutoCloseable { /* Package */ void startKeepalive(Context c) { + // FIXME: NO_KEEPALIVE needs to be a constant if (mConfig.getNattKeepaliveInterval() == 0) { return; } @@ -208,7 +250,7 @@ public final class IpSecTransform implements AutoCloseable { (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); if (mKeepalive != null) { - Log.e(TAG, "Keepalive already started for this IpSecTransform."); + Log.wtf(TAG, "Keepalive already started for this IpSecTransform."); return; } @@ -218,10 +260,11 @@ public final class IpSecTransform implements AutoCloseable { mConfig.getNetwork(), mConfig.getNattKeepaliveInterval(), mKeepaliveCallback, - mConfig.getLocalIp(), + mConfig.getLocalAddress(), mConfig.getEncapLocalPort(), - mConfig.getRemoteIp()); + mConfig.getRemoteAddress()); try { + // FIXME: this is still a horrible way to fudge the synchronous callback mKeepaliveSyncLock.wait(2000); } catch (InterruptedException e) { } @@ -231,6 +274,11 @@ public final class IpSecTransform implements AutoCloseable { } } + /* Package */ + int getResourceId() { + return mResourceId; + } + /* Package */ void stopKeepalive() { if (mKeepalive == null) { @@ -247,16 +295,6 @@ public final class IpSecTransform implements AutoCloseable { } } - /* Package */ - void setTransformId(int transformId) { - mTransformId = transformId; - } - - /* Package */ - int getTransformId() { - return mTransformId; - } - /** * Builder object to facilitate the creation of IpSecTransform objects. * @@ -280,7 +318,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setEncryption( @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.flow[direction].encryptionAlgo = algo; + mConfig.flow[direction].encryption = algo; return this; } @@ -295,7 +333,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setAuthentication( @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.flow[direction].authenticationAlgo = algo; + mConfig.flow[direction].authentication = algo; return this; } @@ -318,6 +356,8 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setSpi( @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) { + // TODO: convert to using the resource Id of the SPI. Then build() can validate + // the owner in the IpSecService mConfig.flow[direction].spi = spi.getSpi(); return this; } @@ -439,7 +479,8 @@ public final class IpSecTransform implements AutoCloseable { * * @param context current Context */ - public Builder(Context context) { + public Builder(@NonNull Context context) { + Preconditions.checkNotNull(context); mContext = context; mConfig = new IpSecConfig(); } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 994adc480f..a7ce95ba0c 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -17,23 +17,40 @@ package com.android.server; import static android.Manifest.permission.DUMP; +import static android.net.IpSecManager.INVALID_RESOURCE_ID; +import static android.net.IpSecManager.KEY_RESOURCE_ID; +import static android.net.IpSecManager.KEY_SPI; +import static android.net.IpSecManager.KEY_STATUS; import android.content.Context; import android.net.IIpSecService; import android.net.INetd; +import android.net.IpSecAlgorithm; +import android.net.IpSecConfig; +import android.net.IpSecManager; +import android.net.IpSecTransform; import android.net.util.NetdService; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.util.Log; import android.util.Slog; - +import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.concurrent.atomic.AtomicInteger; /** @hide */ public class IpSecService extends IIpSecService.Stub { private static final String TAG = "IpSecService"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final String NETD_SERVICE_NAME = "netd"; + private static final int[] DIRECTIONS = + new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN}; /** Binder context for this service */ private final Context mContext; @@ -42,6 +59,159 @@ public class IpSecService extends IIpSecService.Stub { private static final int NETD_FETCH_TIMEOUT = 5000; //ms + private AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); + + private abstract class ManagedResource implements IBinder.DeathRecipient { + final int pid; + final int uid; + private IBinder mBinder; + + ManagedResource(IBinder binder) { + super(); + mBinder = binder; + pid = Binder.getCallingPid(); + uid = Binder.getCallingUid(); + + try { + mBinder.linkToDeath(this, 0); + } catch (RemoteException e) { + binderDied(); + } + } + + /** + * When this record is no longer needed for managing system resources this function should + * unlink all references held by the record to allow efficient garbage collection. + */ + public final void release() { + //Release all the underlying system resources first + releaseResources(); + + if (mBinder != null) { + mBinder.unlinkToDeath(this, 0); + } + mBinder = null; + + //remove this record so that it can be cleaned up + nullifyRecord(); + } + + /** + * If the Binder object dies, this function is called to free the system resources that are + * being managed by this record and to subsequently release this record for garbage + * collection + */ + public final void binderDied() { + release(); + } + + /** + * Implement this method to release all object references contained in the subclass to allow + * efficient garbage collection of the record. This should remove any references to the + * record from all other locations that hold a reference as the record is no longer valid. + */ + protected abstract void nullifyRecord(); + + /** + * Implement this method to release all system resources that are being protected by this + * record. Once the resources are released, the record should be invalidated and no longer + * used by calling releaseRecord() + */ + protected abstract void releaseResources(); + }; + + private final class TransformRecord extends ManagedResource { + private IpSecConfig mConfig; + private int mResourceId; + + TransformRecord(IpSecConfig config, int resourceId, IBinder binder) { + super(binder); + mConfig = config; + mResourceId = resourceId; + } + + public IpSecConfig getConfig() { + return mConfig; + } + + @Override + protected void releaseResources() { + for (int direction : DIRECTIONS) { + try { + getNetdInstance() + .ipSecDeleteSecurityAssociation( + mResourceId, + direction, + (mConfig.getLocalAddress() != null) + ? mConfig.getLocalAddress().getHostAddress() + : "", + (mConfig.getRemoteAddress() != null) + ? mConfig.getRemoteAddress().getHostAddress() + : "", + mConfig.getSpi(direction)); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (RemoteException e) { + Log.e(TAG, "Failed to delete SA with ID: " + mResourceId); + } + } + } + + @Override + protected void nullifyRecord() { + mConfig = null; + mResourceId = INVALID_RESOURCE_ID; + } + } + + private final class SpiRecord extends ManagedResource { + private final int mDirection; + private final String mLocalAddress; + private final String mRemoteAddress; + private final IBinder mBinder; + private int mSpi; + private int mResourceId; + + SpiRecord( + int resourceId, + int direction, + String localAddress, + String remoteAddress, + int spi, + IBinder binder) { + super(binder); + mResourceId = resourceId; + mDirection = direction; + mLocalAddress = localAddress; + mRemoteAddress = remoteAddress; + mSpi = spi; + mBinder = binder; + } + + protected void releaseResources() { + try { + getNetdInstance() + .ipSecDeleteSecurityAssociation( + mResourceId, mDirection, mLocalAddress, mRemoteAddress, mSpi); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (RemoteException e) { + Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId); + } + } + + protected void nullifyRecord() { + mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; + mResourceId = INVALID_RESOURCE_ID; + } + } + + @GuardedBy("mSpiRecords") + private final SparseArray mSpiRecords = new SparseArray<>(); + + @GuardedBy("mTransformRecords") + private final SparseArray mTransformRecords = new SparseArray<>(); + /** * Constructs a new IpSecService instance * @@ -80,22 +250,21 @@ public class IpSecService extends IIpSecService.Stub { t.run(); } - INetd getNetdInstance() { + INetd getNetdInstance() throws RemoteException { final INetd netd = NetdService.getInstance(); if (netd == null) { - throw new RemoteException("Failed to Get Netd Instance").rethrowFromSystemServer(); + throw new RemoteException("Failed to Get Netd Instance"); } return netd; } boolean isNetdAlive() { synchronized (mLock) { - final INetd netd = getNetdInstance(); - if (netd == null) { - return false; - } - try { + final INetd netd = getNetdInstance(); + if (netd == null) { + return false; + } return netd.isAlive(); } catch (RemoteException re) { return false; @@ -103,6 +272,217 @@ public class IpSecService extends IIpSecService.Stub { } } + @Override + /** Get a new SPI and maintain the reservation in the system server */ + public Bundle reserveSecurityParameterIndex( + int direction, String remoteAddress, int requestedSpi, IBinder binder) + throws RemoteException { + int resourceId = mNextResourceId.getAndIncrement(); + + int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; + String localAddress = ""; + Bundle retBundle = new Bundle(3); + try { + spi = + getNetdInstance() + .ipSecAllocateSpi( + resourceId, + direction, + localAddress, + remoteAddress, + requestedSpi); + Log.d(TAG, "Allocated SPI " + spi); + retBundle.putInt(KEY_STATUS, IpSecManager.Status.OK); + retBundle.putInt(KEY_RESOURCE_ID, resourceId); + retBundle.putInt(KEY_SPI, spi); + synchronized (mSpiRecords) { + mSpiRecords.put( + resourceId, + new SpiRecord( + resourceId, direction, localAddress, remoteAddress, spi, binder)); + } + } catch (ServiceSpecificException e) { + // TODO: Add appropriate checks when other ServiceSpecificException types are supported + retBundle.putInt(KEY_STATUS, IpSecManager.Status.SPI_UNAVAILABLE); + retBundle.putInt(KEY_RESOURCE_ID, resourceId); + retBundle.putInt(KEY_SPI, spi); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return retBundle; + } + + /** Release a previously allocated SPI that has been registered with the system server */ + @Override + public void releaseSecurityParameterIndex(int resourceId) throws RemoteException {} + + /** + * Open a socket via the system server and bind it to the specified port (random if port=0). + * This will return a PFD to the user that represent a bound UDP socket. The system server will + * cache the socket and a record of its owner so that it can and must be freed when no longer + * needed. + */ + @Override + public Bundle openUdpEncapsulationSocket(int port, IBinder binder) throws RemoteException { + return null; + } + + /** close a socket that has been been allocated by and registered with the system server */ + @Override + public void closeUdpEncapsulationSocket(ParcelFileDescriptor socket) {} + + /** + * Create a transport mode transform, which represent two security associations (one in each + * direction) in the kernel. The transform will be cached by the system server and must be freed + * when no longer needed. It is possible to free one, deleting the SA from underneath sockets + * that are using it, which will result in all of those sockets becoming unable to send or + * receive data. + */ + @Override + public Bundle createTransportModeTransform(IpSecConfig c, IBinder binder) + throws RemoteException { + // TODO: Basic input validation here since it's coming over the Binder + int resourceId = mNextResourceId.getAndIncrement(); + for (int direction : DIRECTIONS) { + IpSecAlgorithm auth = c.getAuthentication(direction); + IpSecAlgorithm crypt = c.getEncryption(direction); + try { + int result = + getNetdInstance() + .ipSecAddSecurityAssociation( + resourceId, + c.getMode(), + direction, + (c.getLocalAddress() != null) + ? c.getLocalAddress().getHostAddress() + : "", + (c.getRemoteAddress() != null) + ? c.getRemoteAddress().getHostAddress() + : "", + (c.getNetwork() != null) + ? c.getNetwork().getNetworkHandle() + : 0, + c.getSpi(direction), + (auth != null) ? auth.getName() : "", + (auth != null) ? auth.getKey() : null, + (auth != null) ? auth.getTruncationLengthBits() : 0, + (crypt != null) ? crypt.getName() : "", + (crypt != null) ? crypt.getKey() : null, + (crypt != null) ? crypt.getTruncationLengthBits() : 0, + c.getEncapType(), + c.getEncapLocalPort(), + c.getEncapRemotePort()); + if (result != c.getSpi(direction)) { + // TODO: cleanup the first SA if creation of second SA fails + Bundle retBundle = new Bundle(2); + retBundle.putInt(KEY_STATUS, IpSecManager.Status.SPI_UNAVAILABLE); + retBundle.putInt(KEY_RESOURCE_ID, INVALID_RESOURCE_ID); + return retBundle; + } + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } + } + synchronized (mTransformRecords) { + mTransformRecords.put(resourceId, new TransformRecord(c, resourceId, binder)); + } + + Bundle retBundle = new Bundle(2); + retBundle.putInt(KEY_STATUS, IpSecManager.Status.OK); + retBundle.putInt(KEY_RESOURCE_ID, resourceId); + return retBundle; + } + + /** + * Delete a transport mode transform that was previously allocated by + registered with the + * system server. If this is called on an inactive (or non-existent) transform, it will not + * return an error. It's safe to de-allocate transforms that may have already been deleted for + * other reasons. + */ + @Override + public void deleteTransportModeTransform(int resourceId) throws RemoteException { + synchronized (mTransformRecords) { + TransformRecord record; + // We want to non-destructively get so that we can check credentials before removing + // this from the records. + record = mTransformRecords.get(resourceId); + + if (record == null) { + throw new IllegalArgumentException( + "Transform " + resourceId + " is not available to be deleted"); + } + + if (record.pid != Binder.getCallingPid() || record.uid != Binder.getCallingUid()) { + throw new SecurityException("Only the owner of an IpSec Transform may delete it!"); + } + + // TODO: if releaseResources() throws RemoteException, we can try again to clean up on + // binder death. Need to make sure that path is actually functional. + record.releaseResources(); + mTransformRecords.remove(resourceId); + record.nullifyRecord(); + } + } + + /** + * Apply an active transport mode transform to a socket, which will apply the IPsec security + * association as a correspondent policy to the provided socket + */ + @Override + public void applyTransportModeTransform(ParcelFileDescriptor socket, int resourceId) + throws RemoteException { + + synchronized (mTransformRecords) { + TransformRecord info; + // FIXME: this code should be factored out into a security check + getter + info = mTransformRecords.get(resourceId); + + if (info == null) { + throw new IllegalArgumentException("Transform " + resourceId + " is not active"); + } + + // TODO: make this a function. + if (info.pid != getCallingPid() || info.uid != getCallingUid()) { + throw new SecurityException("Only the owner of an IpSec Transform may apply it!"); + } + + IpSecConfig c = info.getConfig(); + try { + for (int direction : DIRECTIONS) { + getNetdInstance() + .ipSecApplyTransportModeTransform( + socket.getFileDescriptor(), + resourceId, + direction, + (c.getLocalAddress() != null) + ? c.getLocalAddress().getHostAddress() + : "", + (c.getRemoteAddress() != null) + ? c.getRemoteAddress().getHostAddress() + : "", + c.getSpi(direction)); + } + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } + } + } + /** + * Remove a transport mode transform from a socket, applying the default (empty) policy. This + * will ensure that NO IPsec policy is applied to the socket (would be the equivalent of + * applying a policy that performs no IPsec). Today the resourceId parameter is passed but not + * used: reserved for future improved input validation. + */ + @Override + public void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId) + throws RemoteException { + try { + getNetdInstance().ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); From 0560678b89cf5f24a30de87d5650abb76333725d Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 6 Apr 2017 18:16:28 -0700 Subject: [PATCH 020/881] IpSecManager and IpSecAlgorithm API Tweaks -Add a reserveSecurityParamterIndex() function that allows the system to select an SPI. -Disallow INVALID_SECURITY_PARAMETER_INDEX from being passed as an explicit SPI request. -Remove the ALGO_ prefix from constants in IpSecAlgorithm Bug: 36073210 Test: Updated CTS tests still pass on bullhead Change-Id: Ic94809996076b0718f153f550b82192fe7048a2e --- core/java/android/net/IpSecAlgorithm.java | 34 +++++++++++------------ core/java/android/net/IpSecManager.java | 31 ++++++++++++++++++++- 2 files changed, 47 insertions(+), 18 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 7fea4a25ca..ce7894fb3b 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -32,7 +32,7 @@ public final class IpSecAlgorithm implements Parcelable { * *

Valid lengths for this key are {128, 192, 256}. */ - public static final String ALGO_CRYPT_AES_CBC = "cbc(aes)"; + public static final String CRYPT_AES_CBC = "cbc(aes)"; /** * MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in new @@ -40,7 +40,7 @@ public final class IpSecAlgorithm implements Parcelable { * *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 128. */ - public static final String ALGO_AUTH_HMAC_MD5 = "hmac(md5)"; + public static final String AUTH_HMAC_MD5 = "hmac(md5)"; /** * SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in @@ -48,35 +48,35 @@ public final class IpSecAlgorithm implements Parcelable { * *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 160. */ - public static final String ALGO_AUTH_HMAC_SHA1 = "hmac(sha1)"; + public static final String AUTH_HMAC_SHA1 = "hmac(sha1)"; /** * SHA256 HMAC Authentication/Integrity Algorithm. * *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 256. */ - public static final String ALGO_AUTH_HMAC_SHA256 = "hmac(sha256)"; + public static final String AUTH_HMAC_SHA256 = "hmac(sha256)"; /** * SHA384 HMAC Authentication/Integrity Algorithm. * *

Valid truncation lengths are multiples of 8 bits from 192 to (default) 384. */ - public static final String ALGO_AUTH_HMAC_SHA384 = "hmac(sha384)"; + public static final String AUTH_HMAC_SHA384 = "hmac(sha384)"; /** * SHA512 HMAC Authentication/Integrity Algorithm * *

Valid truncation lengths are multiples of 8 bits from 256 to (default) 512. */ - public static final String ALGO_AUTH_HMAC_SHA512 = "hmac(sha512)"; + public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; /** @hide */ @StringDef({ - ALGO_CRYPT_AES_CBC, - ALGO_AUTH_HMAC_MD5, - ALGO_AUTH_HMAC_SHA1, - ALGO_AUTH_HMAC_SHA256, - ALGO_AUTH_HMAC_SHA512 + CRYPT_AES_CBC, + AUTH_HMAC_MD5, + AUTH_HMAC_SHA1, + AUTH_HMAC_SHA256, + AUTH_HMAC_SHA512 }) @Retention(RetentionPolicy.SOURCE) public @interface AlgorithmName {} @@ -164,17 +164,17 @@ public final class IpSecAlgorithm implements Parcelable { private static boolean isTruncationLengthValid(String algo, int truncLenBits) { switch (algo) { - case ALGO_CRYPT_AES_CBC: + case CRYPT_AES_CBC: return (truncLenBits == 128 || truncLenBits == 192 || truncLenBits == 256); - case ALGO_AUTH_HMAC_MD5: + case AUTH_HMAC_MD5: return (truncLenBits >= 96 && truncLenBits <= 128); - case ALGO_AUTH_HMAC_SHA1: + case AUTH_HMAC_SHA1: return (truncLenBits >= 96 && truncLenBits <= 160); - case ALGO_AUTH_HMAC_SHA256: + case AUTH_HMAC_SHA256: return (truncLenBits >= 96 && truncLenBits <= 256); - case ALGO_AUTH_HMAC_SHA384: + case AUTH_HMAC_SHA384: return (truncLenBits >= 192 && truncLenBits <= 384); - case ALGO_AUTH_HMAC_SHA512: + case AUTH_HMAC_SHA512: return (truncLenBits >= 256 && truncLenBits <= 512); default: return false; diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 6852beb065..4bfeb096df 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -193,15 +193,44 @@ public final class IpSecManager { * * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress. - * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. * @return the reserved SecurityParameterIndex * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated * for this user * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved */ + public SecurityParameterIndex reserveSecurityParameterIndex( + int direction, InetAddress remoteAddress) + throws ResourceUnavailableException { + try { + return new SecurityParameterIndex( + mService, + direction, + remoteAddress, + IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); + } catch (SpiUnavailableException unlikely) { + throw new ResourceUnavailableException("No SPIs available"); + } + } + + /** + * Reserve an SPI for traffic bound towards the specified remote address. + * + *

If successful, this SPI is guaranteed available until released by a call to {@link + * SecurityParameterIndex#close()}. + * + * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} + * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress. + * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. + * @return the reserved SecurityParameterIndex + * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated + * for this user + */ public SecurityParameterIndex reserveSecurityParameterIndex( int direction, InetAddress remoteAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { + if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { + throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); + } return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi); } From 04a11e02a90733be8ceb24f8c39624a3df7775f6 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 6 Apr 2017 17:46:00 -0700 Subject: [PATCH 021/881] Add FileDescriptor Versions of applyTransportModeTransform() Because there is no way using the Java sockets API to actually get a socket of AF_INET on mode machines, it is necessary to provide a way to apply transforms to sockets made using the native wrapper API, which uses POSIX APIs and will create a socket that is AF_INET. Bug: 36073210 Test: b/34811227 Change-Id: I28ac7cc4f36045ce523a54111e5be975b0331356 --- core/java/android/net/IpSecManager.java | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 4bfeb096df..f8702e2e00 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -277,6 +277,23 @@ public final class IpSecManager { } } + /** + * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec + * encapsulation of the traffic flowing between the socket and the remote InetAddress of that + * transform. For security reasons, attempts to send traffic to any IP address other than the + * address associated with that transform will throw an IOException. In addition, if the + * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to + * send() or receive() until the transform is removed from the socket by calling {@link + * #removeTransportModeTransform(Socket, IpSecTransform)}; + * + * @param socket a socket file descriptor + * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform. + */ + public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) + throws IOException { + applyTransportModeTransform(new ParcelFileDescriptor(socket), transform); + } + /** * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to @@ -318,6 +335,20 @@ public final class IpSecManager { removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform); } + /** + * Remove a transform from a given stream socket. Once removed, traffic on the socket will not + * be encypted. This allows sockets that have been used for IPsec to be reclaimed for + * communication in the clear in the event socket reuse is desired. This operation will succeed + * regardless of the underlying state of a transform. If a transform is removed, communication + * on all sockets to which that transform was applied will fail until this method is called. + * + * @param socket a socket file descriptor that previously had a transform applied to it. + * @param transform the IPsec Transform that was previously applied to the given socket + */ + public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) { + removeTransportModeTransform(new ParcelFileDescriptor(socket), transform); + } + /* Call down to activate a transform */ private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { try { From f56c5ebe819146795db993042ec86109bdeb6b11 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 5 Apr 2017 14:06:11 +0900 Subject: [PATCH 022/881] Nsdmanager/NsdService: add logging This patch adds basic logging to NsdManager and NsdService, and improves the facilities for pretty printing the event ids defined in NsdManager. It also includes a few minor cleanups: - adding 'final' on effectively final instance variables of NsdManager and NsdService. - similarly, adding 'static' on effectively static class fields. - regrouping instance variables together. Test: no functional changes Bug: 33074219 (cherry picked from commit 2183ba9b5f8eb54c74cd198a7506b21319794e99) Merged-In: I360d539e73cc8e4b45d4e0d20b2e345455fdb10c Change-Id: Id917f3a2085d17f277850af36a2cf859e3614a0f --- core/java/android/net/nsd/NsdManager.java | 49 ++++++-- .../java/com/android/server/NsdService.java | 107 +++++++++--------- 2 files changed, 94 insertions(+), 62 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 33d12a3a3f..1dde3cad23 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -45,7 +45,7 @@ import com.android.internal.util.Protocol; * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt * *

The API is asynchronous and responses to requests from an application are on listener - * callbacks on a seperate thread. + * callbacks on a seperate internal thread. * *

There are three main operations the API supports - registration, discovery and resolution. *

@@ -119,8 +119,8 @@ import com.android.internal.util.Protocol;
  * {@see NsdServiceInfo}
  */
 public final class NsdManager {
-    private static final String TAG = "NsdManager";
-    INsdManager mService;
+    private static final String TAG = NsdManager.class.getSimpleName();
+    private static final boolean DBG = false;
 
     /**
      * Broadcast intent action to indicate whether network service discovery is
@@ -130,8 +130,7 @@ public final class NsdManager {
      * @see #EXTRA_NSD_STATE
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_NSD_STATE_CHANGED =
-        "android.net.nsd.STATE_CHANGED";
+    public static final String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
 
     /**
      * The lookup key for an int that indicates whether network service discovery is enabled
@@ -208,13 +207,47 @@ public final class NsdManager {
     /** Dns based service discovery protocol */
     public static final int PROTOCOL_DNS_SD = 0x0001;
 
-    private Context mContext;
+    private static final SparseArray EVENT_NAMES = new SparseArray<>();
+    static {
+        EVENT_NAMES.put(DISCOVER_SERVICES, "DISCOVER_SERVICES");
+        EVENT_NAMES.put(DISCOVER_SERVICES_STARTED, "DISCOVER_SERVICES_STARTED");
+        EVENT_NAMES.put(DISCOVER_SERVICES_FAILED, "DISCOVER_SERVICES_FAILED");
+        EVENT_NAMES.put(SERVICE_FOUND, "SERVICE_FOUND");
+        EVENT_NAMES.put(SERVICE_LOST, "SERVICE_LOST");
+        EVENT_NAMES.put(STOP_DISCOVERY, "STOP_DISCOVERY");
+        EVENT_NAMES.put(STOP_DISCOVERY_FAILED, "STOP_DISCOVERY_FAILED");
+        EVENT_NAMES.put(STOP_DISCOVERY_SUCCEEDED, "STOP_DISCOVERY_SUCCEEDED");
+        EVENT_NAMES.put(REGISTER_SERVICE, "REGISTER_SERVICE");
+        EVENT_NAMES.put(REGISTER_SERVICE_FAILED, "REGISTER_SERVICE_FAILED");
+        EVENT_NAMES.put(REGISTER_SERVICE_SUCCEEDED, "REGISTER_SERVICE_SUCCEEDED");
+        EVENT_NAMES.put(UNREGISTER_SERVICE, "UNREGISTER_SERVICE");
+        EVENT_NAMES.put(UNREGISTER_SERVICE_FAILED, "UNREGISTER_SERVICE_FAILED");
+        EVENT_NAMES.put(UNREGISTER_SERVICE_SUCCEEDED, "UNREGISTER_SERVICE_SUCCEEDED");
+        EVENT_NAMES.put(RESOLVE_SERVICE, "RESOLVE_SERVICE");
+        EVENT_NAMES.put(RESOLVE_SERVICE_FAILED, "RESOLVE_SERVICE_FAILED");
+        EVENT_NAMES.put(RESOLVE_SERVICE_SUCCEEDED, "RESOLVE_SERVICE_SUCCEEDED");
+        EVENT_NAMES.put(ENABLE, "ENABLE");
+        EVENT_NAMES.put(DISABLE, "DISABLE");
+        EVENT_NAMES.put(NATIVE_DAEMON_EVENT, "NATIVE_DAEMON_EVENT");
+    }
+
+    /** @hide */
+    public static String nameOf(int event) {
+        String name = EVENT_NAMES.get(event);
+        if (name == null) {
+            return Integer.toString(event);
+        }
+        return name;
+    }
+
+    private final INsdManager mService;
+    private final Context mContext;
 
     private static final int INVALID_LISTENER_KEY = 0;
     private static final int BUSY_LISTENER_KEY = -1;
     private int mListenerKey = 1;
     private final SparseArray mListenerMap = new SparseArray();
-    private final SparseArray mServiceMap = new SparseArray();
+    private final SparseArray mServiceMap = new SparseArray<>();
     private final Object mMapLock = new Object();
 
     private final AsyncChannel mAsyncChannel = new AsyncChannel();
@@ -300,6 +333,7 @@ public final class NsdManager {
 
         @Override
         public void handleMessage(Message message) {
+            if (DBG) Log.d(TAG, "received " + nameOf(message.what));
             switch (message.what) {
                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                     mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
@@ -377,7 +411,6 @@ public final class NsdManager {
 
     // if the listener is already in the map, reject it.  Otherwise, add it and
     // return its key.
-
     private int putListener(Object listener, NsdServiceInfo s) {
         if (listener == null) return INVALID_LISTENER_KEY;
         int key;
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 8ae95d5ada..43b9f8b2ce 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -57,46 +57,27 @@ public class NsdService extends INsdManager.Stub {
     private static final String TAG = "NsdService";
     private static final String MDNS_TAG = "mDnsConnector";
 
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
-    private Context mContext;
-    private ContentResolver mContentResolver;
-    private NsdStateMachine mNsdStateMachine;
+    private final Context mContext;
+    private final ContentResolver mContentResolver;
+    private final NsdStateMachine mNsdStateMachine;
+    private final NativeDaemonConnector mNativeConnector;
+    private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
 
     /**
      * Clients receiving asynchronous messages
      */
-    private HashMap mClients = new HashMap();
+    private final HashMap mClients = new HashMap<>();
 
     /* A map from unique id to client info */
-    private SparseArray mIdToClientInfoMap= new SparseArray();
+    private final SparseArray mIdToClientInfoMap= new SparseArray<>();
 
-    private AsyncChannel mReplyChannel = new AsyncChannel();
+    private final AsyncChannel mReplyChannel = new AsyncChannel();
 
-    private int INVALID_ID = 0;
+    private static final int INVALID_ID = 0;
     private int mUniqueId = 1;
 
-    private static final int BASE = Protocol.BASE_NSD_MANAGER;
-    private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1;
-    private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
-
-    static {
-        sCmdToString[NsdManager.DISCOVER_SERVICES - BASE] = "DISCOVER";
-        sCmdToString[NsdManager.STOP_DISCOVERY - BASE] = "STOP-DISCOVER";
-        sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER";
-        sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER";
-        sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE";
-    }
-
-    private static String cmdToString(int cmd) {
-        cmd -= BASE;
-        if ((cmd >= 0) && (cmd < sCmdToString.length)) {
-            return sCmdToString[cmd];
-        } else {
-            return null;
-        }
-    }
-
     private class NsdStateMachine extends StateMachine {
 
         private final DefaultState mDefaultState = new DefaultState();
@@ -105,7 +86,7 @@ public class NsdService extends INsdManager.Stub {
 
         @Override
         protected String getWhatToString(int what) {
-            return cmdToString(what);
+            return NsdManager.nameOf(what);
         }
 
         /**
@@ -114,13 +95,13 @@ public class NsdService extends INsdManager.Stub {
         private void registerForNsdSetting() {
             ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
                 @Override
-                    public void onChange(boolean selfChange) {
-                        if (isNsdEnabled()) {
-                            mNsdStateMachine.sendMessage(NsdManager.ENABLE);
-                        } else {
-                            mNsdStateMachine.sendMessage(NsdManager.DISABLE);
-                        }
+                public void onChange(boolean selfChange) {
+                    if (isNsdEnabled()) {
+                        mNsdStateMachine.sendMessage(NsdManager.ENABLE);
+                    } else {
+                        mNsdStateMachine.sendMessage(NsdManager.DISABLE);
                     }
+                }
             };
 
             mContext.getContentResolver().registerContentObserver(
@@ -412,7 +393,8 @@ public class NsdService extends INsdManager.Stub {
                 int id = Integer.parseInt(cooked[1]);
                 ClientInfo clientInfo = mIdToClientInfoMap.get(id);
                 if (clientInfo == null) {
-                    Slog.e(TAG, "Unique id with no client mapping: " + id);
+                    String name = NativeResponseCode.nameOf(code);
+                    Slog.e(TAG, String.format("id %d for %s has no client mapping", id, name));
                     handled = false;
                     return handled;
                 }
@@ -423,42 +405,43 @@ public class NsdService extends INsdManager.Stub {
                     // This can happen because of race conditions. For example,
                     // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
                     // and we may get in this situation.
-                    Slog.d(TAG, "Notification for a listener that is no longer active: " + id);
+                    String name = NativeResponseCode.nameOf(code);
+                    Slog.d(TAG, String.format(
+                            "Notification %s for listener id %d that is no longer active",
+                            name, id));
                     handled = false;
                     return handled;
                 }
-
+                if (DBG) {
+                    String name = NativeResponseCode.nameOf(code);
+                    Slog.d(TAG, String.format("Native daemon message %s: %s", name, raw));
+                }
                 switch (code) {
                     case NativeResponseCode.SERVICE_FOUND:
                         /* NNN uniqueId serviceName regType domain */
-                        if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw);
                         servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
                         clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
                                 clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_LOST:
                         /* NNN uniqueId serviceName regType domain */
-                        if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw);
                         servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
                         clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
                                 clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
                         /* NNN uniqueId errorCode */
-                        if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw);
                         clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED,
                                 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
                         break;
                     case NativeResponseCode.SERVICE_REGISTERED:
                         /* NNN regId serviceName regType */
-                        if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw);
                         servInfo = new NsdServiceInfo(cooked[2], null);
                         clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
                                 id, clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
                         /* NNN regId errorCode */
-                        if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw);
                         clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED,
                                NsdManager.FAILURE_INTERNAL_ERROR, clientId);
                         break;
@@ -470,7 +453,6 @@ public class NsdService extends INsdManager.Stub {
                         break;
                     case NativeResponseCode.SERVICE_RESOLVED:
                         /* NNN resolveId fullName hostName port txtlen txtdata */
-                        if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw);
                         int index = 0;
                         while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
                             if (cooked[2].charAt(index) == '\\') {
@@ -507,7 +489,6 @@ public class NsdService extends INsdManager.Stub {
                         break;
                     case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
                         /* NNN resolveId errorCode */
-                        if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw);
                         stopResolveService(id);
                         removeRequestMap(clientId, id, clientInfo);
                         clientInfo.mResolvedService = null;
@@ -519,13 +500,11 @@ public class NsdService extends INsdManager.Stub {
                         stopGetAddrInfo(id);
                         removeRequestMap(clientId, id, clientInfo);
                         clientInfo.mResolvedService = null;
-                        if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw);
                         clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
                                 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
                         break;
                     case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
                         /* NNN resolveId hostname ttl addr */
-                        if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw);
                         try {
                             clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
                             clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED,
@@ -571,9 +550,6 @@ public class NsdService extends INsdManager.Stub {
         return sb.toString();
     }
 
-    private NativeDaemonConnector mNativeConnector;
-    private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
-
     private NsdService(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
@@ -634,7 +610,7 @@ public class NsdService extends INsdManager.Stub {
     }
 
     /* These should be in sync with system/netd/server/ResponseCode.h */
-    class NativeResponseCode {
+    static final class NativeResponseCode {
         public static final int SERVICE_DISCOVERY_FAILED    =   602;
         public static final int SERVICE_FOUND               =   603;
         public static final int SERVICE_LOST                =   604;
@@ -650,6 +626,29 @@ public class NsdService extends INsdManager.Stub {
 
         public static final int SERVICE_GET_ADDR_FAILED     =   611;
         public static final int SERVICE_GET_ADDR_SUCCESS    =   612;
+
+        private static final SparseArray CODE_NAMES = new SparseArray<>();
+        static {
+            CODE_NAMES.put(SERVICE_DISCOVERY_FAILED, "SERVICE_DISCOVERY_FAILED");
+            CODE_NAMES.put(SERVICE_FOUND, "SERVICE_FOUND");
+            CODE_NAMES.put(SERVICE_LOST, "SERVICE_LOST");
+            CODE_NAMES.put(SERVICE_REGISTRATION_FAILED, "SERVICE_REGISTRATION_FAILED");
+            CODE_NAMES.put(SERVICE_REGISTERED, "SERVICE_REGISTERED");
+            CODE_NAMES.put(SERVICE_RESOLUTION_FAILED, "SERVICE_RESOLUTION_FAILED");
+            CODE_NAMES.put(SERVICE_RESOLVED, "SERVICE_RESOLVED");
+            CODE_NAMES.put(SERVICE_UPDATED, "SERVICE_UPDATED");
+            CODE_NAMES.put(SERVICE_UPDATE_FAILED, "SERVICE_UPDATE_FAILED");
+            CODE_NAMES.put(SERVICE_GET_ADDR_FAILED, "SERVICE_GET_ADDR_FAILED");
+            CODE_NAMES.put(SERVICE_GET_ADDR_SUCCESS, "SERVICE_GET_ADDR_SUCCESS");
+        }
+
+        static String nameOf(int code) {
+            String name = CODE_NAMES.get(code);
+            if (name == null) {
+                return Integer.toString(code);
+            }
+            return name;
+        }
     }
 
     private class NativeEvent {
@@ -863,10 +862,10 @@ public class NsdService extends INsdManager.Stub {
         private NsdServiceInfo mResolvedService;
 
         /* A map from client id to unique id sent to mDns */
-        private SparseArray mClientIds = new SparseArray();
+        private final SparseArray mClientIds = new SparseArray<>();
 
         /* A map from client id to the type of the request we had received */
-        private SparseArray mClientRequests = new SparseArray();
+        private final SparseArray mClientRequests = new SparseArray<>();
 
         private ClientInfo(AsyncChannel c, Messenger m) {
             mChannel = c;

From 1bcfebf971796a0914b3972df737ae015dd06fc8 Mon Sep 17 00:00:00 2001
From: Nathan Harold 
Date: Mon, 17 Apr 2017 17:11:58 -0700
Subject: [PATCH 023/881] Consistenly Throw IOExceptions from IpSecManager

Bug: 36073210
Test: api-update
Change-Id: Ia3825e85b09b6330f1326a26cf9e1cadf9dacf71
Merged-In: Ia3825e85b09b6330f1326a26cf9e1cadf9dacf71
(cherry picked from commit c2fd6cfdc9dce33d57a3c2780e0527dd4b1bfeb9)
---
 core/java/android/net/IpSecManager.java | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index f8702e2e00..1a55b37665 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -317,7 +317,8 @@ public final class IpSecManager {
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
      */
-    public void removeTransportModeTransform(Socket socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(ParcelFileDescriptor.fromSocket(socket), transform);
     }
 
@@ -331,7 +332,8 @@ public final class IpSecManager {
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
      */
-    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(ParcelFileDescriptor.fromDatagramSocket(socket), transform);
     }
 
@@ -345,7 +347,8 @@ public final class IpSecManager {
      * @param socket a socket file descriptor that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
      */
-    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) {
+    public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform)
+            throws IOException {
         removeTransportModeTransform(new ParcelFileDescriptor(socket), transform);
     }
 
@@ -419,7 +422,7 @@ public final class IpSecManager {
          *
          * @param fd a file descriptor previously returned as a UDP Encapsulation socket.
          */
-        public void close() {
+        public void close() throws IOException {
             // TODO: Go close the socket
             mCloseGuard.close();
         }

From 238b78c2aa8fece83ec7f8f4897a9de55604ed9e Mon Sep 17 00:00:00 2001
From: Nathan Harold 
Date: Mon, 17 Apr 2017 19:34:33 -0700
Subject: [PATCH 024/881] Hide Socket+DatagramSocket IpSecTransform methods

These methods do not currently work for IPv4 sockets,
so they need to be hidden until the underlying kernel
code can be made to work properly in a dual-stack
environment.

Bug: 36073210
Test: compilation
Merged-In: Idce367f638a42da374a7f1dc5ebb8931c9555e06
Change-Id: Idce367f638a42da374a7f1dc5ebb8931c9555e06
(cherry picked from commit da18b028f85e9a2c969c636aea6abf7f4bac3922)
---
 core/java/android/net/IpSecManager.java | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 1a55b37665..375b7eeb01 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -245,6 +245,7 @@ public final class IpSecManager {
      *
      * @param socket a stream socket
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     * @hide
      */
     public void applyTransportModeTransform(Socket socket, IpSecTransform transform)
             throws IOException {
@@ -262,6 +263,7 @@ public final class IpSecManager {
      *
      * @param socket a datagram socket
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
+     * @hide
      */
     public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
             throws IOException {
@@ -284,7 +286,7 @@ public final class IpSecManager {
      * address associated with that transform will throw an IOException. In addition, if the
      * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to
      * send() or receive() until the transform is removed from the socket by calling {@link
-     * #removeTransportModeTransform(Socket, IpSecTransform)};
+     * #removeTransportModeTransform(FileDescriptor, IpSecTransform)};
      *
      * @param socket a socket file descriptor
      * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform.
@@ -316,6 +318,7 @@ public final class IpSecManager {
      *
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
+     * @hide
      */
     public void removeTransportModeTransform(Socket socket, IpSecTransform transform)
             throws IOException {
@@ -331,6 +334,7 @@ public final class IpSecManager {
      *
      * @param socket a socket that previously had a transform applied to it.
      * @param transform the IPsec Transform that was previously applied to the given socket
+     * @hide
      */
     public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform)
             throws IOException {

From 7d4b344b193030e3b5a4bafef9c3289bd5335a84 Mon Sep 17 00:00:00 2001
From: Hugo Benichi 
Date: Wed, 5 Apr 2017 14:43:29 +0900
Subject: [PATCH 025/881] NsdService: minor cleanups

Minor cleanups in switches of processMessage and handleNativeEvent.

Test: no functional changes
Bug: 33074219

(cherry picked from commit 23dba85fff01a9f51beea8ce811fc98b582f8e71)

Merged-In: I9ad4ce812c0d2c02a671a7a871ad427e4ce29b4a
Change-Id: Ic029cc9fa007d8c485f64f4afcbd4dc10da1ae29
---
 .../java/com/android/server/NsdService.java   | 28 +++++++------------
 1 file changed, 10 insertions(+), 18 deletions(-)

diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 43b9f8b2ce..bb530fb8c1 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -253,20 +253,17 @@ public class NsdService extends INsdManager.Stub {
             public boolean processMessage(Message msg) {
                 ClientInfo clientInfo;
                 NsdServiceInfo servInfo;
-                boolean result = HANDLED;
                 int id;
                 switch (msg.what) {
-                  case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                         //First client
                         if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL &&
                                 mClients.size() == 0) {
                             startMDnsDaemon();
                         }
-                        result = NOT_HANDLED;
-                        break;
+                        return NOT_HANDLED;
                     case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                        result = NOT_HANDLED;
-                        break;
+                        return NOT_HANDLED;
                     case NsdManager.DISABLE:
                         //TODO: cleanup clients
                         transitionTo(mDisabledState);
@@ -377,26 +374,23 @@ public class NsdService extends INsdManager.Stub {
                     case NsdManager.NATIVE_DAEMON_EVENT:
                         NativeEvent event = (NativeEvent) msg.obj;
                         if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
-                            result = NOT_HANDLED;
+                            return NOT_HANDLED;
                         }
                         break;
                     default:
-                        result = NOT_HANDLED;
-                        break;
+                        return NOT_HANDLED;
                 }
-                return result;
+                return HANDLED;
             }
 
             private boolean handleNativeEvent(int code, String raw, String[] cooked) {
-                boolean handled = true;
                 NsdServiceInfo servInfo;
                 int id = Integer.parseInt(cooked[1]);
                 ClientInfo clientInfo = mIdToClientInfoMap.get(id);
                 if (clientInfo == null) {
                     String name = NativeResponseCode.nameOf(code);
                     Slog.e(TAG, String.format("id %d for %s has no client mapping", id, name));
-                    handled = false;
-                    return handled;
+                    return false;
                 }
 
                 /* This goes in response as msg.arg2 */
@@ -409,8 +403,7 @@ public class NsdService extends INsdManager.Stub {
                     Slog.d(TAG, String.format(
                             "Notification %s for listener id %d that is no longer active",
                             name, id));
-                    handled = false;
-                    return handled;
+                    return false;
                 }
                 if (DBG) {
                     String name = NativeResponseCode.nameOf(code);
@@ -518,10 +511,9 @@ public class NsdService extends INsdManager.Stub {
                         clientInfo.mResolvedService = null;
                         break;
                     default:
-                        handled = false;
-                        break;
+                        return false;
                 }
-                return handled;
+                return true;
             }
        }
     }

From faf8a9191762444f659164ce633bdfec1ab8de62 Mon Sep 17 00:00:00 2001
From: Nathan Harold 
Date: Tue, 25 Apr 2017 14:21:52 -0700
Subject: [PATCH 026/881] Hide IpSecManager, IpSecTransform, and IpSecAlgorithm

These classes, originally planned to be part of the
public API, are not ready for public consumption.
They are planned to be un-hidden in a future release.

Bug: 37681043
Test: make update-api and make
Merged-In: I8caccd3f8455341cb56a2256354eacbadedff047
Change-Id: I8caccd3f8455341cb56a2256354eacbadedff047
(cherry picked from commit e38565fc74ee19e27175782be3cf2f0dffefd3a6)
---
 core/java/android/net/IpSecAlgorithm.java | 2 ++
 core/java/android/net/IpSecManager.java   | 2 ++
 core/java/android/net/IpSecTransform.java | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index ce7894fb3b..48b095d9b7 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -24,6 +24,8 @@ import java.lang.annotation.RetentionPolicy;
 /**
  * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to
  * RFC 4301.
+ *
+ * @hide
  */
 public final class IpSecAlgorithm implements Parcelable {
 
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 375b7eeb01..114e46e54f 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -37,6 +37,8 @@ import java.net.Socket;
  * 

An IpSecManager may be obtained by calling {@link * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE} + * + * @hide */ public final class IpSecManager { private static final String TAG = "IpSecManager"; diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 801e98c7b1..639d1f2689 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -45,6 +45,8 @@ import java.net.InetAddress; * *

An IpSecTransform may either represent a tunnel mode transform that operates on a wide array * of traffic or may represent a transport mode transform operating on a Socket or Sockets. + * + * @hide */ public final class IpSecTransform implements AutoCloseable { private static final String TAG = "IpSecTransform"; From 410ab36029c6f3e1262da1ffccfdc4d944c230b8 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Fri, 7 Apr 2017 15:20:56 +0900 Subject: [PATCH 027/881] NetworkStatsFactory: fix double accounting on IPv6 only networks For 464xlat scenarios on IPv6 networks, the clatd interface setup introduces double counting of apps ipv4 traffic. NetworkStatsFactory was accounting for this on the tx path, but not on the rx path. Also it did not accounted for the 20 bytes added by the IPv6 header. This patch subtract correctly the rx and tx traffic from the root uid on the underlying interface, and also adds correctly the 20 bytes cost per packet on the stacked interface for 464xlat traffic. Test: added several new unit tests, based on synthetic data and real data also. Bug: 33681750 Change-Id: I4867fe181938d94b5594b3d88896a3c4e01d895c Merged-In: I2675643b220acbc6110179fa937d4c313b6f5e32 (cherry picked from commit e1bb3a14d1ee1aba2f92e5bccf659774699eaffe) --- .../internal/net/NetworkStatsFactory.java | 65 ++++++++++--------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 506114bd01..2fb3532c8f 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -50,6 +50,11 @@ public class NetworkStatsFactory { private static final boolean USE_NATIVE_PARSING = true; private static final boolean SANITY_CHECK_NATIVE = false; + private static final String CLATD_INTERFACE_PREFIX = "v4-"; + // Delta between IPv4 header (20b) and IPv6 header (40b). + // Used for correct stats accounting on clatd interfaces. + private static final int IPV4V6_HEADER_DELTA = 20; + /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ private final File mStatsXtIfaceAll; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */ @@ -57,6 +62,7 @@ public class NetworkStatsFactory { /** Path to {@code /proc/net/xt_qtaguid/stats}. */ private final File mStatsXtUid; + // TODO: to improve testability and avoid global state, do not use a static variable. @GuardedBy("sStackedIfaces") private static final ArrayMap sStackedIfaces = new ArrayMap<>(); @@ -124,9 +130,7 @@ public class NetworkStatsFactory { stats.addValues(entry); reader.finishLine(); } - } catch (NullPointerException e) { - throw new ProtocolException("problem parsing stats", e); - } catch (NumberFormatException e) { + } catch (NullPointerException|NumberFormatException e) { throw new ProtocolException("problem parsing stats", e); } finally { IoUtils.closeQuietly(reader); @@ -171,9 +175,7 @@ public class NetworkStatsFactory { stats.addValues(entry); reader.finishLine(); } - } catch (NullPointerException e) { - throw new ProtocolException("problem parsing stats", e); - } catch (NumberFormatException e) { + } catch (NullPointerException|NumberFormatException e) { throw new ProtocolException("problem parsing stats", e); } finally { IoUtils.closeQuietly(reader); @@ -188,26 +190,32 @@ public class NetworkStatsFactory { public NetworkStats readNetworkStatsDetail(int limitUid, String[] limitIfaces, int limitTag, NetworkStats lastStats) throws IOException { - final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, - lastStats); + final NetworkStats stats = + readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); + NetworkStats.Entry entry = null; // for recycling synchronized (sStackedIfaces) { - // Sigh, xt_qtaguid ends up double-counting tx traffic going through - // clatd interfaces, so we need to subtract it here. + // For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 + // packet on the stacked interface, and once as translated to an IPv6 packet on the + // base interface. For correct stats accounting on the base interface, every 464xlat + // packet needs to be subtracted from the root UID on the base interface both for tx + // and rx traffic (http://b/12249687, http:/b/33681750). final int size = sStackedIfaces.size(); for (int i = 0; i < size; i++) { final String stackedIface = sStackedIfaces.keyAt(i); final String baseIface = sStackedIfaces.valueAt(i); + if (!stackedIface.startsWith(CLATD_INTERFACE_PREFIX)) { + continue; + } - // Count up the tx traffic and subtract from root UID on the - // base interface. - NetworkStats.Entry adjust = new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, - 0L, 0L); - NetworkStats.Entry entry = null; + NetworkStats.Entry adjust = + new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); for (int j = 0; j < stats.size(); j++) { entry = stats.getValues(j, entry); if (Objects.equals(entry.iface, stackedIface)) { - adjust.txBytes -= entry.txBytes; + adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); + adjust.rxPackets -= entry.rxPackets; adjust.txPackets -= entry.txPackets; } } @@ -215,19 +223,20 @@ public class NetworkStatsFactory { } } - // Double sigh, all rx traffic on clat needs to be tweaked to - // account for the dropped IPv6 header size post-unwrap. - NetworkStats.Entry entry = null; + // For 464xlat traffic, xt_qtaguid only counts the bytes of the inner IPv4 packet sent on + // the stacked interface with prefix "v4-" and drops the IPv6 header size after unwrapping. + // To account correctly for on-the-wire traffic, add the 20 additional bytes difference + // for all packets (http://b/12249687, http:/b/33681750). for (int i = 0; i < stats.size(); i++) { entry = stats.getValues(i, entry); - if (entry.iface != null && entry.iface.startsWith("clat")) { - // Delta between IPv4 header (20b) and IPv6 header (40b) - entry.rxBytes = entry.rxPackets * 20; - entry.rxPackets = 0; - entry.txBytes = 0; - entry.txPackets = 0; - stats.combineValues(entry); + if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { + continue; } + entry.rxBytes = entry.rxPackets * IPV4V6_HEADER_DELTA; + entry.txBytes = entry.txPackets * IPV4V6_HEADER_DELTA; + entry.rxPackets = 0; + entry.txPackets = 0; + stats.combineValues(entry); } return stats; @@ -305,9 +314,7 @@ public class NetworkStatsFactory { reader.finishLine(); } - } catch (NullPointerException e) { - throw new ProtocolException("problem parsing idx " + idx, e); - } catch (NumberFormatException e) { + } catch (NullPointerException|NumberFormatException e) { throw new ProtocolException("problem parsing idx " + idx, e); } finally { IoUtils.closeQuietly(reader); From bad59112f567c005db79030d2a8d17816328c3dc Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Mon, 15 May 2017 16:34:52 -0700 Subject: [PATCH 028/881] Be resilient to restoring unintelligible network templates Some OEMs have introduced incompatible network bookkeeping. We now detect and ignore those network definitions at restore time. In addition, we now * log when an undefined network match type is used to construct a NetworkTemplate instance, and * quietly refuse to match such a NetworkTemplate against any known network identifier, rather than crashing the inquiring app. Bug 38151335 Test: manual Change-Id: I565b6f6b87df1f13a8c0c01ae6049bda270b1e48 --- core/java/android/net/NetworkTemplate.java | 43 +++++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index caf79829db..0d2fcd0740 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -18,8 +18,8 @@ package android.net; import static android.net.ConnectivityManager.TYPE_BLUETOOTH; import static android.net.ConnectivityManager.TYPE_ETHERNET; -import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIMAX; @@ -34,8 +34,8 @@ import static android.telephony.TelephonyManager.getNetworkClass; import android.os.Parcel; import android.os.Parcelable; import android.util.BackupUtils; +import android.util.Log; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import java.io.ByteArrayOutputStream; @@ -52,14 +52,18 @@ import java.util.Objects; * @hide */ public class NetworkTemplate implements Parcelable { + private static final String TAG = "NetworkTemplate"; + /** * Current Version of the Backup Serializer. */ private static final int BACKUP_VERSION = 1; public static final int MATCH_MOBILE_ALL = 1; + /** @deprecated don't use this any more */ @Deprecated public static final int MATCH_MOBILE_3G_LOWER = 2; + /** @deprecated don't use this any more */ @Deprecated public static final int MATCH_MOBILE_4G = 3; public static final int MATCH_WIFI = 4; @@ -69,9 +73,26 @@ public class NetworkTemplate implements Parcelable { public static final int MATCH_BLUETOOTH = 8; public static final int MATCH_PROXY = 9; + private static boolean isKnownMatchRule(final int rule) { + switch (rule) { + case MATCH_MOBILE_ALL: + case MATCH_MOBILE_3G_LOWER: + case MATCH_MOBILE_4G: + case MATCH_WIFI: + case MATCH_ETHERNET: + case MATCH_MOBILE_WILDCARD: + case MATCH_WIFI_WILDCARD: + case MATCH_BLUETOOTH: + case MATCH_PROXY: + return true; + + default: + return false; + } + } + private static boolean sForceAllNetworkTypes = false; - @VisibleForTesting public static void forceAllNetworkTypes() { sForceAllNetworkTypes = true; } @@ -180,6 +201,11 @@ public class NetworkTemplate implements Parcelable { mSubscriberId = subscriberId; mMatchSubscriberIds = matchSubscriberIds; mNetworkId = networkId; + + if (!isKnownMatchRule(matchRule)) { + Log.e(TAG, "Unknown network template rule " + matchRule + + " will not match any identity."); + } } private NetworkTemplate(Parcel in) { @@ -294,7 +320,9 @@ public class NetworkTemplate implements Parcelable { case MATCH_PROXY: return matchesProxy(ident); default: - throw new IllegalArgumentException("unknown network template"); + // We have no idea what kind of network template we are, so we + // just claim not to match anything. + return false; } } @@ -428,7 +456,7 @@ public class NetworkTemplate implements Parcelable { case MATCH_PROXY: return "PROXY"; default: - return "UNKNOWN"; + return "UNKNOWN(" + matchRule + ")"; } } @@ -496,6 +524,11 @@ public class NetworkTemplate implements Parcelable { String subscriberId = BackupUtils.readString(in); String networkId = BackupUtils.readString(in); + if (!isKnownMatchRule(matchRule)) { + throw new BackupUtils.BadVersionException( + "Restored network template contains unknown match rule " + matchRule); + } + return new NetworkTemplate(matchRule, subscriberId, networkId); } } From a086cac905f913aa4689942ea49c3752aa37b652 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Fri, 28 Apr 2017 15:31:10 +0900 Subject: [PATCH 029/881] NsdService: test coverage for client requests. Adding coverage for: - NsdManager client disconnection - in-flight request GC Test: new test passes Bug: 37013369, 33298084 Bug: 38503832 (cherry picked from commit 4dd4db77209ab2ef302a3a2a4892b05aadd26ec6) Change-Id: I02aca772d88306acae09db739ced7a2b1119b72b --- core/java/android/net/nsd/NsdManager.java | 8 +++++ .../java/com/android/server/NsdService.java | 35 ++++++------------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 3fd9f19364..22bda77195 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -269,6 +269,14 @@ public final class NsdManager { init(); } + /** + * @hide + */ + @VisibleForTesting + public void disconnect() { + mAsyncChannel.disconnect(); + } + /** * Failures are passed with {@link RegistrationListener#onRegistrationFailed}, * {@link RegistrationListener#onUnregistrationFailed}, diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index d762214fad..4bccfa5408 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -49,7 +49,6 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.Protocol; import com.android.internal.util.State; import com.android.internal.util.StateMachine; -import com.android.server.NativeDaemonConnector.Command; /** * Network Service Discovery Service handles remote service discovery operation requests by @@ -155,7 +154,7 @@ public class NsdService extends INsdManager.Stub { } //Last client if (mClients.size() == 0) { - stopMDnsDaemon(); + mDaemon.stop(); } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: @@ -215,14 +214,14 @@ public class NsdService extends INsdManager.Stub { public void enter() { sendNsdStateChangeBroadcast(true); if (mClients.size() > 0) { - startMDnsDaemon(); + mDaemon.start(); } } @Override public void exit() { if (mClients.size() > 0) { - stopMDnsDaemon(); + mDaemon.stop(); } } @@ -256,7 +255,7 @@ public class NsdService extends INsdManager.Stub { //First client if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && mClients.size() == 0) { - startMDnsDaemon(); + mDaemon.start(); } return NOT_HANDLED; case AsyncChannel.CMD_CHANNEL_DISCONNECTED: @@ -703,26 +702,13 @@ public class NsdService extends INsdManager.Stub { return true; } - public boolean execute(Command cmd) { - if (DBG) { - Slog.d(TAG, cmd.toString()); - } - try { - mNativeConnector.execute(cmd); - } catch (NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to execute " + cmd, e); - return false; - } - return true; + public void start() { + execute("start-service"); } - } - private boolean startMDnsDaemon() { - return mDaemon.execute("start-service"); - } - - private boolean stopMDnsDaemon() { - return mDaemon.execute("stop-service"); + public void stop() { + execute("stop-service"); + } } private boolean registerService(int regId, NsdServiceInfo service) { @@ -734,8 +720,7 @@ public class NsdService extends INsdManager.Stub { int port = service.getPort(); byte[] textRecord = service.getTxtRecord(); String record = Base64.encodeToString(textRecord, Base64.DEFAULT).replace("\n", ""); - Command cmd = new Command("mdnssd", "register", regId, name, type, port, record); - return mDaemon.execute(cmd); + return mDaemon.execute("register", regId, name, type, port, record); } private boolean unregisterService(int regId) { From a81f4156e6f5d8e117dd8050503ccab5c45b9d0e Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Tue, 11 Apr 2017 14:42:47 +0900 Subject: [PATCH 030/881] NsdService: simple cleanups This patch replace some SparseArray with SparseIntArray, and simplify a value lookup function by using indexOfValue(). Test: TODO Bug: 37013369, 33298084 Bug: 38503832 (cherry picked from commit d2552aee119299bf66d694960c72a00141642ef5) Change-Id: Ifbe4f01bad8964e6f3a6e9633415959ab5feb0af --- .../java/com/android/server/NsdService.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 4bccfa5408..0ffac077d0 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -35,6 +35,7 @@ import android.provider.Settings; import android.util.Base64; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseIntArray; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -240,8 +241,8 @@ public class NsdService extends INsdManager.Stub { } private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { - clientInfo.mClientIds.remove(clientId); - clientInfo.mClientRequests.remove(clientId); + clientInfo.mClientIds.delete(clientId); + clientInfo.mClientRequests.delete(clientId); mIdToClientInfoMap.remove(globalId); } @@ -294,7 +295,7 @@ public class NsdService extends INsdManager.Stub { clientInfo = mClients.get(msg.replyTo); try { - id = clientInfo.mClientIds.get(msg.arg2).intValue(); + id = clientInfo.mClientIds.get(msg.arg2); } catch (NullPointerException e) { replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, NsdManager.FAILURE_INTERNAL_ERROR); @@ -332,7 +333,7 @@ public class NsdService extends INsdManager.Stub { if (DBG) Slog.d(TAG, "unregister service"); clientInfo = mClients.get(msg.replyTo); try { - id = clientInfo.mClientIds.get(msg.arg2).intValue(); + id = clientInfo.mClientIds.get(msg.arg2); } catch (NullPointerException e) { replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, NsdManager.FAILURE_INTERNAL_ERROR); @@ -813,10 +814,10 @@ public class NsdService extends INsdManager.Stub { private NsdServiceInfo mResolvedService; /* A map from client id to unique id sent to mDns */ - private final SparseArray mClientIds = new SparseArray<>(); + private final SparseIntArray mClientIds = new SparseIntArray(); /* A map from client id to the type of the request we had received */ - private final SparseArray mClientRequests = new SparseArray<>(); + private final SparseIntArray mClientRequests = new SparseIntArray(); private ClientInfo(AsyncChannel c, Messenger m) { mChannel = c; @@ -843,6 +844,7 @@ public class NsdService extends INsdManager.Stub { // and send cancellations to the daemon. private void expungeAllRequests() { int globalId, clientId, i; + // TODO: to keep handler responsive, do not clean all requests for that client at once. for (i = 0; i < mClientIds.size(); i++) { clientId = mClientIds.keyAt(i); globalId = mClientIds.valueAt(i); @@ -870,15 +872,11 @@ public class NsdService extends INsdManager.Stub { // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, // return the corresponding listener id. mDnsClient id is also called a global id. private int getClientId(final int globalId) { - // This doesn't use mClientIds.indexOfValue because indexOfValue uses == (not .equals) - // while also coercing the int primitives to Integer objects. - for (int i = 0, nSize = mClientIds.size(); i < nSize; i++) { - int mDnsId = mClientIds.valueAt(i); - if (globalId == mDnsId) { - return mClientIds.keyAt(i); - } + int idx = mClientIds.indexOfValue(globalId); + if (idx < 0) { + return idx; } - return -1; + return mClientIds.keyAt(idx); } } From fe07698782fcde17fff5d7be45ee7b2a36b8a43c Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Fri, 26 May 2017 16:08:22 -0700 Subject: [PATCH 031/881] Added video calling data usage per-uid support Now the VT call data usage will be counted under current dialer's data usage as well as the total device data usage. Test: Manual bug: 37671326 Change-Id: I8351e9ae17c84210f7ca6c319d3bddcbb0043341 --- .../server/net/NetworkStatsService.java | 53 ++++++++----------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index e746355097..ab685ca28b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -18,7 +18,6 @@ package com.android.server.net; import static android.Manifest.permission.ACCESS_NETWORK_STATE; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; -import static android.Manifest.permission.DUMP; import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.content.Intent.ACTION_SHUTDOWN; @@ -31,7 +30,6 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; -import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; @@ -58,14 +56,13 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.SECOND_IN_MILLIS; -import static com.android.internal.util.Preconditions.checkArgument; + import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; import android.app.AlarmManager; -import android.app.IAlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -1041,7 +1038,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // snapshot and record current counters; read UID stats first to // avoid over counting dev stats. final NetworkStats uidSnapshot = getNetworkStatsUidDetail(); - final NetworkStats xtSnapshot = getNetworkStatsXtAndVt(); + final NetworkStats xtSnapshot = getNetworkStatsXt(); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); @@ -1367,7 +1364,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Return snapshot of current UID statistics, including any - * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values. + * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations} + * values. */ private NetworkStats getNetworkStatsUidDetail() throws RemoteException { final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); @@ -1375,43 +1373,34 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(); uidSnapshot.combineAllValues(tetherSnapshot); + + final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( + Context.TELEPHONY_SERVICE); + + // fold video calling data usage stats into uid snapshot + final NetworkStats vtStats = telephonyManager.getVtDataUsage(true); + if (vtStats != null) { + uidSnapshot.combineAllValues(vtStats); + } uidSnapshot.combineAllValues(mUidOperations); return uidSnapshot; } /** - * Return snapshot of current XT plus VT statistics. + * Return snapshot of current XT statistics with video calling data usage statistics. */ - private NetworkStats getNetworkStatsXtAndVt() throws RemoteException { + private NetworkStats getNetworkStatsXt() throws RemoteException { final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt(); - TelephonyManager tm = (TelephonyManager) mContext.getSystemService( + final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); - long usage = tm.getVtDataUsage(); - - if (LOGV) Slog.d(TAG, "VT call data usage = " + usage); - - final NetworkStats vtSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 1); - - final NetworkStats.Entry entry = new NetworkStats.Entry(); - entry.iface = VT_INTERFACE; - entry.uid = -1; - entry.set = TAG_ALL; - entry.tag = TAG_NONE; - - // Since modem only tell us the total usage instead of each usage for RX and TX, - // we need to split it up (though it might not quite accurate). At - // least we can make sure the data usage report to the user will still be accurate. - entry.rxBytes = usage / 2; - entry.rxPackets = 0; - entry.txBytes = usage - entry.rxBytes; - entry.txPackets = 0; - vtSnapshot.combineValues(entry); - - // Merge VT int XT - xtSnapshot.combineAllValues(vtSnapshot); + // Merge video calling data usage into XT + final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(false); + if (vtSnapshot != null) { + xtSnapshot.combineAllValues(vtSnapshot); + } return xtSnapshot; } From 0a47018b06e0fce8230e47b8d475ef7f7bc7f5e5 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 2 Jun 2017 17:36:26 -0600 Subject: [PATCH 032/881] Annotate @SystemApi with required permissions. Most @SystemApi methods should be protected with system (or higher) permissions, so annotate common methods with @RequiresPermission to make automatic verification easier. Verification is really only relevant when calling into system services (where permissions checking can happen on the other side of a Binder call), so annotate managers with the new @SystemService annotation, which is now automatically documented. This is purely a docs change; no logic changes are being made. Test: make -j32 update-api && make -j32 offline-sdk-docs Bug: 62263906 Change-Id: I2554227202d84465676aa4ab0dd336b5c45fc651 --- core/java/android/app/usage/NetworkStatsManager.java | 2 ++ core/java/android/net/EthernetManager.java | 2 ++ core/java/android/net/IpSecManager.java | 7 +++---- core/java/android/net/TrafficStats.java | 3 +++ core/java/android/net/nsd/NsdManager.java | 5 ++--- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 6cd4e92383..ef262e0460 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -19,6 +19,7 @@ package android.app.usage; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; +import android.annotation.SystemService; import android.app.usage.NetworkStats.Bucket; import android.content.Context; import android.net.ConnectivityManager; @@ -82,6 +83,7 @@ import android.util.Log; * the above permission, even to access an app's own data usage, and carrier-privileged apps were * not included. */ +@SystemService(Context.NETWORK_STATS_SERVICE) public class NetworkStatsManager { private static final String TAG = "NetworkStatsManager"; private static final boolean DBG = false; diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 664b7b4089..31a30968cb 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.SystemService; import android.content.Context; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; @@ -31,6 +32,7 @@ import java.util.ArrayList; * * @hide */ +@SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; private static final int MSG_AVAILABILITY_CHANGED = 1000; diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 114e46e54f..e3cda5e7d8 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -18,6 +18,8 @@ package android.net; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; +import android.annotation.SystemService; +import android.content.Context; import android.os.Binder; import android.os.Bundle; import android.os.ParcelFileDescriptor; @@ -34,12 +36,9 @@ import java.net.Socket; * This class contains methods for managing IPsec sessions, which will perform kernel-space * encryption and decryption of socket or Network traffic. * - *

An IpSecManager may be obtained by calling {@link - * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link - * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE} - * * @hide */ +@SystemService(Context.IPSEC_SERVICE) public final class IpSecManager { private static final String TAG = "IpSecManager"; diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index fc66395bcd..f9346165df 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.DownloadManager; import android.app.backup.BackupManager; @@ -243,6 +244,7 @@ public class TrafficStats { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public static void setThreadStatsUid(int uid) { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); } @@ -255,6 +257,7 @@ public class TrafficStats { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public static void clearThreadStatsUid() { NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); } diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 1dde3cad23..2d480a18d5 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -17,6 +17,7 @@ package android.net.nsd; import android.annotation.SdkConstant; +import android.annotation.SystemService; import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.os.Handler; @@ -113,11 +114,9 @@ import com.android.internal.util.Protocol; * http://www.iana.org/form/ports-service. Existing services can be found at * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml * - * Get an instance of this class by calling {@link android.content.Context#getSystemService(String) - * Context.getSystemService(Context.NSD_SERVICE)}. - * * {@see NsdServiceInfo} */ +@SystemService(Context.NSD_SERVICE) public final class NsdManager { private static final String TAG = NsdManager.class.getSimpleName(); private static final boolean DBG = false; From febebd856dac3c7f64d371c2711ae25d075f7641 Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Thu, 25 May 2017 11:06:40 -0700 Subject: [PATCH 033/881] [P2P] Add binder to service calls Bug: 33040182 Test: unit tests, run-time behavior Change-Id: Ic383efc858bb4454d99c98ab24365c63ad3e7f54 --- wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl index 8b1cfaee81..bfdd45d9f9 100644 --- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl +++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl @@ -25,8 +25,9 @@ import android.os.Messenger; */ interface IWifiP2pManager { - Messenger getMessenger(); + Messenger getMessenger(in IBinder binder); Messenger getP2pStateMachineMessenger(); + oneway void close(in IBinder binder); void setMiracastMode(int mode); void checkConfigureWifiDisplayPermission(); } From 01501cea486bf9c509834f74369d8281f8c5b688 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 6 Jun 2017 19:16:28 +0900 Subject: [PATCH 034/881] Make Ethernet more robust. 1. Remove the IP provisioning thread and just attempt provisioning indefinitely whenever we have an interface. 2. Make all methods run on the passed-in handler thread. This makes it easier to verify correctness by code inspection. 3. Remove the code that changes the factory score depending on whether we're tracking an interface and have link. This is unnecessary complexity, as there is no penalty to accepting a request even if we don't have an interface. 4. Remove code duplication and only have one codepath for stopping layer 3. Tested the following are tested with this CL: - Booting with an interface connected. - Disconnecting/reconnecting the Ethernet cable repeatedly, particularly at inconvenient times (e.g., during provisioning). - Similarly, disconnecting/reconnecting USB Ethernet interfaces. - Falling back to another Ethernet interface if the currently tracked Ethernet interface is unplugged. - Disconnecting and restarting provisioning when provisioning is lost (e.g., if the default route is deleted). - Crashing the system server causes Ethernet to reconnect on restart. - The above while running watch -n 0.1 adb shell dumpsys ethernet Bug: 62308954 Test: tested on marlin with USB ethernet adapters, as described Change-Id: Iad12a52a903bfaccf7e245dfe499652c752c31e9 --- .../ethernet/EthernetNetworkFactory.java | 468 +++++++++--------- 1 file changed, 227 insertions(+), 241 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 0b091f26b1..7ff3f6c310 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -34,7 +34,6 @@ import android.net.NetworkInfo.DetailedState; import android.net.StaticIpConfiguration; import android.net.ip.IpManager; import android.net.ip.IpManager.ProvisioningConfiguration; -import android.net.ip.IpManager.WaitForProvisioningCallback; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; @@ -50,6 +49,8 @@ import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; /** @@ -84,6 +85,9 @@ class EthernetNetworkFactory { /** To set link state and configure IP addresses. */ private INetworkManagementService mNMService; + /** All code runs here, including start(). */ + private Handler mHandler; + /* To communicate with ConnectivityManager */ private NetworkCapabilities mNetworkCapabilities; private NetworkAgent mNetworkAgent; @@ -96,19 +100,18 @@ class EthernetNetworkFactory { /** To notify Ethernet status. */ private final RemoteCallbackList mListeners; - /** Data members. All accesses to these must be synchronized(this). */ - private static String mIface = ""; + /** Data members. All accesses to these must be on the handler thread. */ + private String mIface = ""; private String mHwAddr; - private static boolean mLinkUp; + private boolean mLinkUp; private NetworkInfo mNetworkInfo; private LinkProperties mLinkProperties; private IpManager mIpManager; - private Thread mIpProvisioningThread; + private boolean mNetworkRequested = false; EthernetNetworkFactory(RemoteCallbackList listeners) { - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); - mLinkProperties = new LinkProperties(); initNetworkCapabilities(); + clearInfo(); mListeners = listeners; } @@ -118,26 +121,40 @@ class EthernetNetworkFactory { } protected void startNetwork() { - onRequestNetwork(); + if (!mNetworkRequested) { + mNetworkRequested = true; + maybeStartIpManager(); + } } + protected void stopNetwork() { + mNetworkRequested = false; + stopIpManager(); } } - private void stopIpManagerLocked() { + private void clearInfo() { + mLinkProperties = new LinkProperties(); + mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + mNetworkInfo.setExtraInfo(mHwAddr); + mNetworkInfo.setIsAvailable(isTrackingInterface()); + } + + private void stopIpManager() { if (mIpManager != null) { mIpManager.shutdown(); mIpManager = null; } - } - - private void stopIpProvisioningThreadLocked() { - stopIpManagerLocked(); - - if (mIpProvisioningThread != null) { - mIpProvisioningThread.interrupt(); - mIpProvisioningThread = null; + // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object + // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: + // that sets the state to IDLE, and ConnectivityService will still think we're connected. + // + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); + if (mNetworkAgent != null) { + updateAgent(); + mNetworkAgent = null; } + clearInfo(); } /** @@ -150,36 +167,36 @@ class EthernetNetworkFactory { } Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down")); - synchronized(this) { - mLinkUp = up; - mNetworkInfo.setIsAvailable(up); - if (!up) { - // Tell the agent we're disconnected. It will call disconnect(). - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - stopIpProvisioningThreadLocked(); - } - updateAgent(); - // set our score lower than any network could go - // so we get dropped. TODO - just unregister the factory - // when link goes down. - mFactory.setScoreFilter(up ? NETWORK_SCORE : -1); + mLinkUp = up; + if (up) { + maybeStartIpManager(); + } else { + stopIpManager(); } } private class InterfaceObserver extends BaseNetworkObserver { @Override public void interfaceLinkStateChanged(String iface, boolean up) { - updateInterfaceState(iface, up); + mHandler.post(() -> { + updateInterfaceState(iface, up); + }); } @Override public void interfaceAdded(String iface) { - maybeTrackInterface(iface); + mHandler.post(() -> { + maybeTrackInterface(iface); + }); } @Override public void interfaceRemoved(String iface) { - stopTrackingInterface(iface); + mHandler.post(() -> { + if (stopTrackingInterface(iface)) { + trackFirstAvailableInterface(); + } + }); } } @@ -195,15 +212,13 @@ class EthernetNetworkFactory { return; } - synchronized (this) { - if (!isTrackingInterface()) { - setInterfaceInfoLocked(iface, config.getHardwareAddress()); - mNetworkInfo.setIsAvailable(true); - mNetworkInfo.setExtraInfo(mHwAddr); - } else { - Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); - mNMService.setInterfaceDown(iface); - } + if (!isTrackingInterface()) { + setInterfaceInfo(iface, config.getHardwareAddress()); + mNetworkInfo.setIsAvailable(true); + mNetworkInfo.setExtraInfo(mHwAddr); + } else { + Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); + mNMService.setInterfaceDown(iface); } } catch (RemoteException e) { Log.e(TAG, "Error upping interface " + mIface + ": " + e); @@ -221,23 +236,14 @@ class EthernetNetworkFactory { return true; } - private void stopTrackingInterface(String iface) { + private boolean stopTrackingInterface(String iface) { if (!iface.equals(mIface)) - return; + return false; Log.d(TAG, "Stopped tracking interface " + iface); - // TODO: Unify this codepath with stop(). - synchronized (this) { - stopIpProvisioningThreadLocked(); - setInterfaceInfoLocked("", null); - mNetworkInfo.setExtraInfo(null); - mLinkUp = false; - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - updateAgent(); - mNetworkAgent = null; - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); - mLinkProperties = new LinkProperties(); - } + setInterfaceInfo("", null); + stopIpManager(); + return true; } private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) { @@ -260,156 +266,127 @@ class EthernetNetworkFactory { } public void updateAgent() { - synchronized (EthernetNetworkFactory.this) { - if (mNetworkAgent == null) return; - if (DBG) { - Log.i(TAG, "Updating mNetworkAgent with: " + - mNetworkCapabilities + ", " + - mNetworkInfo + ", " + - mLinkProperties); + if (mNetworkAgent == null) return; + if (DBG) { + Log.i(TAG, "Updating mNetworkAgent with: " + + mNetworkCapabilities + ", " + + mNetworkInfo + ", " + + mLinkProperties); + } + mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + mNetworkAgent.sendNetworkInfo(mNetworkInfo); + mNetworkAgent.sendLinkProperties(mLinkProperties); + // never set the network score below 0. + mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); + } + + void onIpLayerStarted(LinkProperties linkProperties) { + if (mNetworkAgent != null) { + Log.e(TAG, "Already have a NetworkAgent - aborting new request"); + stopIpManager(); + return; + } + mLinkProperties = linkProperties; + mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); + + // Create our NetworkAgent. + mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, + NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, + NETWORK_SCORE) { + public void unwanted() { + if (this == mNetworkAgent) { + stopIpManager(); + } else if (mNetworkAgent != null) { + Log.d(TAG, "Ignoring unwanted as we have a more modern " + + "instance"); + } // Otherwise, we've already called stopIpManager. } - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); - mNetworkAgent.sendLinkProperties(mLinkProperties); - // never set the network score below 0. - mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); + }; + } + + void onIpLayerStopped(LinkProperties linkProperties) { + // This cannot happen due to provisioning timeout, because our timeout is 0. It can only + // happen if we're provisioned and we lose provisioning. + stopIpManager(); + maybeStartIpManager(); + } + + void updateLinkProperties(LinkProperties linkProperties) { + mLinkProperties = linkProperties; + if (mNetworkAgent != null) { + mNetworkAgent.sendLinkProperties(linkProperties); } } - /* Called by the NetworkFactory on the handler thread. */ - public void onRequestNetwork() { - synchronized(EthernetNetworkFactory.this) { - if (mIpProvisioningThread != null) { - return; - } + public void maybeStartIpManager() { + if (mNetworkRequested && mIpManager == null && isTrackingInterface()) { + startIpManager(); + } + } + + public void startIpManager() { + if (DBG) { + Log.d(TAG, String.format("starting IpManager(%s): mNetworkInfo=%s", mIface, + mNetworkInfo)); } - final Thread ipProvisioningThread = new Thread(new Runnable() { - public void run() { - if (DBG) { - Log.d(TAG, String.format("starting ipProvisioningThread(%s): mNetworkInfo=%s", - mIface, mNetworkInfo)); - } + LinkProperties linkProperties; - LinkProperties linkProperties; + IpConfiguration config = mEthernetManager.getConfiguration(); - IpConfiguration config = mEthernetManager.getConfiguration(); - - if (config.getIpAssignment() == IpAssignment.STATIC) { - if (!setStaticIpAddress(config.getStaticIpConfiguration())) { - // We've already logged an error. - return; - } - linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); - } else { - mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); - WaitForProvisioningCallback ipmCallback = new WaitForProvisioningCallback() { - @Override - public void onLinkPropertiesChange(LinkProperties newLp) { - synchronized(EthernetNetworkFactory.this) { - if (mNetworkAgent != null && mNetworkInfo.isConnected()) { - mLinkProperties = newLp; - mNetworkAgent.sendLinkProperties(newLp); - } - } - } - }; - - synchronized(EthernetNetworkFactory.this) { - stopIpManagerLocked(); - mIpManager = new IpManager(mContext, mIface, ipmCallback); - - if (config.getProxySettings() == ProxySettings.STATIC || - config.getProxySettings() == ProxySettings.PAC) { - mIpManager.setHttpProxy(config.getHttpProxy()); - } - - final String tcpBufferSizes = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_tcp_buffers); - if (!TextUtils.isEmpty(tcpBufferSizes)) { - mIpManager.setTcpBufferSizes(tcpBufferSizes); - } - - final ProvisioningConfiguration provisioningConfiguration = - mIpManager.buildProvisioningConfiguration() - .withProvisioningTimeoutMs(0) - .build(); - mIpManager.startProvisioning(provisioningConfiguration); - } - - linkProperties = ipmCallback.waitForProvisioning(); - if (linkProperties == null) { - Log.e(TAG, "IP provisioning error"); - // set our score lower than any network could go - // so we get dropped. - mFactory.setScoreFilter(-1); - synchronized(EthernetNetworkFactory.this) { - stopIpManagerLocked(); - } - return; - } - } - - synchronized(EthernetNetworkFactory.this) { - if (mNetworkAgent != null) { - Log.e(TAG, "Already have a NetworkAgent - aborting new request"); - stopIpManagerLocked(); - mIpProvisioningThread = null; - return; - } - mLinkProperties = linkProperties; - mNetworkInfo.setIsAvailable(true); - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); - - // Create our NetworkAgent. - mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext, - NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, - NETWORK_SCORE) { - public void unwanted() { - synchronized(EthernetNetworkFactory.this) { - if (this == mNetworkAgent) { - stopIpManagerLocked(); - - mLinkProperties.clear(); - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, - mHwAddr); - updateAgent(); - mNetworkAgent = null; - try { - mNMService.clearInterfaceAddresses(mIface); - } catch (Exception e) { - Log.e(TAG, "Failed to clear addresses or disable ipv6" + e); - } - } else { - Log.d(TAG, "Ignoring unwanted as we have a more modern " + - "instance"); - } - } - }; - }; - - mIpProvisioningThread = null; - } - - if (DBG) { - Log.d(TAG, String.format("exiting ipProvisioningThread(%s): mNetworkInfo=%s", - mIface, mNetworkInfo)); - } + if (config.getIpAssignment() == IpAssignment.STATIC) { + if (!setStaticIpAddress(config.getStaticIpConfiguration())) { + // We've already logged an error. + return; } - }); + linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); + } else { + mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); + IpManager.Callback ipmCallback = new IpManager.Callback() { + @Override + public void onProvisioningSuccess(LinkProperties newLp) { + mHandler.post(() -> onIpLayerStarted(newLp)); + } - synchronized(EthernetNetworkFactory.this) { - if (mIpProvisioningThread == null) { - mIpProvisioningThread = ipProvisioningThread; - mIpProvisioningThread.start(); + @Override + public void onProvisioningFailure(LinkProperties newLp) { + mHandler.post(() -> onIpLayerStopped(newLp)); + } + + @Override + public void onLinkPropertiesChange(LinkProperties newLp) { + mHandler.post(() -> updateLinkProperties(newLp)); + } + }; + + stopIpManager(); + mIpManager = new IpManager(mContext, mIface, ipmCallback); + + if (config.getProxySettings() == ProxySettings.STATIC || + config.getProxySettings() == ProxySettings.PAC) { + mIpManager.setHttpProxy(config.getHttpProxy()); } + + final String tcpBufferSizes = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_tcp_buffers); + if (!TextUtils.isEmpty(tcpBufferSizes)) { + mIpManager.setTcpBufferSizes(tcpBufferSizes); + } + + final ProvisioningConfiguration provisioningConfiguration = + mIpManager.buildProvisioningConfiguration() + .withProvisioningTimeoutMs(0) + .build(); + mIpManager.startProvisioning(provisioningConfiguration); } } /** * Begin monitoring connectivity */ - public synchronized void start(Context context, Handler target) { + public void start(Context context, Handler handler) { + mHandler = handler; + // The services we use. IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); mNMService = INetworkManagementService.Stub.asInterface(b); @@ -420,9 +397,9 @@ class EthernetNetworkFactory { com.android.internal.R.string.config_ethernet_iface_regex); // Create and register our NetworkFactory. - mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper()); + mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, mHandler.getLooper()); mFactory.setCapabilityFilter(mNetworkCapabilities); - mFactory.setScoreFilter(-1); // this set high when we have an iface + mFactory.setScoreFilter(NETWORK_SCORE); mFactory.register(); mContext = context; @@ -437,23 +414,22 @@ class EthernetNetworkFactory { // If an Ethernet interface is already connected, start tracking that. // Otherwise, the first Ethernet interface to appear will be tracked. + mHandler.post(() -> trackFirstAvailableInterface()); + } + + public void trackFirstAvailableInterface() { try { final String[] ifaces = mNMService.listInterfaces(); for (String iface : ifaces) { - synchronized(this) { - if (maybeTrackInterface(iface)) { - // We have our interface. Track it. - // Note: if the interface already has link (e.g., if we - // crashed and got restarted while it was running), - // we need to fake a link up notification so we start - // configuring it. Since we're already holding the lock, - // any real link up/down notification will only arrive - // after we've done this. - if (mNMService.getInterfaceConfig(iface).hasFlag("running")) { - updateInterfaceState(iface, true); - } - break; + if (maybeTrackInterface(iface)) { + // We have our interface. Track it. + // Note: if the interface already has link (e.g., if we crashed and got + // restarted while it was running), we need to fake a link up notification so we + // start configuring it. + if (mNMService.getInterfaceConfig(iface).hasFlag("running")) { + updateInterfaceState(iface, true); } + break; } } } catch (RemoteException|IllegalStateException e) { @@ -461,21 +437,9 @@ class EthernetNetworkFactory { } } - public synchronized void stop() { - stopIpProvisioningThreadLocked(); - // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object - // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: - // that sets the state to IDLE, and ConnectivityService will still think we're connected. - // - // TODO: stop using explicit comparisons to DISCONNECTED / SUSPENDED in ConnectivityService, - // and instead use isConnectedOrConnecting(). - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - mLinkUp = false; - updateAgent(); - mLinkProperties = new LinkProperties(); - mNetworkAgent = null; - setInterfaceInfoLocked("", null); - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + public void stop() { + stopIpManager(); + setInterfaceInfo("", null); mFactory.unregister(); } @@ -489,20 +453,22 @@ class EthernetNetworkFactory { mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000); } - public synchronized boolean isTrackingInterface() { + public boolean isTrackingInterface() { return !TextUtils.isEmpty(mIface); } /** * Set interface information and notify listeners if availability is changed. - * This should be called with the lock held. */ - private void setInterfaceInfoLocked(String iface, String hwAddr) { + private void setInterfaceInfo(String iface, String hwAddr) { boolean oldAvailable = isTrackingInterface(); mIface = iface; mHwAddr = hwAddr; boolean available = isTrackingInterface(); + mNetworkInfo.setExtraInfo(mHwAddr); + mNetworkInfo.setIsAvailable(available); + if (oldAvailable != available) { int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { @@ -516,26 +482,46 @@ class EthernetNetworkFactory { } } - synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { - if (isTrackingInterface()) { - pw.println("Tracking interface: " + mIface); - pw.increaseIndent(); - pw.println("MAC address: " + mHwAddr); - pw.println("Link state: " + (mLinkUp ? "up" : "down")); - pw.decreaseIndent(); - } else { - pw.println("Not tracking any interface"); - } + private void postAndWaitForRunnable(Runnable r) throws InterruptedException { + CountDownLatch latch = new CountDownLatch(1); + mHandler.post(() -> { + try { + r.run(); + } finally { + latch.countDown(); + } + }); + latch.await(); + } - pw.println(); - pw.println("NetworkInfo: " + mNetworkInfo); - pw.println("LinkProperties: " + mLinkProperties); - pw.println("NetworkAgent: " + mNetworkAgent); - if (mIpManager != null) { - pw.println("IpManager:"); - pw.increaseIndent(); - mIpManager.dump(fd, pw, args); - pw.decreaseIndent(); + + void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { + try { + postAndWaitForRunnable(() -> { + pw.println("Network Requested: " + mNetworkRequested); + if (isTrackingInterface()) { + pw.println("Tracking interface: " + mIface); + pw.increaseIndent(); + pw.println("MAC address: " + mHwAddr); + pw.println("Link state: " + (mLinkUp ? "up" : "down")); + pw.decreaseIndent(); + } else { + pw.println("Not tracking any interface"); + } + + pw.println(); + pw.println("NetworkInfo: " + mNetworkInfo); + pw.println("LinkProperties: " + mLinkProperties); + pw.println("NetworkAgent: " + mNetworkAgent); + if (mIpManager != null) { + pw.println("IpManager:"); + pw.increaseIndent(); + mIpManager.dump(fd, pw, args); + pw.decreaseIndent(); + } + }); + } catch (InterruptedException e) { + throw new IllegalStateException("dump() interrupted"); } } } From 4ccafebd8a626812a97332d5b70d9a3ea43354ad Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 6 Jun 2017 19:16:28 +0900 Subject: [PATCH 035/881] Make Ethernet more robust. 1. Remove the IP provisioning thread and just attempt provisioning indefinitely whenever we have an interface. 2. Make all methods run on the passed-in handler thread. This makes it easier to verify correctness by code inspection. 3. Remove the code that changes the factory score depending on whether we're tracking an interface and have link. This is unnecessary complexity, as there is no penalty to accepting a request even if we don't have an interface. 4. Remove code duplication and only have one codepath for stopping layer 3. Tested the following are tested with this CL: - Booting with an interface connected. - Disconnecting/reconnecting the Ethernet cable repeatedly, particularly at inconvenient times (e.g., during provisioning). - Similarly, disconnecting/reconnecting USB Ethernet interfaces. - Falling back to another Ethernet interface if the currently tracked Ethernet interface is unplugged. - Disconnecting and restarting provisioning when provisioning is lost (e.g., if the default route is deleted). - Crashing the system server causes Ethernet to reconnect on restart. - The above while running watch -n 0.1 adb shell dumpsys ethernet (cherry picked from commit 01501cea486bf9c509834f74369d8281f8c5b688) Bug: 62308954 Test: tested on marlin with USB ethernet adapters, as described Test: smoketested on aosp_bullhead Change-Id: Ie3041f1d453d15c81eee81adfc8593269c499d79 --- .../ethernet/EthernetNetworkFactory.java | 468 +++++++++--------- 1 file changed, 227 insertions(+), 241 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 0b091f26b1..7ff3f6c310 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -34,7 +34,6 @@ import android.net.NetworkInfo.DetailedState; import android.net.StaticIpConfiguration; import android.net.ip.IpManager; import android.net.ip.IpManager.ProvisioningConfiguration; -import android.net.ip.IpManager.WaitForProvisioningCallback; import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; @@ -50,6 +49,8 @@ import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Arrays; +import java.util.concurrent.CountDownLatch; /** @@ -84,6 +85,9 @@ class EthernetNetworkFactory { /** To set link state and configure IP addresses. */ private INetworkManagementService mNMService; + /** All code runs here, including start(). */ + private Handler mHandler; + /* To communicate with ConnectivityManager */ private NetworkCapabilities mNetworkCapabilities; private NetworkAgent mNetworkAgent; @@ -96,19 +100,18 @@ class EthernetNetworkFactory { /** To notify Ethernet status. */ private final RemoteCallbackList mListeners; - /** Data members. All accesses to these must be synchronized(this). */ - private static String mIface = ""; + /** Data members. All accesses to these must be on the handler thread. */ + private String mIface = ""; private String mHwAddr; - private static boolean mLinkUp; + private boolean mLinkUp; private NetworkInfo mNetworkInfo; private LinkProperties mLinkProperties; private IpManager mIpManager; - private Thread mIpProvisioningThread; + private boolean mNetworkRequested = false; EthernetNetworkFactory(RemoteCallbackList listeners) { - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); - mLinkProperties = new LinkProperties(); initNetworkCapabilities(); + clearInfo(); mListeners = listeners; } @@ -118,26 +121,40 @@ class EthernetNetworkFactory { } protected void startNetwork() { - onRequestNetwork(); + if (!mNetworkRequested) { + mNetworkRequested = true; + maybeStartIpManager(); + } } + protected void stopNetwork() { + mNetworkRequested = false; + stopIpManager(); } } - private void stopIpManagerLocked() { + private void clearInfo() { + mLinkProperties = new LinkProperties(); + mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + mNetworkInfo.setExtraInfo(mHwAddr); + mNetworkInfo.setIsAvailable(isTrackingInterface()); + } + + private void stopIpManager() { if (mIpManager != null) { mIpManager.shutdown(); mIpManager = null; } - } - - private void stopIpProvisioningThreadLocked() { - stopIpManagerLocked(); - - if (mIpProvisioningThread != null) { - mIpProvisioningThread.interrupt(); - mIpProvisioningThread = null; + // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object + // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: + // that sets the state to IDLE, and ConnectivityService will still think we're connected. + // + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); + if (mNetworkAgent != null) { + updateAgent(); + mNetworkAgent = null; } + clearInfo(); } /** @@ -150,36 +167,36 @@ class EthernetNetworkFactory { } Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down")); - synchronized(this) { - mLinkUp = up; - mNetworkInfo.setIsAvailable(up); - if (!up) { - // Tell the agent we're disconnected. It will call disconnect(). - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - stopIpProvisioningThreadLocked(); - } - updateAgent(); - // set our score lower than any network could go - // so we get dropped. TODO - just unregister the factory - // when link goes down. - mFactory.setScoreFilter(up ? NETWORK_SCORE : -1); + mLinkUp = up; + if (up) { + maybeStartIpManager(); + } else { + stopIpManager(); } } private class InterfaceObserver extends BaseNetworkObserver { @Override public void interfaceLinkStateChanged(String iface, boolean up) { - updateInterfaceState(iface, up); + mHandler.post(() -> { + updateInterfaceState(iface, up); + }); } @Override public void interfaceAdded(String iface) { - maybeTrackInterface(iface); + mHandler.post(() -> { + maybeTrackInterface(iface); + }); } @Override public void interfaceRemoved(String iface) { - stopTrackingInterface(iface); + mHandler.post(() -> { + if (stopTrackingInterface(iface)) { + trackFirstAvailableInterface(); + } + }); } } @@ -195,15 +212,13 @@ class EthernetNetworkFactory { return; } - synchronized (this) { - if (!isTrackingInterface()) { - setInterfaceInfoLocked(iface, config.getHardwareAddress()); - mNetworkInfo.setIsAvailable(true); - mNetworkInfo.setExtraInfo(mHwAddr); - } else { - Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); - mNMService.setInterfaceDown(iface); - } + if (!isTrackingInterface()) { + setInterfaceInfo(iface, config.getHardwareAddress()); + mNetworkInfo.setIsAvailable(true); + mNetworkInfo.setExtraInfo(mHwAddr); + } else { + Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); + mNMService.setInterfaceDown(iface); } } catch (RemoteException e) { Log.e(TAG, "Error upping interface " + mIface + ": " + e); @@ -221,23 +236,14 @@ class EthernetNetworkFactory { return true; } - private void stopTrackingInterface(String iface) { + private boolean stopTrackingInterface(String iface) { if (!iface.equals(mIface)) - return; + return false; Log.d(TAG, "Stopped tracking interface " + iface); - // TODO: Unify this codepath with stop(). - synchronized (this) { - stopIpProvisioningThreadLocked(); - setInterfaceInfoLocked("", null); - mNetworkInfo.setExtraInfo(null); - mLinkUp = false; - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - updateAgent(); - mNetworkAgent = null; - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); - mLinkProperties = new LinkProperties(); - } + setInterfaceInfo("", null); + stopIpManager(); + return true; } private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) { @@ -260,156 +266,127 @@ class EthernetNetworkFactory { } public void updateAgent() { - synchronized (EthernetNetworkFactory.this) { - if (mNetworkAgent == null) return; - if (DBG) { - Log.i(TAG, "Updating mNetworkAgent with: " + - mNetworkCapabilities + ", " + - mNetworkInfo + ", " + - mLinkProperties); + if (mNetworkAgent == null) return; + if (DBG) { + Log.i(TAG, "Updating mNetworkAgent with: " + + mNetworkCapabilities + ", " + + mNetworkInfo + ", " + + mLinkProperties); + } + mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); + mNetworkAgent.sendNetworkInfo(mNetworkInfo); + mNetworkAgent.sendLinkProperties(mLinkProperties); + // never set the network score below 0. + mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); + } + + void onIpLayerStarted(LinkProperties linkProperties) { + if (mNetworkAgent != null) { + Log.e(TAG, "Already have a NetworkAgent - aborting new request"); + stopIpManager(); + return; + } + mLinkProperties = linkProperties; + mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); + + // Create our NetworkAgent. + mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, + NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, + NETWORK_SCORE) { + public void unwanted() { + if (this == mNetworkAgent) { + stopIpManager(); + } else if (mNetworkAgent != null) { + Log.d(TAG, "Ignoring unwanted as we have a more modern " + + "instance"); + } // Otherwise, we've already called stopIpManager. } - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); - mNetworkAgent.sendLinkProperties(mLinkProperties); - // never set the network score below 0. - mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); + }; + } + + void onIpLayerStopped(LinkProperties linkProperties) { + // This cannot happen due to provisioning timeout, because our timeout is 0. It can only + // happen if we're provisioned and we lose provisioning. + stopIpManager(); + maybeStartIpManager(); + } + + void updateLinkProperties(LinkProperties linkProperties) { + mLinkProperties = linkProperties; + if (mNetworkAgent != null) { + mNetworkAgent.sendLinkProperties(linkProperties); } } - /* Called by the NetworkFactory on the handler thread. */ - public void onRequestNetwork() { - synchronized(EthernetNetworkFactory.this) { - if (mIpProvisioningThread != null) { - return; - } + public void maybeStartIpManager() { + if (mNetworkRequested && mIpManager == null && isTrackingInterface()) { + startIpManager(); + } + } + + public void startIpManager() { + if (DBG) { + Log.d(TAG, String.format("starting IpManager(%s): mNetworkInfo=%s", mIface, + mNetworkInfo)); } - final Thread ipProvisioningThread = new Thread(new Runnable() { - public void run() { - if (DBG) { - Log.d(TAG, String.format("starting ipProvisioningThread(%s): mNetworkInfo=%s", - mIface, mNetworkInfo)); - } + LinkProperties linkProperties; - LinkProperties linkProperties; + IpConfiguration config = mEthernetManager.getConfiguration(); - IpConfiguration config = mEthernetManager.getConfiguration(); - - if (config.getIpAssignment() == IpAssignment.STATIC) { - if (!setStaticIpAddress(config.getStaticIpConfiguration())) { - // We've already logged an error. - return; - } - linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); - } else { - mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); - WaitForProvisioningCallback ipmCallback = new WaitForProvisioningCallback() { - @Override - public void onLinkPropertiesChange(LinkProperties newLp) { - synchronized(EthernetNetworkFactory.this) { - if (mNetworkAgent != null && mNetworkInfo.isConnected()) { - mLinkProperties = newLp; - mNetworkAgent.sendLinkProperties(newLp); - } - } - } - }; - - synchronized(EthernetNetworkFactory.this) { - stopIpManagerLocked(); - mIpManager = new IpManager(mContext, mIface, ipmCallback); - - if (config.getProxySettings() == ProxySettings.STATIC || - config.getProxySettings() == ProxySettings.PAC) { - mIpManager.setHttpProxy(config.getHttpProxy()); - } - - final String tcpBufferSizes = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_tcp_buffers); - if (!TextUtils.isEmpty(tcpBufferSizes)) { - mIpManager.setTcpBufferSizes(tcpBufferSizes); - } - - final ProvisioningConfiguration provisioningConfiguration = - mIpManager.buildProvisioningConfiguration() - .withProvisioningTimeoutMs(0) - .build(); - mIpManager.startProvisioning(provisioningConfiguration); - } - - linkProperties = ipmCallback.waitForProvisioning(); - if (linkProperties == null) { - Log.e(TAG, "IP provisioning error"); - // set our score lower than any network could go - // so we get dropped. - mFactory.setScoreFilter(-1); - synchronized(EthernetNetworkFactory.this) { - stopIpManagerLocked(); - } - return; - } - } - - synchronized(EthernetNetworkFactory.this) { - if (mNetworkAgent != null) { - Log.e(TAG, "Already have a NetworkAgent - aborting new request"); - stopIpManagerLocked(); - mIpProvisioningThread = null; - return; - } - mLinkProperties = linkProperties; - mNetworkInfo.setIsAvailable(true); - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); - - // Create our NetworkAgent. - mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext, - NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, - NETWORK_SCORE) { - public void unwanted() { - synchronized(EthernetNetworkFactory.this) { - if (this == mNetworkAgent) { - stopIpManagerLocked(); - - mLinkProperties.clear(); - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, - mHwAddr); - updateAgent(); - mNetworkAgent = null; - try { - mNMService.clearInterfaceAddresses(mIface); - } catch (Exception e) { - Log.e(TAG, "Failed to clear addresses or disable ipv6" + e); - } - } else { - Log.d(TAG, "Ignoring unwanted as we have a more modern " + - "instance"); - } - } - }; - }; - - mIpProvisioningThread = null; - } - - if (DBG) { - Log.d(TAG, String.format("exiting ipProvisioningThread(%s): mNetworkInfo=%s", - mIface, mNetworkInfo)); - } + if (config.getIpAssignment() == IpAssignment.STATIC) { + if (!setStaticIpAddress(config.getStaticIpConfiguration())) { + // We've already logged an error. + return; } - }); + linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); + } else { + mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); + IpManager.Callback ipmCallback = new IpManager.Callback() { + @Override + public void onProvisioningSuccess(LinkProperties newLp) { + mHandler.post(() -> onIpLayerStarted(newLp)); + } - synchronized(EthernetNetworkFactory.this) { - if (mIpProvisioningThread == null) { - mIpProvisioningThread = ipProvisioningThread; - mIpProvisioningThread.start(); + @Override + public void onProvisioningFailure(LinkProperties newLp) { + mHandler.post(() -> onIpLayerStopped(newLp)); + } + + @Override + public void onLinkPropertiesChange(LinkProperties newLp) { + mHandler.post(() -> updateLinkProperties(newLp)); + } + }; + + stopIpManager(); + mIpManager = new IpManager(mContext, mIface, ipmCallback); + + if (config.getProxySettings() == ProxySettings.STATIC || + config.getProxySettings() == ProxySettings.PAC) { + mIpManager.setHttpProxy(config.getHttpProxy()); } + + final String tcpBufferSizes = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_tcp_buffers); + if (!TextUtils.isEmpty(tcpBufferSizes)) { + mIpManager.setTcpBufferSizes(tcpBufferSizes); + } + + final ProvisioningConfiguration provisioningConfiguration = + mIpManager.buildProvisioningConfiguration() + .withProvisioningTimeoutMs(0) + .build(); + mIpManager.startProvisioning(provisioningConfiguration); } } /** * Begin monitoring connectivity */ - public synchronized void start(Context context, Handler target) { + public void start(Context context, Handler handler) { + mHandler = handler; + // The services we use. IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); mNMService = INetworkManagementService.Stub.asInterface(b); @@ -420,9 +397,9 @@ class EthernetNetworkFactory { com.android.internal.R.string.config_ethernet_iface_regex); // Create and register our NetworkFactory. - mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper()); + mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, mHandler.getLooper()); mFactory.setCapabilityFilter(mNetworkCapabilities); - mFactory.setScoreFilter(-1); // this set high when we have an iface + mFactory.setScoreFilter(NETWORK_SCORE); mFactory.register(); mContext = context; @@ -437,23 +414,22 @@ class EthernetNetworkFactory { // If an Ethernet interface is already connected, start tracking that. // Otherwise, the first Ethernet interface to appear will be tracked. + mHandler.post(() -> trackFirstAvailableInterface()); + } + + public void trackFirstAvailableInterface() { try { final String[] ifaces = mNMService.listInterfaces(); for (String iface : ifaces) { - synchronized(this) { - if (maybeTrackInterface(iface)) { - // We have our interface. Track it. - // Note: if the interface already has link (e.g., if we - // crashed and got restarted while it was running), - // we need to fake a link up notification so we start - // configuring it. Since we're already holding the lock, - // any real link up/down notification will only arrive - // after we've done this. - if (mNMService.getInterfaceConfig(iface).hasFlag("running")) { - updateInterfaceState(iface, true); - } - break; + if (maybeTrackInterface(iface)) { + // We have our interface. Track it. + // Note: if the interface already has link (e.g., if we crashed and got + // restarted while it was running), we need to fake a link up notification so we + // start configuring it. + if (mNMService.getInterfaceConfig(iface).hasFlag("running")) { + updateInterfaceState(iface, true); } + break; } } } catch (RemoteException|IllegalStateException e) { @@ -461,21 +437,9 @@ class EthernetNetworkFactory { } } - public synchronized void stop() { - stopIpProvisioningThreadLocked(); - // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object - // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: - // that sets the state to IDLE, and ConnectivityService will still think we're connected. - // - // TODO: stop using explicit comparisons to DISCONNECTED / SUSPENDED in ConnectivityService, - // and instead use isConnectedOrConnecting(). - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - mLinkUp = false; - updateAgent(); - mLinkProperties = new LinkProperties(); - mNetworkAgent = null; - setInterfaceInfoLocked("", null); - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + public void stop() { + stopIpManager(); + setInterfaceInfo("", null); mFactory.unregister(); } @@ -489,20 +453,22 @@ class EthernetNetworkFactory { mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000); } - public synchronized boolean isTrackingInterface() { + public boolean isTrackingInterface() { return !TextUtils.isEmpty(mIface); } /** * Set interface information and notify listeners if availability is changed. - * This should be called with the lock held. */ - private void setInterfaceInfoLocked(String iface, String hwAddr) { + private void setInterfaceInfo(String iface, String hwAddr) { boolean oldAvailable = isTrackingInterface(); mIface = iface; mHwAddr = hwAddr; boolean available = isTrackingInterface(); + mNetworkInfo.setExtraInfo(mHwAddr); + mNetworkInfo.setIsAvailable(available); + if (oldAvailable != available) { int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { @@ -516,26 +482,46 @@ class EthernetNetworkFactory { } } - synchronized void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { - if (isTrackingInterface()) { - pw.println("Tracking interface: " + mIface); - pw.increaseIndent(); - pw.println("MAC address: " + mHwAddr); - pw.println("Link state: " + (mLinkUp ? "up" : "down")); - pw.decreaseIndent(); - } else { - pw.println("Not tracking any interface"); - } + private void postAndWaitForRunnable(Runnable r) throws InterruptedException { + CountDownLatch latch = new CountDownLatch(1); + mHandler.post(() -> { + try { + r.run(); + } finally { + latch.countDown(); + } + }); + latch.await(); + } - pw.println(); - pw.println("NetworkInfo: " + mNetworkInfo); - pw.println("LinkProperties: " + mLinkProperties); - pw.println("NetworkAgent: " + mNetworkAgent); - if (mIpManager != null) { - pw.println("IpManager:"); - pw.increaseIndent(); - mIpManager.dump(fd, pw, args); - pw.decreaseIndent(); + + void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { + try { + postAndWaitForRunnable(() -> { + pw.println("Network Requested: " + mNetworkRequested); + if (isTrackingInterface()) { + pw.println("Tracking interface: " + mIface); + pw.increaseIndent(); + pw.println("MAC address: " + mHwAddr); + pw.println("Link state: " + (mLinkUp ? "up" : "down")); + pw.decreaseIndent(); + } else { + pw.println("Not tracking any interface"); + } + + pw.println(); + pw.println("NetworkInfo: " + mNetworkInfo); + pw.println("LinkProperties: " + mLinkProperties); + pw.println("NetworkAgent: " + mNetworkAgent); + if (mIpManager != null) { + pw.println("IpManager:"); + pw.increaseIndent(); + mIpManager.dump(fd, pw, args); + pw.decreaseIndent(); + } + }); + } catch (InterruptedException e) { + throw new IllegalStateException("dump() interrupted"); } } } From a16337b500067aca7968368a12b0c994e221397b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 23 Jun 2017 01:21:25 +0900 Subject: [PATCH 036/881] Don't crash if the interface disappears just after appearing. If the interface disappears between interfaceAdded() and setInterfaceUp, we'll crash with an IllegalStateException in NetworkManagementService#setInterfaceConfig. Ignore the error instead. This should be safe because we don't modify any state unless our calls succeed. Bug: 62870779 Test: builds aosp_bullhead-eng Change-Id: If8c2375f7fffe25a9fa79dc4f1981c745384a276 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 7ff3f6c310..d6d0defd32 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -208,7 +208,7 @@ class EthernetNetworkFactory { InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); if (config == null) { - Log.e(TAG, "Null iterface config for " + iface + ". Bailing out."); + Log.e(TAG, "Null interface config for " + iface + ". Bailing out."); return; } @@ -220,7 +220,9 @@ class EthernetNetworkFactory { Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); mNMService.setInterfaceDown(iface); } - } catch (RemoteException e) { + } catch (RemoteException | IllegalStateException e) { + // Either the system is crashing or the interface has disappeared. Just ignore the + // error; we haven't modified any state because we only do that if our calls succeed. Log.e(TAG, "Error upping interface " + mIface + ": " + e); } } From 67f33458e155429dabfb0d8d7617c843b89da1d0 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 23 Jun 2017 01:21:25 +0900 Subject: [PATCH 037/881] Don't crash if the interface disappears just after appearing. If the interface disappears between interfaceAdded() and setInterfaceUp, we'll crash with an IllegalStateException in NetworkManagementService#setInterfaceConfig. Ignore the error instead. This should be safe because we don't modify any state unless our calls succeed. (cherry picked from commit a16337b500067aca7968368a12b0c994e221397b) Bug: 62870779 Test: builds aosp_bullhead-eng Test: builds marlin-eng Test: exception is logged and device doesn't crash when unplugging USB ethernet adapter while it's being initialized Change-Id: If8c2375f7fffe25a9fa79dc4f1981c745384a276 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 7ff3f6c310..d6d0defd32 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -208,7 +208,7 @@ class EthernetNetworkFactory { InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); if (config == null) { - Log.e(TAG, "Null iterface config for " + iface + ". Bailing out."); + Log.e(TAG, "Null interface config for " + iface + ". Bailing out."); return; } @@ -220,7 +220,9 @@ class EthernetNetworkFactory { Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); mNMService.setInterfaceDown(iface); } - } catch (RemoteException e) { + } catch (RemoteException | IllegalStateException e) { + // Either the system is crashing or the interface has disappeared. Just ignore the + // error; we haven't modified any state because we only do that if our calls succeed. Log.e(TAG, "Error upping interface " + mIface + ": " + e); } } From 38fd65b25bf2dad8f02f1418f37d73ba69619862 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 26 Jun 2017 19:50:41 -0600 Subject: [PATCH 038/881] Allocate well-known tag for app store updates. This way an app store can shift blame for update-related network traffic onto the app that is being updated. Using a well-known tag makes it easy for developers to identify that they didn't explicitly request the traffic at runtime, similar to how backup/restore traffic is handled. Bug: 38282350 Test: builds, boots Change-Id: I003dd7c9615d4ab318250f1e44fa5d195ac94d23 --- core/java/android/net/TrafficStats.java | 44 ++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index f9346165df..19857076a0 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -109,25 +109,26 @@ public class TrafficStats { */ public static final int TAG_SYSTEM_RESTORE = 0xFFFFFF04; - /** @hide */ - public static final int TAG_SYSTEM_DHCP = 0xFFFFFF05; - /** @hide */ - public static final int TAG_SYSTEM_NTP = 0xFFFFFF06; - /** @hide */ - public static final int TAG_SYSTEM_PROBE = 0xFFFFFF07; - /** @hide */ - public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF08; - /** @hide */ - public static final int TAG_SYSTEM_GPS = 0xFFFFFF09; - /** @hide */ - public static final int TAG_SYSTEM_PAC = 0xFFFFFF0A; - /** - * Sockets that are strictly local on device; never hits network. + * Default tag value for code or resources downloaded by an app store on + * behalf of the app, such as app updates. * * @hide */ - public static final int TAG_SYSTEM_LOCAL = 0xFFFFFFAA; + public static final int TAG_SYSTEM_CODE = 0xFFFFFF05; + + /** @hide */ + public static final int TAG_SYSTEM_DHCP = 0xFFFFFF40; + /** @hide */ + public static final int TAG_SYSTEM_NTP = 0xFFFFFF41; + /** @hide */ + public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42; + /** @hide */ + public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF43; + /** @hide */ + public static final int TAG_SYSTEM_GPS = 0xFFFFFF44; + /** @hide */ + public static final int TAG_SYSTEM_PAC = 0xFFFFFF45; private static INetworkStatsService sStatsService; @@ -209,6 +210,19 @@ public class TrafficStats { setThreadStatsTag(TAG_SYSTEM_RESTORE); } + /** + * Set active tag to use when accounting {@link Socket} traffic originating + * from the current thread. The tag used internally is well-defined to + * distinguish all code-related traffic, such as updates performed by an app + * store. + * + * @hide + */ + @SystemApi + public static void setThreadStatsTagCode() { + setThreadStatsTag(TAG_SYSTEM_CODE); + } + /** * Get the active tag used when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. From 20d50337cb6c81bb7c83bb8441eb927438d0689a Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 27 Jun 2017 11:01:36 -0600 Subject: [PATCH 039/881] Only require that system UIDs tag their sockets. Apps with a normal UID are typically isolated enough to not require socket tagging; we're mostly interested in tracking down internal UIDs that have lots of code sharing the same UID. Also fix up everyone doing manual string checks of Build.TYPE, since we now have first-class fields for those. Bug: 38126076 Test: builds, boots Change-Id: I3a40348196bd8459289f2b9355d9783a07f1e7dd --- core/java/android/net/NetworkIdentity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 0775bdaaf3..acd7b56027 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -157,7 +157,7 @@ public class NetworkIdentity implements Comparable { * Scrub given IMSI on production builds. */ public static String scrubSubscriberId(String subscriberId) { - if ("eng".equals(Build.TYPE)) { + if (Build.IS_ENG) { return subscriberId; } else if (subscriberId != null) { // TODO: parse this as MCC+MNC instead of hard-coding From 43f61f6b4594154c76f45b0e9d670dfa5b45385c Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 26 Jun 2017 11:24:47 -0600 Subject: [PATCH 040/881] Unify permissions under UPDATE_DEVICE_STATS. The UPDATE_DEVICE_STATS permission has become the de-facto mechanism that platform components use to shift blame for resource usage, so it's confusing to also have a separate MODIFY_NETWORK_ACCOUNTING permission. So this change replaces MODIFY_NETWORK_ACCOUNTING with UPDATE_DEVICE_STATS. Bug: 62483389 Test: builds, boots Exempt-From-Owner-Approval: Bug 63673347 Change-Id: I872759f02327b6d531ec2338bd876890aded60ad --- .../java/com/android/server/net/NetworkStatsService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index ab685ca28b..8209adeb89 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -18,7 +18,6 @@ package com.android.server.net; import static android.Manifest.permission.ACCESS_NETWORK_STATE; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; -import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; @@ -689,7 +688,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void incrementOperationCount(int uid, int tag, int operationCount) { if (Binder.getCallingUid() != uid) { - mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.UPDATE_DEVICE_STATS, TAG); } if (operationCount < 0) { @@ -710,7 +710,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setUidForeground(int uid, boolean uidForeground) { - mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); synchronized (mStatsLock) { final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT; @@ -750,7 +750,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void advisePersistThreshold(long thresholdBytes) { - mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); assertBandwidthControlEnabled(); // clamp threshold into safe range From 43ea1e553296f86423f2cf885f50fb507a745df8 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Tue, 2 May 2017 13:36:28 +0900 Subject: [PATCH 041/881] NsdManager: remove duplicated argument validation This patch simplifies argument validation in NsdManager public api and regroup duplicated validation into common methods. This makes stack traces more actionable as now specific errors will cause the api to throw exception from specific methods, whereas before IllegalArgumentException would be thrown from inside the same api method for different reasons. This patch also includes a couple of other small cleanups. Test: $ runtest -x frameworks/base/tests/net/../NsdManagerTest.java Bug: 35362108 Bug: 37013369 Bug: 62044295 Bug: 63826516 Merged-In: Iaad13e13976e9bf8f508d7188f823f8184ac414b (cherry pick from commit f2c64f87259679c44ef151b08cccab43ca5d4342) Change-Id: I5e6a1ecc6b98069ef0089bbceecf73f7692df227 --- core/java/android/net/nsd/NsdManager.java | 176 +++++++++------------- 1 file changed, 73 insertions(+), 103 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index ace3748664..1e41eea925 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -16,6 +16,10 @@ package android.net.nsd; +import static com.android.internal.util.Preconditions.checkArgument; +import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.internal.util.Preconditions.checkStringNotEmpty; + import android.annotation.SdkConstant; import android.annotation.SystemService; import android.annotation.SdkConstant.SdkConstantType; @@ -240,12 +244,12 @@ public final class NsdManager { return name; } + private static int FIRST_LISTENER_KEY = 1; + private final INsdManager mService; private final Context mContext; - private static final int INVALID_LISTENER_KEY = 0; - private static final int BUSY_LISTENER_KEY = -1; - private int mListenerKey = 1; + private int mListenerKey = FIRST_LISTENER_KEY; private final SparseArray mListenerMap = new SparseArray(); private final SparseArray mServiceMap = new SparseArray<>(); private final Object mMapLock = new Object(); @@ -311,7 +315,6 @@ public final class NsdManager { public void onServiceFound(NsdServiceInfo serviceInfo); public void onServiceLost(NsdServiceInfo serviceInfo); - } /** Interface for callback invocation for service registration */ @@ -342,8 +345,9 @@ public final class NsdManager { @Override public void handleMessage(Message message) { - if (DBG) Log.d(TAG, "received " + nameOf(message.what)); - switch (message.what) { + final int what = message.what; + final int key = message.arg2; + switch (what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); return; @@ -356,19 +360,26 @@ public final class NsdManager { default: break; } - Object listener = getListener(message.arg2); + final Object listener; + final NsdServiceInfo ns; + synchronized (mMapLock) { + listener = mListenerMap.get(key); + ns = mServiceMap.get(key); + } if (listener == null) { Log.d(TAG, "Stale key " + message.arg2); return; } - NsdServiceInfo ns = getNsdService(message.arg2); - switch (message.what) { + if (DBG) { + Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", service " + ns); + } + switch (what) { case DISCOVER_SERVICES_STARTED: String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); ((DiscoveryListener) listener).onDiscoveryStarted(s); break; case DISCOVER_SERVICES_FAILED: - removeListener(message.arg2); + removeListener(key); ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns), message.arg1); break; @@ -381,16 +392,16 @@ public final class NsdManager { case STOP_DISCOVERY_FAILED: // TODO: failure to stop discovery should be internal and retried internally, as // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED - removeListener(message.arg2); + removeListener(key); ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns), message.arg1); break; case STOP_DISCOVERY_SUCCEEDED: - removeListener(message.arg2); + removeListener(key); ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns)); break; case REGISTER_SERVICE_FAILED: - removeListener(message.arg2); + removeListener(key); ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1); break; case REGISTER_SERVICE_SUCCEEDED: @@ -398,7 +409,7 @@ public final class NsdManager { (NsdServiceInfo) message.obj); break; case UNREGISTER_SERVICE_FAILED: - removeListener(message.arg2); + removeListener(key); ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1); break; case UNREGISTER_SERVICE_SUCCEEDED: @@ -408,11 +419,11 @@ public final class NsdManager { ((RegistrationListener) listener).onServiceUnregistered(ns); break; case RESOLVE_SERVICE_FAILED: - removeListener(message.arg2); + removeListener(key); ((ResolveListener) listener).onResolveFailed(ns, message.arg1); break; case RESOLVE_SERVICE_SUCCEEDED: - removeListener(message.arg2); + removeListener(key); ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj); break; default: @@ -422,40 +433,27 @@ public final class NsdManager { } } - // if the listener is already in the map, reject it. Otherwise, add it and - // return its key. + private int nextListenerKey() { + // Ensure mListenerKey >= FIRST_LISTENER_KEY; + mListenerKey = Math.max(FIRST_LISTENER_KEY, mListenerKey + 1); + return mListenerKey; + } + + // Assert that the listener is not in the map, then add it and returns its key private int putListener(Object listener, NsdServiceInfo s) { - if (listener == null) return INVALID_LISTENER_KEY; - int key; + checkListener(listener); + final int key; synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - if (valueIndex != -1) { - return BUSY_LISTENER_KEY; - } - do { - key = mListenerKey++; - } while (key == INVALID_LISTENER_KEY); + checkArgument(valueIndex == -1, "listener already in use"); + key = nextListenerKey(); mListenerMap.put(key, listener); mServiceMap.put(key, s); } return key; } - private Object getListener(int key) { - if (key == INVALID_LISTENER_KEY) return null; - synchronized (mMapLock) { - return mListenerMap.get(key); - } - } - - private NsdServiceInfo getNsdService(int key) { - synchronized (mMapLock) { - return mServiceMap.get(key); - } - } - private void removeListener(int key) { - if (key == INVALID_LISTENER_KEY) return; synchronized (mMapLock) { mListenerMap.remove(key); mServiceMap.remove(key); @@ -463,16 +461,15 @@ public final class NsdManager { } private int getListenerKey(Object listener) { + checkListener(listener); synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - if (valueIndex != -1) { - return mListenerMap.keyAt(valueIndex); - } + checkArgument(valueIndex != -1, "listener not registered"); + return mListenerMap.keyAt(valueIndex); } - return INVALID_LISTENER_KEY; } - private String getNsdServiceInfoType(NsdServiceInfo s) { + private static String getNsdServiceInfoType(NsdServiceInfo s) { if (s == null) return "?"; return s.getServiceType(); } @@ -482,7 +479,9 @@ public final class NsdManager { */ private void init() { final Messenger messenger = getMessenger(); - if (messenger == null) throw new RuntimeException("Failed to initialize"); + if (messenger == null) { + fatal("Failed to obtain service Messenger"); + } HandlerThread t = new HandlerThread("NsdManager"); t.start(); mHandler = new ServiceHandler(t.getLooper()); @@ -490,10 +489,15 @@ public final class NsdManager { try { mConnected.await(); } catch (InterruptedException e) { - Log.e(TAG, "interrupted wait at init"); + fatal("Interrupted wait at init"); } } + private static void fatal(String msg) { + Log.e(TAG, msg); + throw new RuntimeException(msg); + } + /** * Register a service to be discovered by other services. * @@ -513,23 +517,10 @@ public final class NsdManager { */ public void registerService(NsdServiceInfo serviceInfo, int protocolType, RegistrationListener listener) { - if (TextUtils.isEmpty(serviceInfo.getServiceName()) || - TextUtils.isEmpty(serviceInfo.getServiceType())) { - throw new IllegalArgumentException("Service name or type cannot be empty"); - } - if (serviceInfo.getPort() <= 0) { - throw new IllegalArgumentException("Invalid port number"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } - if (protocolType != PROTOCOL_DNS_SD) { - throw new IllegalArgumentException("Unsupported protocol"); - } + checkArgument(serviceInfo.getPort() > 0, "Invalid port number"); + checkServiceInfo(serviceInfo); + checkProtocol(protocolType); int key = putListener(listener, serviceInfo); - if (key == BUSY_LISTENER_KEY) { - throw new IllegalArgumentException("listener already in use"); - } mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo); } @@ -548,12 +539,6 @@ public final class NsdManager { */ public void unregisterService(RegistrationListener listener) { int id = getListenerKey(listener); - if (id == INVALID_LISTENER_KEY) { - throw new IllegalArgumentException("listener not registered"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id); } @@ -586,25 +571,13 @@ public final class NsdManager { * Cannot be null. Cannot be in use for an active service discovery. */ public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } - if (TextUtils.isEmpty(serviceType)) { - throw new IllegalArgumentException("Service type cannot be empty"); - } - - if (protocolType != PROTOCOL_DNS_SD) { - throw new IllegalArgumentException("Unsupported protocol"); - } + checkStringNotEmpty(serviceType, "Service type cannot be empty"); + checkProtocol(protocolType); NsdServiceInfo s = new NsdServiceInfo(); s.setServiceType(serviceType); int key = putListener(listener, s); - if (key == BUSY_LISTENER_KEY) { - throw new IllegalArgumentException("listener already in use"); - } - mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s); } @@ -626,12 +599,6 @@ public final class NsdManager { */ public void stopServiceDiscovery(DiscoveryListener listener) { int id = getListenerKey(listener); - if (id == INVALID_LISTENER_KEY) { - throw new IllegalArgumentException("service discovery not active on listener"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id); } @@ -645,19 +612,8 @@ public final class NsdManager { * Cannot be in use for an active service resolution. */ public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { - if (TextUtils.isEmpty(serviceInfo.getServiceName()) || - TextUtils.isEmpty(serviceInfo.getServiceType())) { - throw new IllegalArgumentException("Service name or type cannot be empty"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } - + checkServiceInfo(serviceInfo); int key = putListener(listener, serviceInfo); - - if (key == BUSY_LISTENER_KEY) { - throw new IllegalArgumentException("listener already in use"); - } mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo); } @@ -671,10 +627,10 @@ public final class NsdManager { } /** - * Get a reference to NetworkService handler. This is used to establish + * Get a reference to NsdService handler. This is used to establish * an AsyncChannel communication with the service * - * @return Messenger pointing to the NetworkService handler + * @return Messenger pointing to the NsdService handler */ private Messenger getMessenger() { try { @@ -683,4 +639,18 @@ public final class NsdManager { throw e.rethrowFromSystemServer(); } } + + private static void checkListener(Object listener) { + checkNotNull(listener, "listener cannot be null"); + } + + private static void checkProtocol(int protocolType) { + checkArgument(protocolType == PROTOCOL_DNS_SD, "Unsupported protocol"); + } + + private static void checkServiceInfo(NsdServiceInfo serviceInfo) { + checkNotNull(serviceInfo, "NsdServiceInfo cannot be null"); + checkStringNotEmpty(serviceInfo.getServiceName(),"Service name cannot be empty"); + checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty"); + } } From a7e08f91fde1a0b884bfb2b3049bdba1246089f3 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Tue, 2 May 2017 13:36:28 +0900 Subject: [PATCH 042/881] NsdManager: remove duplicated argument validation This patch simplifies argument validation in NsdManager public api and regroup duplicated validation into common methods. This makes stack traces more actionable as now specific errors will cause the api to throw exception from specific methods, whereas before IllegalArgumentException would be thrown from inside the same api method for different reasons. This patch also includes a couple of other small cleanups. Test: $ runtest -x frameworks/base/tests/net/../NsdManagerTest.java Bug: 37013369 (cherry picked from commit f2c64f87259679c44ef151b08cccab43ca5d4342) Change-Id: Icf047532aa551fbe0a70721cfb95507eaa84d51e --- core/java/android/net/nsd/NsdManager.java | 176 +++++++++------------- 1 file changed, 73 insertions(+), 103 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index ace3748664..1e41eea925 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -16,6 +16,10 @@ package android.net.nsd; +import static com.android.internal.util.Preconditions.checkArgument; +import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.internal.util.Preconditions.checkStringNotEmpty; + import android.annotation.SdkConstant; import android.annotation.SystemService; import android.annotation.SdkConstant.SdkConstantType; @@ -240,12 +244,12 @@ public final class NsdManager { return name; } + private static int FIRST_LISTENER_KEY = 1; + private final INsdManager mService; private final Context mContext; - private static final int INVALID_LISTENER_KEY = 0; - private static final int BUSY_LISTENER_KEY = -1; - private int mListenerKey = 1; + private int mListenerKey = FIRST_LISTENER_KEY; private final SparseArray mListenerMap = new SparseArray(); private final SparseArray mServiceMap = new SparseArray<>(); private final Object mMapLock = new Object(); @@ -311,7 +315,6 @@ public final class NsdManager { public void onServiceFound(NsdServiceInfo serviceInfo); public void onServiceLost(NsdServiceInfo serviceInfo); - } /** Interface for callback invocation for service registration */ @@ -342,8 +345,9 @@ public final class NsdManager { @Override public void handleMessage(Message message) { - if (DBG) Log.d(TAG, "received " + nameOf(message.what)); - switch (message.what) { + final int what = message.what; + final int key = message.arg2; + switch (what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); return; @@ -356,19 +360,26 @@ public final class NsdManager { default: break; } - Object listener = getListener(message.arg2); + final Object listener; + final NsdServiceInfo ns; + synchronized (mMapLock) { + listener = mListenerMap.get(key); + ns = mServiceMap.get(key); + } if (listener == null) { Log.d(TAG, "Stale key " + message.arg2); return; } - NsdServiceInfo ns = getNsdService(message.arg2); - switch (message.what) { + if (DBG) { + Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", service " + ns); + } + switch (what) { case DISCOVER_SERVICES_STARTED: String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); ((DiscoveryListener) listener).onDiscoveryStarted(s); break; case DISCOVER_SERVICES_FAILED: - removeListener(message.arg2); + removeListener(key); ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns), message.arg1); break; @@ -381,16 +392,16 @@ public final class NsdManager { case STOP_DISCOVERY_FAILED: // TODO: failure to stop discovery should be internal and retried internally, as // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED - removeListener(message.arg2); + removeListener(key); ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns), message.arg1); break; case STOP_DISCOVERY_SUCCEEDED: - removeListener(message.arg2); + removeListener(key); ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns)); break; case REGISTER_SERVICE_FAILED: - removeListener(message.arg2); + removeListener(key); ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1); break; case REGISTER_SERVICE_SUCCEEDED: @@ -398,7 +409,7 @@ public final class NsdManager { (NsdServiceInfo) message.obj); break; case UNREGISTER_SERVICE_FAILED: - removeListener(message.arg2); + removeListener(key); ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1); break; case UNREGISTER_SERVICE_SUCCEEDED: @@ -408,11 +419,11 @@ public final class NsdManager { ((RegistrationListener) listener).onServiceUnregistered(ns); break; case RESOLVE_SERVICE_FAILED: - removeListener(message.arg2); + removeListener(key); ((ResolveListener) listener).onResolveFailed(ns, message.arg1); break; case RESOLVE_SERVICE_SUCCEEDED: - removeListener(message.arg2); + removeListener(key); ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj); break; default: @@ -422,40 +433,27 @@ public final class NsdManager { } } - // if the listener is already in the map, reject it. Otherwise, add it and - // return its key. + private int nextListenerKey() { + // Ensure mListenerKey >= FIRST_LISTENER_KEY; + mListenerKey = Math.max(FIRST_LISTENER_KEY, mListenerKey + 1); + return mListenerKey; + } + + // Assert that the listener is not in the map, then add it and returns its key private int putListener(Object listener, NsdServiceInfo s) { - if (listener == null) return INVALID_LISTENER_KEY; - int key; + checkListener(listener); + final int key; synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - if (valueIndex != -1) { - return BUSY_LISTENER_KEY; - } - do { - key = mListenerKey++; - } while (key == INVALID_LISTENER_KEY); + checkArgument(valueIndex == -1, "listener already in use"); + key = nextListenerKey(); mListenerMap.put(key, listener); mServiceMap.put(key, s); } return key; } - private Object getListener(int key) { - if (key == INVALID_LISTENER_KEY) return null; - synchronized (mMapLock) { - return mListenerMap.get(key); - } - } - - private NsdServiceInfo getNsdService(int key) { - synchronized (mMapLock) { - return mServiceMap.get(key); - } - } - private void removeListener(int key) { - if (key == INVALID_LISTENER_KEY) return; synchronized (mMapLock) { mListenerMap.remove(key); mServiceMap.remove(key); @@ -463,16 +461,15 @@ public final class NsdManager { } private int getListenerKey(Object listener) { + checkListener(listener); synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - if (valueIndex != -1) { - return mListenerMap.keyAt(valueIndex); - } + checkArgument(valueIndex != -1, "listener not registered"); + return mListenerMap.keyAt(valueIndex); } - return INVALID_LISTENER_KEY; } - private String getNsdServiceInfoType(NsdServiceInfo s) { + private static String getNsdServiceInfoType(NsdServiceInfo s) { if (s == null) return "?"; return s.getServiceType(); } @@ -482,7 +479,9 @@ public final class NsdManager { */ private void init() { final Messenger messenger = getMessenger(); - if (messenger == null) throw new RuntimeException("Failed to initialize"); + if (messenger == null) { + fatal("Failed to obtain service Messenger"); + } HandlerThread t = new HandlerThread("NsdManager"); t.start(); mHandler = new ServiceHandler(t.getLooper()); @@ -490,10 +489,15 @@ public final class NsdManager { try { mConnected.await(); } catch (InterruptedException e) { - Log.e(TAG, "interrupted wait at init"); + fatal("Interrupted wait at init"); } } + private static void fatal(String msg) { + Log.e(TAG, msg); + throw new RuntimeException(msg); + } + /** * Register a service to be discovered by other services. * @@ -513,23 +517,10 @@ public final class NsdManager { */ public void registerService(NsdServiceInfo serviceInfo, int protocolType, RegistrationListener listener) { - if (TextUtils.isEmpty(serviceInfo.getServiceName()) || - TextUtils.isEmpty(serviceInfo.getServiceType())) { - throw new IllegalArgumentException("Service name or type cannot be empty"); - } - if (serviceInfo.getPort() <= 0) { - throw new IllegalArgumentException("Invalid port number"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } - if (protocolType != PROTOCOL_DNS_SD) { - throw new IllegalArgumentException("Unsupported protocol"); - } + checkArgument(serviceInfo.getPort() > 0, "Invalid port number"); + checkServiceInfo(serviceInfo); + checkProtocol(protocolType); int key = putListener(listener, serviceInfo); - if (key == BUSY_LISTENER_KEY) { - throw new IllegalArgumentException("listener already in use"); - } mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo); } @@ -548,12 +539,6 @@ public final class NsdManager { */ public void unregisterService(RegistrationListener listener) { int id = getListenerKey(listener); - if (id == INVALID_LISTENER_KEY) { - throw new IllegalArgumentException("listener not registered"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id); } @@ -586,25 +571,13 @@ public final class NsdManager { * Cannot be null. Cannot be in use for an active service discovery. */ public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } - if (TextUtils.isEmpty(serviceType)) { - throw new IllegalArgumentException("Service type cannot be empty"); - } - - if (protocolType != PROTOCOL_DNS_SD) { - throw new IllegalArgumentException("Unsupported protocol"); - } + checkStringNotEmpty(serviceType, "Service type cannot be empty"); + checkProtocol(protocolType); NsdServiceInfo s = new NsdServiceInfo(); s.setServiceType(serviceType); int key = putListener(listener, s); - if (key == BUSY_LISTENER_KEY) { - throw new IllegalArgumentException("listener already in use"); - } - mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s); } @@ -626,12 +599,6 @@ public final class NsdManager { */ public void stopServiceDiscovery(DiscoveryListener listener) { int id = getListenerKey(listener); - if (id == INVALID_LISTENER_KEY) { - throw new IllegalArgumentException("service discovery not active on listener"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id); } @@ -645,19 +612,8 @@ public final class NsdManager { * Cannot be in use for an active service resolution. */ public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { - if (TextUtils.isEmpty(serviceInfo.getServiceName()) || - TextUtils.isEmpty(serviceInfo.getServiceType())) { - throw new IllegalArgumentException("Service name or type cannot be empty"); - } - if (listener == null) { - throw new IllegalArgumentException("listener cannot be null"); - } - + checkServiceInfo(serviceInfo); int key = putListener(listener, serviceInfo); - - if (key == BUSY_LISTENER_KEY) { - throw new IllegalArgumentException("listener already in use"); - } mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo); } @@ -671,10 +627,10 @@ public final class NsdManager { } /** - * Get a reference to NetworkService handler. This is used to establish + * Get a reference to NsdService handler. This is used to establish * an AsyncChannel communication with the service * - * @return Messenger pointing to the NetworkService handler + * @return Messenger pointing to the NsdService handler */ private Messenger getMessenger() { try { @@ -683,4 +639,18 @@ public final class NsdManager { throw e.rethrowFromSystemServer(); } } + + private static void checkListener(Object listener) { + checkNotNull(listener, "listener cannot be null"); + } + + private static void checkProtocol(int protocolType) { + checkArgument(protocolType == PROTOCOL_DNS_SD, "Unsupported protocol"); + } + + private static void checkServiceInfo(NsdServiceInfo serviceInfo) { + checkNotNull(serviceInfo, "NsdServiceInfo cannot be null"); + checkStringNotEmpty(serviceInfo.getServiceName(),"Service name cannot be empty"); + checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty"); + } } From ce144deb7b824a4c2fbc0d48e664267a74c61ba6 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 7 Aug 2017 15:47:35 +0900 Subject: [PATCH 043/881] NetworkStats: more robust subtraction for deltas This patch ensures that subtract() between two NetworkStats object will return a delta with no negative entries in all cases. When the stats delta contains some negative values, there are clamped to 0. Some logging is added when this happens. This is what's expected by NetworkStatsHistory#recordData(). Bug: 64365917 Test: runtest frameworks-net Change-Id: I16e97e73f600225f80e0ce517e80c07c6f399196 --- core/java/android/net/NetworkStats.java | 45 ++++++++++++------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 77ce65b081..be9e809738 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -672,36 +672,33 @@ public class NetworkStats implements Parcelable { entry.tag = left.tag[i]; entry.metered = left.metered[i]; entry.roaming = left.roaming[i]; + entry.rxBytes = left.rxBytes[i]; + entry.rxPackets = left.rxPackets[i]; + entry.txBytes = left.txBytes[i]; + entry.txPackets = left.txPackets[i]; + entry.operations = left.operations[i]; // find remote row that matches, and subtract final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, entry.roaming, i); - if (j == -1) { - // newly appearing row, return entire value - entry.rxBytes = left.rxBytes[i]; - entry.rxPackets = left.rxPackets[i]; - entry.txBytes = left.txBytes[i]; - entry.txPackets = left.txPackets[i]; - entry.operations = left.operations[i]; - } else { - // existing row, subtract remote value - entry.rxBytes = left.rxBytes[i] - right.rxBytes[j]; - entry.rxPackets = left.rxPackets[i] - right.rxPackets[j]; - entry.txBytes = left.txBytes[i] - right.txBytes[j]; - entry.txPackets = left.txPackets[i] - right.txPackets[j]; - entry.operations = left.operations[i] - right.operations[j]; + if (j != -1) { + // Found matching row, subtract remote value. + entry.rxBytes -= right.rxBytes[j]; + entry.rxPackets -= right.rxPackets[j]; + entry.txBytes -= right.txBytes[j]; + entry.txPackets -= right.txPackets[j]; + entry.operations -= right.operations[j]; + } - if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 - || entry.txPackets < 0 || entry.operations < 0) { - if (observer != null) { - observer.foundNonMonotonic(left, i, right, j, cookie); - } - entry.rxBytes = Math.max(entry.rxBytes, 0); - entry.rxPackets = Math.max(entry.rxPackets, 0); - entry.txBytes = Math.max(entry.txBytes, 0); - entry.txPackets = Math.max(entry.txPackets, 0); - entry.operations = Math.max(entry.operations, 0); + if (entry.isNegative()) { + if (observer != null) { + observer.foundNonMonotonic(left, i, right, j, cookie); } + entry.rxBytes = Math.max(entry.rxBytes, 0); + entry.rxPackets = Math.max(entry.rxPackets, 0); + entry.txBytes = Math.max(entry.txBytes, 0); + entry.txPackets = Math.max(entry.txPackets, 0); + entry.operations = Math.max(entry.operations, 0); } result.addValues(entry); From 63ee528005546ffc41d68bcade5abce2cc81bad6 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 11 Aug 2017 15:04:12 -0600 Subject: [PATCH 044/881] Rename API to match StorageStats. Since they're both measuring app code (APKs), name this API consistently with StorageStats.getAppBytes(). Bug: 64331226 Test: builds, boots Change-Id: I1b00427b619a78c043b1b5fac2d0e6406b51d454 --- core/java/android/net/TrafficStats.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 19857076a0..c339856f43 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -110,12 +110,12 @@ public class TrafficStats { public static final int TAG_SYSTEM_RESTORE = 0xFFFFFF04; /** - * Default tag value for code or resources downloaded by an app store on - * behalf of the app, such as app updates. + * Default tag value for code (typically APKs) downloaded by an app store on + * behalf of the app, such as updates. * * @hide */ - public static final int TAG_SYSTEM_CODE = 0xFFFFFF05; + public static final int TAG_SYSTEM_APP = 0xFFFFFF05; /** @hide */ public static final int TAG_SYSTEM_DHCP = 0xFFFFFF40; @@ -213,14 +213,14 @@ public class TrafficStats { /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. The tag used internally is well-defined to - * distinguish all code-related traffic, such as updates performed by an app - * store. + * distinguish all code (typically APKs) downloaded by an app store on + * behalf of the app, such as updates. * * @hide */ @SystemApi - public static void setThreadStatsTagCode() { - setThreadStatsTag(TAG_SYSTEM_CODE); + public static void setThreadStatsTagApp() { + setThreadStatsTag(TAG_SYSTEM_APP); } /** From f5138c8f44b997fd0d86dbc82c68cef4eeac6c91 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 17 Aug 2017 19:23:08 +0900 Subject: [PATCH 045/881] Add tether offload traffic to interface stats as well. Currently, we only count add tethering traffic to per-UID stats, but not to total data usage (i.e., dev and XT stats). This is correct for software tethering, because all software forwarded packets are already included in interface counters, but it is incorrect for hardware offload, because such packets do not increment interface counters. To fix this: 1. Add an argument to ITetheringStatsProvider#getTetherStats to indicate whether per-UID stats are requested. For clarity, define integer constants STATS_PER_IFACE and STATS_PER_UID to represent these operations. 2. Make NetdTetheringStatsProvider return stats only if per-UID stats are requested. (Otherwise tethering traffic would be double-counted). 3. Make OffloadController's stats provider return the same stats regardless of whether per-UID stats were requested or not. 4. Make NetworkStatsService add non-per-UID tethering stats to the dev and XT snapshots. The per-UID snapshots were already correctly adding in per-UID stats. Bug: 29337859 Bug: 32163131 Test: runtest frameworks-net Test: runtest frameworks-telephony Change-Id: I7a4d04ab47694d754874136179f8edad71099638 --- core/java/android/net/NetworkStats.java | 5 +++++ .../android/server/net/NetworkStatsService.java | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index be9e809738..171adc054b 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -82,6 +82,11 @@ public class NetworkStats implements Parcelable { /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; + /** Denotes a request for stats at the interface level. */ + public static final int STATS_PER_IFACE = 0; + /** Denotes a request for stats at the interface and UID level. */ + public static final int STATS_PER_UID = 1; + // TODO: move fields to "mVariable" notation /** diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 8209adeb89..b14aa13bfb 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -29,6 +29,8 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; @@ -1041,6 +1043,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats xtSnapshot = getNetworkStatsXt(); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); + // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats + // providers that isn't already counted by dev and XT stats. + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); + xtSnapshot.combineAllValues(tetherSnapshot); + devSnapshot.combineAllValues(tetherSnapshot); // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. @@ -1371,14 +1378,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); // fold tethering stats and operations into uid snapshot - final NetworkStats tetherSnapshot = getNetworkStatsTethering(); + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); // fold video calling data usage stats into uid snapshot - final NetworkStats vtStats = telephonyManager.getVtDataUsage(true); + final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { uidSnapshot.combineAllValues(vtStats); } @@ -1397,7 +1404,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Context.TELEPHONY_SERVICE); // Merge video calling data usage into XT - final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(false); + final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE); if (vtSnapshot != null) { xtSnapshot.combineAllValues(vtSnapshot); } @@ -1409,9 +1416,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Return snapshot of current tethering statistics. Will return empty * {@link NetworkStats} if any problems are encountered. */ - private NetworkStats getNetworkStatsTethering() throws RemoteException { + private NetworkStats getNetworkStatsTethering(int how) throws RemoteException { try { - return mNetworkManager.getNetworkStatsTethering(); + return mNetworkManager.getNetworkStatsTethering(how); } catch (IllegalStateException e) { Log.wtf(TAG, "problem reading network stats", e); return new NetworkStats(0L, 10); From 591c50889a5bd05c56f00f5509e79e713785f8c7 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 17 Aug 2017 19:23:08 +0900 Subject: [PATCH 046/881] Add tether offload traffic to interface stats as well. Currently, we only count add tethering traffic to per-UID stats, but not to total data usage (i.e., dev and XT stats). This is correct for software tethering, because all software forwarded packets are already included in interface counters, but it is incorrect for hardware offload, because such packets do not increment interface counters. To fix this: 1. Add an argument to ITetheringStatsProvider#getTetherStats to indicate whether per-UID stats are requested. For clarity, define integer constants STATS_PER_IFACE and STATS_PER_UID to represent these operations. 2. Make NetdTetheringStatsProvider return stats only if per-UID stats are requested. (Otherwise tethering traffic would be double-counted). 3. Make OffloadController's stats provider return the same stats regardless of whether per-UID stats were requested or not. 4. Make NetworkStatsService add non-per-UID tethering stats to the dev and XT snapshots. The per-UID snapshots were already correctly adding in per-UID stats. (cherry picked from commit 5356a35c3bcfcdf2d184c620af6bfbf9bddf35c5) Bug: 29337859 Bug: 32163131 Test: runtest frameworks-net Test: runtest frameworks-telephony Change-Id: I325b13d50e88841dfb0db4c35e7e27f163ee72fe Merged-In: I4e8e923d68dce1a4a68608dbd6c75a91165aa4ee --- core/java/android/net/NetworkStats.java | 5 +++++ .../android/server/net/NetworkStatsService.java | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 77ce65b081..0780af602b 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -82,6 +82,11 @@ public class NetworkStats implements Parcelable { /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; + /** Denotes a request for stats at the interface level. */ + public static final int STATS_PER_IFACE = 0; + /** Denotes a request for stats at the interface and UID level. */ + public static final int STATS_PER_UID = 1; + // TODO: move fields to "mVariable" notation /** diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4152070dc6..ef96de74cb 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -31,6 +31,8 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; @@ -1032,6 +1034,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats xtSnapshot = getNetworkStatsXt(); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); + // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats + // providers that isn't already counted by dev and XT stats. + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); + xtSnapshot.combineAllValues(tetherSnapshot); + devSnapshot.combineAllValues(tetherSnapshot); // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. @@ -1328,14 +1335,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); // fold tethering stats and operations into uid snapshot - final NetworkStats tetherSnapshot = getNetworkStatsTethering(); + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); // fold video calling data usage stats into uid snapshot - final NetworkStats vtStats = telephonyManager.getVtDataUsage(true); + final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { uidSnapshot.combineAllValues(vtStats); } @@ -1354,7 +1361,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Context.TELEPHONY_SERVICE); // Merge video calling data usage into XT - final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(false); + final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE); if (vtSnapshot != null) { xtSnapshot.combineAllValues(vtSnapshot); } @@ -1366,9 +1373,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Return snapshot of current tethering statistics. Will return empty * {@link NetworkStats} if any problems are encountered. */ - private NetworkStats getNetworkStatsTethering() throws RemoteException { + private NetworkStats getNetworkStatsTethering(int how) throws RemoteException { try { - return mNetworkManager.getNetworkStatsTethering(); + return mNetworkManager.getNetworkStatsTethering(how); } catch (IllegalStateException e) { Log.wtf(TAG, "problem reading network stats", e); return new NetworkStats(0L, 10); From 95b454fdf50b8654a71ca9f7a2e3527b33c5fa5e Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 29 Aug 2017 15:32:13 -0600 Subject: [PATCH 047/881] Augment network stats based on SubscriptionPlan. When a carrier provides an "anchor" of data usage at a specific moment in time, augment the network statistics used by warning/limit thresholds and Settings UI. For example, if the OS measured 500MB of usage, but the carrier says only 400MB has been used, we "squish" down the OS measured usage to match that anchor. Callers using the hidden API will have their data augmented by default, and the public API offers a way to opt-into augmentation. Thorough testing to verify behavior. Test: bit FrameworksNetTests:android.net.,com.android.server.net. Test: cts-tradefed run commandAndExit cts-dev -m CtsUsageStatsTestCases -t android.app.usage.cts.NetworkUsageStatsTest Bug: 64534190 Change-Id: Id3d4d7625bbf04f57643e51dbf376e3fa0ea8eca --- core/java/android/app/usage/NetworkStats.java | 4 +- .../app/usage/NetworkStatsManager.java | 45 +++-- .../android/net/INetworkStatsService.aidl | 2 +- .../java/android/net/NetworkStatsHistory.java | 19 ++ core/java/android/net/NetworkTemplate.java | 4 + .../server/net/NetworkStatsCollection.java | 162 +++++++++++++---- .../server/net/NetworkStatsObservers.java | 14 +- .../server/net/NetworkStatsRecorder.java | 9 +- .../server/net/NetworkStatsService.java | 165 ++++++++++++------ 9 files changed, 305 insertions(+), 119 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 3670b914ec..222e9a0e5e 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -97,12 +97,12 @@ public final class NetworkStats implements AutoCloseable { private NetworkStatsHistory.Entry mRecycledHistoryEntry = null; /** @hide */ - NetworkStats(Context context, NetworkTemplate template, long startTimestamp, + NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp, long endTimestamp) throws RemoteException, SecurityException { final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); // Open network stats session - mSession = statsService.openSessionForUsageStats(context.getOpPackageName()); + mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName()); mCloseGuard.open("close"); mTemplate = template; mStartTimeStamp = startTimestamp; diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index ef262e0460..853b00331a 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -24,15 +24,14 @@ import android.app.usage.NetworkStats.Bucket; import android.content.Context; import android.net.ConnectivityManager; import android.net.DataUsageRequest; +import android.net.INetworkStatsService; import android.net.NetworkIdentity; import android.net.NetworkTemplate; -import android.net.INetworkStatsService; import android.os.Binder; -import android.os.Build; -import android.os.Message; -import android.os.Messenger; import android.os.Handler; import android.os.Looper; +import android.os.Message; +import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; @@ -79,7 +78,7 @@ import android.util.Log; * In addition to tethering usage, usage by removed users and apps, and usage by the system * is also included in the results for callers with one of these higher levels of access. *

- * NOTE: Prior to API level {@value Build.VERSION_CODES#N}, all calls to these APIs required + * NOTE: Prior to API level {@value android.os.Build.VERSION_CODES#N}, all calls to these APIs required * the above permission, even to access an app's own data usage, and carrier-privileged apps were * not included. */ @@ -96,6 +95,13 @@ public class NetworkStatsManager { private final Context mContext; private final INetworkStatsService mService; + /** @hide */ + public static final int FLAG_POLL_ON_OPEN = 1 << 0; + /** @hide */ + public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 1; + + private int mFlags; + /** * {@hide} */ @@ -103,6 +109,25 @@ public class NetworkStatsManager { mContext = context; mService = INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)); + setPollOnOpen(true); + } + + /** @hide */ + public void setPollOnOpen(boolean pollOnOpen) { + if (pollOnOpen) { + mFlags |= FLAG_POLL_ON_OPEN; + } else { + mFlags &= ~FLAG_POLL_ON_OPEN; + } + } + + /** @hide */ + public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) { + if (augmentWithSubscriptionPlan) { + mFlags |= FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; + } else { + mFlags &= ~FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN; + } } /** @@ -136,7 +161,7 @@ public class NetworkStatsManager { } Bucket bucket = null; - NetworkStats stats = new NetworkStats(mContext, template, startTime, endTime); + NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); bucket = stats.getDeviceSummaryForNetwork(); stats.close(); @@ -174,7 +199,7 @@ public class NetworkStatsManager { } NetworkStats stats; - stats = new NetworkStats(mContext, template, startTime, endTime); + stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); stats.startSummaryEnumeration(); stats.close(); @@ -211,7 +236,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime); result.startSummaryEnumeration(); return result; @@ -260,7 +285,7 @@ public class NetworkStatsManager { NetworkStats result; try { - result = new NetworkStats(mContext, template, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime); result.startHistoryEnumeration(uid, tag); } catch (RemoteException e) { Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e); @@ -305,7 +330,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime); result.startUserUidEnumeration(); return result; } diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index e693009c33..91801127fd 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -36,7 +36,7 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ - INetworkStatsSession openSessionForUsageStats(String callingPackage); + INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return network layer usage total for traffic that matches template. */ long getNetworkTotalBytes(in NetworkTemplate template, long start, long end); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 5f521de63c..433f9410cc 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -27,6 +27,7 @@ import static android.net.NetworkStatsHistory.Entry.UNKNOWN; import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; import static android.text.format.DateUtils.SECOND_IN_MILLIS; + import static com.android.internal.util.ArrayUtils.total; import android.os.Parcel; @@ -282,6 +283,24 @@ public class NetworkStatsHistory implements Parcelable { return entry; } + public void setValues(int i, Entry entry) { + // Unwind old values + if (rxBytes != null) totalBytes -= rxBytes[i]; + if (txBytes != null) totalBytes -= txBytes[i]; + + bucketStart[i] = entry.bucketStart; + setLong(activeTime, i, entry.activeTime); + setLong(rxBytes, i, entry.rxBytes); + setLong(rxPackets, i, entry.rxPackets); + setLong(txBytes, i, entry.txBytes); + setLong(txPackets, i, entry.txPackets); + setLong(operations, i, entry.operations); + + // Apply new values + if (rxBytes != null) totalBytes += rxBytes[i]; + if (txBytes != null) totalBytes += txBytes[i]; + } + /** * Record that data traffic occurred in the given time range. Will * distribute across internal buckets, creating new buckets as needed. diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 0d2fcd0740..b307c5d6fc 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -326,6 +326,10 @@ public class NetworkTemplate implements Parcelable { } } + public boolean matchesSubscriberId(String subscriberId) { + return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); + } + /** * Check if mobile network with matching IMSI. */ diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 03543007c8..8837c157ae 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -28,6 +28,8 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; import static android.text.format.DateUtils.WEEK_IN_MILLIS; +import static com.android.server.net.NetworkStatsService.TAG; + import android.net.NetworkIdentity; import android.net.NetworkStats; import android.net.NetworkStatsHistory; @@ -37,20 +39,24 @@ import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; import android.service.NetworkStatsCollectionStatsProto; +import android.telephony.SubscriptionPlan; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.IntArray; +import android.util.Pair; +import android.util.Slog; import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; +import libcore.io.IoUtils; + import com.google.android.collect.Lists; import com.google.android.collect.Maps; -import libcore.io.IoUtils; - import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -60,9 +66,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.ProtocolException; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Objects; /** @@ -140,6 +148,35 @@ public class NetworkStatsCollection implements FileRotator.Reader { return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE; } + @VisibleForTesting + public long roundUp(long time) { + if (time == Long.MIN_VALUE || time == Long.MAX_VALUE + || time == SubscriptionPlan.TIME_UNKNOWN) { + return time; + } else { + final long mod = time % mBucketDuration; + if (mod > 0) { + time -= mod; + time += mBucketDuration; + } + return time; + } + } + + @VisibleForTesting + public long roundDown(long time) { + if (time == Long.MIN_VALUE || time == Long.MAX_VALUE + || time == SubscriptionPlan.TIME_UNKNOWN) { + return time; + } else { + final long mod = time % mBucketDuration; + if (mod > 0) { + time -= mod; + } + return time; + } + } + public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) { return getRelevantUids(accessLevel, Binder.getCallingUid()); } @@ -165,60 +202,110 @@ public class NetworkStatsCollection implements FileRotator.Reader { * Combine all {@link NetworkStatsHistory} in this collection which match * the requested parameters. */ - public NetworkStatsHistory getHistory( - NetworkTemplate template, int uid, int set, int tag, int fields, - @NetworkStatsAccess.Level int accessLevel) { - return getHistory(template, uid, set, tag, fields, Long.MIN_VALUE, Long.MAX_VALUE, - accessLevel); - } - - /** - * Combine all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. - */ - public NetworkStatsHistory getHistory( - NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end, - @NetworkStatsAccess.Level int accessLevel) { - return getHistory(template, uid, set, tag, fields, start, end, accessLevel, - Binder.getCallingUid()); - } - - /** - * Combine all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. - */ - public NetworkStatsHistory getHistory( - NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end, + public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan, + int uid, int set, int tag, int fields, long start, long end, @NetworkStatsAccess.Level int accessLevel, int callerUid) { if (!NetworkStatsAccess.isAccessibleToUser(uid, callerUid, accessLevel)) { throw new SecurityException("Network stats history of uid " + uid + " is forbidden for caller " + callerUid); } + final int bucketEstimate = (int) ((end - start) / mBucketDuration); final NetworkStatsHistory combined = new NetworkStatsHistory( - mBucketDuration, start == end ? 1 : estimateBuckets(), fields); + mBucketDuration, bucketEstimate, fields); // shortcut when we know stats will be empty if (start == end) return combined; + // Figure out the window of time that we should be augmenting (if any) + long augmentStart = SubscriptionPlan.TIME_UNKNOWN; + long augmentEnd = (augmentPlan != null) ? augmentPlan.getDataUsageTime() + : SubscriptionPlan.TIME_UNKNOWN; + // And if augmenting, we might need to collect more data to adjust with + long collectStart = start; + long collectEnd = end; + + if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) { + final Iterator> it = augmentPlan.cycleIterator(); + while (it.hasNext()) { + final Pair cycle = it.next(); + final long cycleStart = cycle.first.toInstant().toEpochMilli(); + final long cycleEnd = cycle.second.toInstant().toEpochMilli(); + if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) { + augmentStart = cycleStart; + collectStart = Long.min(collectStart, augmentStart); + collectEnd = Long.max(collectEnd, augmentEnd); + break; + } + } + } + + if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) { + // Shrink augmentation window so we don't risk undercounting. + augmentStart = roundUp(augmentStart); + augmentEnd = roundDown(augmentEnd); + // Grow collection window so we get all the stats needed. + collectStart = roundDown(collectStart); + collectEnd = roundUp(collectEnd); + } + for (int i = 0; i < mStats.size(); i++) { final Key key = mStats.keyAt(i); if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag && templateMatches(template, key.ident)) { final NetworkStatsHistory value = mStats.valueAt(i); - combined.recordHistory(value, start, end); + combined.recordHistory(value, collectStart, collectEnd); } } - return combined; - } - /** - * Summarize all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. - */ - public NetworkStats getSummary(NetworkTemplate template, long start, long end, - @NetworkStatsAccess.Level int accessLevel) { - return getSummary(template, start, end, accessLevel, Binder.getCallingUid()); + if (augmentStart != SubscriptionPlan.TIME_UNKNOWN) { + final NetworkStatsHistory.Entry entry = combined.getValues( + augmentStart, augmentEnd, null); + + // If we don't have any recorded data for this time period, give + // ourselves something to scale with. + if (entry.rxBytes == 0 || entry.txBytes == 0) { + combined.recordData(augmentStart, augmentEnd, + new NetworkStats.Entry(1, 0, 1, 0, 0)); + combined.getValues(augmentStart, augmentEnd, entry); + } + + final long rawBytes = entry.rxBytes + entry.txBytes; + final long rawRxBytes = entry.rxBytes; + final long rawTxBytes = entry.txBytes; + final long targetBytes = augmentPlan.getDataUsageBytes(); + final long targetRxBytes = (rawRxBytes * targetBytes) / rawBytes; + final long targetTxBytes = (rawTxBytes * targetBytes) / rawBytes; + + // Scale all matching buckets to reach anchor target + final long beforeTotal = combined.getTotalBytes(); + for (int i = 0; i < combined.size(); i++) { + combined.getValues(i, entry); + if (entry.bucketStart >= augmentStart + && entry.bucketStart + entry.bucketDuration <= augmentEnd) { + entry.rxBytes = (entry.rxBytes * targetRxBytes) / rawRxBytes; + entry.txBytes = (entry.txBytes * targetTxBytes) / rawTxBytes; + // We purposefully clear out packet counters to indicate + // that this data has been augmented. + entry.rxPackets = 0; + entry.txPackets = 0; + combined.setValues(i, entry); + } + } + + final long deltaTotal = combined.getTotalBytes() - beforeTotal; + if (deltaTotal != 0) { + Slog.d(TAG, "Augmented network usage by " + deltaTotal + " bytes"); + } + + // Finally we can slice data as originally requested + final NetworkStatsHistory sliced = new NetworkStatsHistory( + mBucketDuration, bucketEstimate, fields); + sliced.recordHistory(combined, start, end); + return sliced; + } else { + return combined; + } } /** @@ -230,6 +317,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { final long now = System.currentTimeMillis(); final NetworkStats stats = new NetworkStats(end - start, 24); + // shortcut when we know stats will be empty if (start == end) return stats; diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java index a256cbcf90..741c2062bd 100644 --- a/services/core/java/com/android/server/net/NetworkStatsObservers.java +++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java @@ -17,28 +17,26 @@ package com.android.server.net; import static android.net.TrafficStats.MB_IN_BYTES; + import static com.android.internal.util.Preconditions.checkArgument; import android.app.usage.NetworkStatsManager; import android.net.DataUsageRequest; import android.net.NetworkStats; -import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; -import android.os.Binder; import android.os.Bundle; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Messenger; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; -import android.util.IntArray; -import android.util.SparseArray; import android.util.Slog; +import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.VpnInfo; @@ -410,7 +408,7 @@ class NetworkStatsObservers { */ private long getTotalBytesForNetworkUid(NetworkTemplate template, int uid) { try { - NetworkStatsHistory history = mCollection.getHistory(template, uid, + NetworkStatsHistory history = mCollection.getHistory(template, null, uid, NetworkStats.SET_ALL, NetworkStats.TAG_NONE, NetworkStatsHistory.FIELD_ALL, Long.MIN_VALUE /* start */, Long.MAX_VALUE /* end */, diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index 80309e19eb..4bee55ef8b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -20,6 +20,7 @@ import static android.net.NetworkStats.TAG_NONE; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.text.format.DateUtils.YEAR_IN_MILLIS; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; @@ -28,6 +29,7 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.os.Binder; import android.os.DropBoxManager; import android.service.NetworkStatsRecorderProto; import android.util.Log; @@ -38,6 +40,9 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; + +import libcore.io.IoUtils; + import com.google.android.collect.Sets; import java.io.ByteArrayOutputStream; @@ -52,8 +57,6 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Map; -import libcore.io.IoUtils; - /** * Logic to record deltas between periodic {@link NetworkStats} snapshots into * {@link NetworkStatsHistory} that belong to {@link NetworkStatsCollection}. @@ -150,7 +153,7 @@ public class NetworkStatsRecorder { public NetworkStats.Entry getTotalSinceBootLocked(NetworkTemplate template) { return mSinceBoot.getSummary(template, Long.MIN_VALUE, Long.MAX_VALUE, - NetworkStatsAccess.Level.DEVICE).getTotal(null); + NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotal(null); } public NetworkStatsCollection getSinceBoot() { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index b14aa13bfb..4bd927d497 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -26,6 +26,8 @@ import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.METERED_ALL; +import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; @@ -33,10 +35,12 @@ import static android.net.NetworkStats.STATS_PER_IFACE; import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; +import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; +import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; @@ -65,6 +69,7 @@ import static com.android.server.NetworkManagementSocketTagger.setKernelCounterS import android.app.AlarmManager; import android.app.PendingIntent; +import android.app.usage.NetworkStatsManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -104,6 +109,8 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; +import android.telephony.SubscriptionManager; +import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; @@ -139,8 +146,8 @@ import java.util.List; * other system services. */ public class NetworkStatsService extends INetworkStatsService.Stub { - private static final String TAG = "NetworkStats"; - private static final boolean LOGV = false; + static final String TAG = "NetworkStats"; + static final boolean LOGV = false; private static final int MSG_PERFORM_POLL = 1; private static final int MSG_UPDATE_IFACES = 2; @@ -194,6 +201,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public long getPollInterval(); public long getTimeCacheMaxAge(); public boolean getSampleEnabled(); + public boolean getAugmentEnabled(); public static class Config { public final long bucketDuration; @@ -466,18 +474,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public INetworkStatsSession openSession() { - return createSession(null, /* poll on create */ false); + // NOTE: if callers want to get non-augmented data, they should go + // through the public API + return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null); } @Override - public INetworkStatsSession openSessionForUsageStats(final String callingPackage) { - return createSession(callingPackage, /* poll on create */ true); + public INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage) { + return openSessionInternal(flags, callingPackage); } - private INetworkStatsSession createSession(final String callingPackage, boolean pollOnCreate) { + private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { assertBandwidthControlEnabled(); - if (pollOnCreate) { + if ((flags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) { final long ident = Binder.clearCallingIdentity(); try { performPoll(FLAG_PERSIST_ALL); @@ -490,9 +500,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // for its lifetime; when caller closes only weak references remain. return new INetworkStatsSession.Stub() { + private final int mCallingUid = Binder.getCallingUid(); + private final String mCallingPackage = callingPackage; + private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel( + callingPackage); + private NetworkStatsCollection mUidComplete; private NetworkStatsCollection mUidTagComplete; - private String mCallingPackage = callingPackage; private NetworkStatsCollection getUidComplete() { synchronized (mStatsLock) { @@ -514,55 +528,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public int[] getRelevantUids() { - return getUidComplete().getRelevantUids(checkAccessLevel(mCallingPackage)); + return getUidComplete().getRelevantUids(mAccessLevel); } @Override - public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start, - long end) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) { - throw new SecurityException("Calling package " + mCallingPackage - + " cannot access device summary network stats"); - } - NetworkStats result = new NetworkStats(end - start, 1); - final long ident = Binder.clearCallingIdentity(); - try { - // Using access level higher than the one we checked for above. - // Reason is that we are combining usage data in a way that is not PII - // anymore. - result.combineAllValues( - internalGetSummaryForNetwork(template, start, end, - NetworkStatsAccess.Level.DEVICE)); - } finally { - Binder.restoreCallingIdentity(ident); - } - return result; + public NetworkStats getDeviceSummaryForNetwork( + NetworkTemplate template, long start, long end) { + return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, + mCallingUid); } @Override public NetworkStats getSummaryForNetwork( NetworkTemplate template, long start, long end) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - return internalGetSummaryForNetwork(template, start, end, accessLevel); + return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, + mCallingUid); } @Override public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - return internalGetHistoryForNetwork(template, fields, accessLevel); + return internalGetHistoryForNetwork(template, flags, fields, mAccessLevel, + mCallingUid); } @Override public NetworkStats getSummaryForAllUid( NetworkTemplate template, long start, long end, boolean includeTags) { try { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); - final NetworkStats stats = - getUidComplete().getSummary(template, start, end, accessLevel); + final NetworkStats stats = getUidComplete() + .getSummary(template, start, end, mAccessLevel, mCallingUid); if (includeTags) { final NetworkStats tagStats = getUidTagComplete() - .getSummary(template, start, end, accessLevel); + .getSummary(template, start, end, mAccessLevel, mCallingUid); stats.combineAllValues(tagStats); } return stats; @@ -576,13 +573,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStatsHistory getHistoryForUid( NetworkTemplate template, int uid, int set, int tag, int fields) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); + // NOTE: We don't augment UID-level statistics if (tag == TAG_NONE) { - return getUidComplete().getHistory(template, uid, set, tag, fields, - accessLevel); + return getUidComplete().getHistory(template, null, uid, set, tag, fields, + Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid); } else { - return getUidTagComplete().getHistory(template, uid, set, tag, fields, - accessLevel); + return getUidTagComplete().getHistory(template, null, uid, set, tag, fields, + Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid); } } @@ -590,13 +587,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStatsHistory getHistoryIntervalForUid( NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end) { - @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage); + // NOTE: We don't augment UID-level statistics if (tag == TAG_NONE) { - return getUidComplete().getHistory(template, uid, set, tag, fields, start, end, - accessLevel); + return getUidComplete().getHistory(template, null, uid, set, tag, fields, + start, end, mAccessLevel, mCallingUid); } else if (uid == Binder.getCallingUid()) { - return getUidTagComplete().getHistory(template, uid, set, tag, fields, - start, end, accessLevel); + return getUidTagComplete().getHistory(template, null, uid, set, tag, fields, + start, end, mAccessLevel, mCallingUid); } else { throw new SecurityException("Calling package " + mCallingPackage + " cannot access tag information from a different uid"); @@ -616,37 +613,85 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext, Binder.getCallingUid(), callingPackage); } + /** + * Find the most relevant {@link SubscriptionPlan} for the given + * {@link NetworkTemplate} and flags. This is typically used to augment + * local measurement results to match a known anchor from the carrier. + */ + private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) { + SubscriptionPlan plan = null; + if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0 + && (template.getMatchRule() == NetworkTemplate.MATCH_MOBILE_ALL) + && mSettings.getAugmentEnabled()) { + Slog.d(TAG, "Resolving plan for " + template); + final long token = Binder.clearCallingIdentity(); + try { + final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class); + final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); + for (int subId : sm.getActiveSubscriptionIdList()) { + if (template.matchesSubscriberId(tm.getSubscriberId(subId))) { + Slog.d(TAG, "Found active matching subId " + subId); + final List plans = sm.getSubscriptionPlans(subId); + if (!plans.isEmpty()) { + plan = plans.get(0); + } + } + } + } finally { + Binder.restoreCallingIdentity(token); + } + Slog.d(TAG, "Resolved to plan " + plan); + } + return plan; + } + /** * Return network summary, splicing between DEV and XT stats when * appropriate. */ - private NetworkStats internalGetSummaryForNetwork( - NetworkTemplate template, long start, long end, - @NetworkStatsAccess.Level int accessLevel) { + private NetworkStats internalGetSummaryForNetwork(NetworkTemplate template, int flags, + long start, long end, @NetworkStatsAccess.Level int accessLevel, int callingUid) { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. - return mXtStatsCached.getSummary(template, start, end, accessLevel); + final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL, + accessLevel, callingUid); + + final long now = System.currentTimeMillis(); + final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); + + final NetworkStats stats = new NetworkStats(end - start, 1); + stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, + ROAMING_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, + entry.operations)); + return stats; } /** * Return network history, splicing between DEV and XT stats when * appropriate. */ - private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, int fields, - @NetworkStatsAccess.Level int accessLevel) { + private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, + int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. - return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields, accessLevel); + return mXtStatsCached.getHistory(template, resolveSubscriptionPlan(template, flags), + UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE, + accessLevel, callingUid); } @Override public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { - // Special case - since this is for internal use only, don't worry about a full access level - // check and just require the signature/privileged permission. + // Special case - since this is for internal use only, don't worry about + // a full access level check and just require the signature/privileged + // permission. mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); assertBandwidthControlEnabled(); - return internalGetSummaryForNetwork(template, start, end, NetworkStatsAccess.Level.DEVICE) - .getTotalBytes(); + + // NOTE: if callers want to get non-augmented data, they should go + // through the public API + return internalGetSummaryForNetwork(template, + NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end, + NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes(); } @Override @@ -1530,6 +1575,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true); } @Override + public boolean getAugmentEnabled() { + return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true); + } + @Override public Config getDevConfig() { return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), From bcdf1c060a9c9659cb2d9a3e4711f22c2c20ae47 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 1 Sep 2017 11:27:13 -0600 Subject: [PATCH 048/881] Don't over-acquire NPMS locks. We only need to hold mNetworkPoliciesSecondLock when working with subscription plans; before this CL we could end up acquiring the two NPMS locks out of order, resulting in a deadlock. Also annotate objects in NSS that require mStatsLock to be held. Test: builds, boots Bug: 65268076 Change-Id: I06497564424316ef895dc8dceba72ae784781dc3 --- .../server/net/NetworkStatsService.java | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4bd927d497..3af5265e6f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -124,6 +124,7 @@ import android.util.SparseIntArray; import android.util.TrustedTime; import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; @@ -241,12 +242,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); + @GuardedBy("mStatsLock") private NetworkStatsRecorder mDevRecorder; + @GuardedBy("mStatsLock") private NetworkStatsRecorder mXtRecorder; + @GuardedBy("mStatsLock") private NetworkStatsRecorder mUidRecorder; + @GuardedBy("mStatsLock") private NetworkStatsRecorder mUidTagRecorder; /** Cached {@link #mXtRecorder} stats. */ + @GuardedBy("mStatsLock") private NetworkStatsCollection mXtStatsCached; /** Current counter sets for each UID. */ @@ -328,15 +334,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return; } - // create data recorders along with historical rotators - mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false); - mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false); - mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false); - mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true); - - updatePersistThresholds(); - synchronized (mStatsLock) { + // create data recorders along with historical rotators + mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false); + mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false); + mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false); + mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true); + + updatePersistThresholdsLocked(); + // upgrade any legacy stats, migrating them to rotated files maybeUpgradeLegacyStatsLocked(); @@ -674,9 +680,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. - return mXtStatsCached.getHistory(template, resolveSubscriptionPlan(template, flags), - UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE, - accessLevel, callingUid); + final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags); + synchronized (mStatsLock) { + return mXtStatsCached.getHistory(template, augmentPlan, + UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE, + accessLevel, callingUid); + } } @Override @@ -813,7 +822,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { synchronized (mStatsLock) { if (!mSystemReady) return; - updatePersistThresholds(); + updatePersistThresholdsLocked(); mDevRecorder.maybePersistLocked(currentTime); mXtRecorder.maybePersistLocked(currentTime); @@ -869,7 +878,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * reflect current {@link #mPersistThreshold} value. Always defers to * {@link Global} values when defined. */ - private void updatePersistThresholds() { + private void updatePersistThresholdsLocked() { mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold)); mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold)); mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold)); @@ -1311,7 +1320,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { synchronized (mStatsLock) { if (args.length > 0 && "--proto".equals(args[0])) { // In this case ignore all other arguments. - dumpProto(fd); + dumpProtoLocked(fd); return; } @@ -1387,7 +1396,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - private void dumpProto(FileDescriptor fd) { + private void dumpProtoLocked(FileDescriptor fd) { final ProtoOutputStream proto = new ProtoOutputStream(fd); // TODO Right now it writes all history. Should it limit to the "since-boot" log? From e5d8610d8e01e5a9d45be5221a10580f63ff8745 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 1 Sep 2017 12:51:51 -0600 Subject: [PATCH 049/881] Gracefully handle integer overflows. Try sticking with integer-based math as much as possible for speed, but switch to double-based math if we detect that we'd end up causing an overflow. New tests to verify. Test: bit FrameworksNetTests:com.android.server.net.NetworkStatsCollectionTest Bug: 65257769 Change-Id: I1ae35599be134f81850c0a3d86928b057fba1eff --- .../server/net/NetworkStatsCollection.java | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 8837c157ae..4ceb592af0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -177,6 +177,34 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } + /** + * Safely multiple a value by a rational. + *

+ * Internally it uses integer-based math whenever possible, but switches + * over to double-based math if values would overflow. + */ + @VisibleForTesting + public static long multiplySafe(long value, long num, long den) { + long x = value; + long y = num; + + // Logic shamelessly borrowed from Math.multiplyExact() + long r = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + if (((ax | ay) >>> 31 != 0)) { + // Some bits greater than 2^31 that might cause overflow + // Check the result using the divide operator + // and check for the special case of Long.MIN_VALUE * -1 + if (((y != 0) && (r / y != x)) || + (x == Long.MIN_VALUE && y == -1)) { + // Use double math to avoid overflowing + return (long) (((double) num / den) * value); + } + } + return r / den; + } + public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) { return getRelevantUids(accessLevel, Binder.getCallingUid()); } @@ -274,8 +302,8 @@ public class NetworkStatsCollection implements FileRotator.Reader { final long rawRxBytes = entry.rxBytes; final long rawTxBytes = entry.txBytes; final long targetBytes = augmentPlan.getDataUsageBytes(); - final long targetRxBytes = (rawRxBytes * targetBytes) / rawBytes; - final long targetTxBytes = (rawTxBytes * targetBytes) / rawBytes; + final long targetRxBytes = multiplySafe(targetBytes, rawRxBytes, rawBytes); + final long targetTxBytes = multiplySafe(targetBytes, rawTxBytes, rawBytes); // Scale all matching buckets to reach anchor target final long beforeTotal = combined.getTotalBytes(); @@ -283,8 +311,8 @@ public class NetworkStatsCollection implements FileRotator.Reader { combined.getValues(i, entry); if (entry.bucketStart >= augmentStart && entry.bucketStart + entry.bucketDuration <= augmentEnd) { - entry.rxBytes = (entry.rxBytes * targetRxBytes) / rawRxBytes; - entry.txBytes = (entry.txBytes * targetTxBytes) / rawTxBytes; + entry.rxBytes = multiplySafe(targetRxBytes, entry.rxBytes, rawRxBytes); + entry.txBytes = multiplySafe(targetTxBytes, entry.txBytes, rawTxBytes); // We purposefully clear out packet counters to indicate // that this data has been augmented. entry.rxPackets = 0; From 648283ecc7c036ba183f1776370838b07881f117 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 31 Jul 2017 20:35:58 +0900 Subject: [PATCH 050/881] Network Service Discovery test: properly release resources Bug: 32561414 Bug: 62918393 Bug: 62044295 Test: runtest frameworks-net Change-Id: If23993b5e391947ecbdc01677f0a643144794b2b --- core/java/android/net/nsd/NsdManager.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 1e41eea925..535bf675cd 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -21,25 +21,24 @@ import static com.android.internal.util.Preconditions.checkNotNull; import static com.android.internal.util.Preconditions.checkStringNotEmpty; import android.annotation.SdkConstant; -import android.annotation.SystemService; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemService; import android.content.Context; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.os.RemoteException; import android.os.Messenger; -import android.text.TextUtils; +import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; -import java.util.concurrent.CountDownLatch; - import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; +import java.util.concurrent.CountDownLatch; + /** * The Network Service Discovery Manager class provides the API to discover services * on a network. As an example, if device A and device B are connected over a Wi-Fi @@ -244,7 +243,7 @@ public final class NsdManager { return name; } - private static int FIRST_LISTENER_KEY = 1; + private static final int FIRST_LISTENER_KEY = 1; private final INsdManager mService; private final Context mContext; @@ -278,6 +277,7 @@ public final class NsdManager { @VisibleForTesting public void disconnect() { mAsyncChannel.disconnect(); + mHandler.getLooper().quitSafely(); } /** @@ -650,7 +650,7 @@ public final class NsdManager { private static void checkServiceInfo(NsdServiceInfo serviceInfo) { checkNotNull(serviceInfo, "NsdServiceInfo cannot be null"); - checkStringNotEmpty(serviceInfo.getServiceName(),"Service name cannot be empty"); + checkStringNotEmpty(serviceInfo.getServiceName(), "Service name cannot be empty"); checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty"); } } From d18ca7c9fa1ee496dce80fb718717f88a77d0571 Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Mon, 7 Aug 2017 15:47:35 +0900 Subject: [PATCH 051/881] NetworkStats: more robust subtraction for deltas This patch ensures that subtract() between two NetworkStats object will return a delta with no negative entries in all cases. When the stats delta contains some negative values, there are clamped to 0. Some logging is added when this happens. This is what's expected by NetworkStatsHistory#recordData(). Bug: 64365917 Bug: 65439160 Test: runtest frameworks-net Merged-In: I16e97e73f600225f80e0ce517e80c07c6f399196 Merged-In: I2ac0bc3914cb65ae8ee27921856d698dc59624b2 Merged-In: I67d5dc4b52b254748ff17fe1e16c2eeb1d03c30d Merged-In: Ib488fb034f72c92f19916490981342a3ef2eb33b (cherry picked from commit ce144deb7b824a4c2fbc0d48e664267a74c61ba6) Change-Id: Ic86b65a65a2517c871221f8784088ec1de18f534 --- core/java/android/net/NetworkStats.java | 45 ++++++++++++------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 0780af602b..171adc054b 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -677,36 +677,33 @@ public class NetworkStats implements Parcelable { entry.tag = left.tag[i]; entry.metered = left.metered[i]; entry.roaming = left.roaming[i]; + entry.rxBytes = left.rxBytes[i]; + entry.rxPackets = left.rxPackets[i]; + entry.txBytes = left.txBytes[i]; + entry.txPackets = left.txPackets[i]; + entry.operations = left.operations[i]; // find remote row that matches, and subtract final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, entry.roaming, i); - if (j == -1) { - // newly appearing row, return entire value - entry.rxBytes = left.rxBytes[i]; - entry.rxPackets = left.rxPackets[i]; - entry.txBytes = left.txBytes[i]; - entry.txPackets = left.txPackets[i]; - entry.operations = left.operations[i]; - } else { - // existing row, subtract remote value - entry.rxBytes = left.rxBytes[i] - right.rxBytes[j]; - entry.rxPackets = left.rxPackets[i] - right.rxPackets[j]; - entry.txBytes = left.txBytes[i] - right.txBytes[j]; - entry.txPackets = left.txPackets[i] - right.txPackets[j]; - entry.operations = left.operations[i] - right.operations[j]; + if (j != -1) { + // Found matching row, subtract remote value. + entry.rxBytes -= right.rxBytes[j]; + entry.rxPackets -= right.rxPackets[j]; + entry.txBytes -= right.txBytes[j]; + entry.txPackets -= right.txPackets[j]; + entry.operations -= right.operations[j]; + } - if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 - || entry.txPackets < 0 || entry.operations < 0) { - if (observer != null) { - observer.foundNonMonotonic(left, i, right, j, cookie); - } - entry.rxBytes = Math.max(entry.rxBytes, 0); - entry.rxPackets = Math.max(entry.rxPackets, 0); - entry.txBytes = Math.max(entry.txBytes, 0); - entry.txPackets = Math.max(entry.txPackets, 0); - entry.operations = Math.max(entry.operations, 0); + if (entry.isNegative()) { + if (observer != null) { + observer.foundNonMonotonic(left, i, right, j, cookie); } + entry.rxBytes = Math.max(entry.rxBytes, 0); + entry.rxPackets = Math.max(entry.rxPackets, 0); + entry.txBytes = Math.max(entry.txBytes, 0); + entry.txPackets = Math.max(entry.txPackets, 0); + entry.operations = Math.max(entry.operations, 0); } result.addValues(entry); From 2e2cec680abb06a580bf2332d30ae2f587d09d66 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 11 Sep 2017 19:50:19 -0700 Subject: [PATCH 052/881] Re-Enable Starting of the IpSecService This reverts commit 41004ff4113dc9175c993638a47af602af6d8a98. Bug: 64800246 Test: compilation Change-Id: I4f5e3cd23001b9d94b3f6dc9fcfe731a90650e6e --- core/java/android/net/IpSecAlgorithm.java | 2 ++ core/java/android/net/IpSecManager.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 5ae3400361..7e956bf388 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -19,7 +19,9 @@ import android.annotation.StringDef; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; + import com.android.internal.util.HexDump; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 2f791e151b..00cacbcd71 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -25,7 +25,9 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.AndroidException; import android.util.Log; + import dalvik.system.CloseGuard; + import java.io.FileDescriptor; import java.io.IOException; import java.net.DatagramSocket; From 004a59a6ab57e3079556b4b9f82e51973e58d40c Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 11 Sep 2017 19:53:33 -0700 Subject: [PATCH 053/881] Re-Expose IpSecService API Surface Note, This reverts commit faf8a9191762444f659164ce633bdfec1ab8de62. Bug: 64800246 Test: compilation Change-Id: I709d4c476647cfe9f6b982fc373f8d76018b3922 --- core/java/android/net/IpSecAlgorithm.java | 2 -- core/java/android/net/IpSecManager.java | 4 +++- core/java/android/net/IpSecTransform.java | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 7e956bf388..ead406c20c 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -28,8 +28,6 @@ import java.lang.annotation.RetentionPolicy; /** * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to * RFC 4301. - * - * @hide */ public final class IpSecAlgorithm implements Parcelable { diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 00cacbcd71..d7908c8cee 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -38,7 +38,9 @@ import java.net.Socket; * This class contains methods for managing IPsec sessions, which will perform kernel-space * encryption and decryption of socket or Network traffic. * - * @hide + *

An IpSecManager may be obtained by calling {@link + * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link + * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE} */ @SystemService(Context.IPSEC_SERVICE) public final class IpSecManager { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index cfbac58bbd..62fd65b9c1 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -26,9 +26,12 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; + import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; + import dalvik.system.CloseGuard; + import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,8 +46,6 @@ import java.net.InetAddress; * *

An IpSecTransform may either represent a tunnel mode transform that operates on a wide array * of traffic or may represent a transport mode transform operating on a Socket or Sockets. - * - * @hide */ public final class IpSecTransform implements AutoCloseable { private static final String TAG = "IpSecTransform"; From ed813205fa396982733dd8a1a164d2fdbbe0cd72 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 23 Aug 2017 13:46:33 -0700 Subject: [PATCH 054/881] Input Validation for IpSecService All of the input to IpSecService over the Binder interface needs to be validated both for sanity and for safety. -Sanity check all the parameters coming from binder. -Added setters for IpSecConfig to decouple the test from the IpSecManager. This was needed because the input validation caused the tests to fail due to a null parameter that was previously un-tested. -Added the mode flag to the IpSecConfig bundle this oversight was found during testing. -Expose the getResourceId() methods for testing in UdpEncapsulationSocket, SecurityParameterIndex, and IpSecTransform classes. -Remove the unneeded getIpSecConfig() from IpSecTransform: unneeded now that we can synthesize configs. Bug: 38397094 Test: runtest frameworks-net Change-Id: I5241fc7fbfa9816d54219acd8d81a9f7eef10dd4 --- core/java/android/net/IpSecConfig.java | 244 +++++++++++------- core/java/android/net/IpSecManager.java | 8 +- core/java/android/net/IpSecTransform.java | 103 ++------ .../java/com/android/server/IpSecService.java | 151 ++++++++--- 4 files changed, 299 insertions(+), 207 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 5a5c740c7a..56224afc27 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -17,105 +17,163 @@ package android.net; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; -import java.net.InetAddress; -import java.net.UnknownHostException; + +import com.android.internal.annotations.VisibleForTesting; /** @hide */ public final class IpSecConfig implements Parcelable { private static final String TAG = "IpSecConfig"; - //MODE_TRANSPORT or MODE_TUNNEL - int mode; + // MODE_TRANSPORT or MODE_TUNNEL + private int mMode = IpSecTransform.MODE_TRANSPORT; - // For tunnel mode - InetAddress localAddress; + // Needs to be valid only for tunnel mode + // Preventing this from being null simplifies Java->Native binder + private String mLocalAddress = ""; - InetAddress remoteAddress; + // Preventing this from being null simplifies Java->Native binder + private String mRemoteAddress = ""; - // Limit selection by network interface - Network network; + // The underlying network interface that represents the "gateway" Network + // for outbound packets. It may also be used to select packets. + private Network mNetwork; public static class Flow { // Minimum requirements for identifying a transform // SPI identifying the IPsec flow in packet processing // and a remote IP address - int spiResourceId; + private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID; // Encryption Algorithm - IpSecAlgorithm encryption; + private IpSecAlgorithm mEncryption; // Authentication Algorithm - IpSecAlgorithm authentication; + private IpSecAlgorithm mAuthentication; @Override public String toString() { return new StringBuilder() - .append("{spiResourceId=") - .append(spiResourceId) - .append(", encryption=") - .append(encryption) - .append(", authentication=") - .append(authentication) + .append("{mSpiResourceId=") + .append(mSpiResourceId) + .append(", mEncryption=") + .append(mEncryption) + .append(", mAuthentication=") + .append(mAuthentication) .append("}") .toString(); } } - final Flow[] flow = new Flow[] {new Flow(), new Flow()}; + private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()}; // For tunnel mode IPv4 UDP Encapsulation // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE - int encapType; - int encapLocalPortResourceId; - int encapRemotePort; + private int mEncapType = IpSecTransform.ENCAP_NONE; + private int mEncapSocketResourceId = IpSecManager.INVALID_RESOURCE_ID; + private int mEncapRemotePort; // An interval, in seconds between the NattKeepalive packets - int nattKeepaliveInterval; + private int mNattKeepaliveInterval; + + /** Set the mode for this IPsec transform */ + public void setMode(int mode) { + mMode = mode; + } + + /** Set the local IP address for Tunnel mode */ + public void setLocalAddress(String localAddress) { + if (localAddress == null) { + throw new IllegalArgumentException("localAddress may not be null!"); + } + mLocalAddress = localAddress; + } + + /** Set the remote IP address for this IPsec transform */ + public void setRemoteAddress(String remoteAddress) { + if (remoteAddress == null) { + throw new IllegalArgumentException("remoteAddress may not be null!"); + } + mRemoteAddress = remoteAddress; + } + + /** Set the SPI for a given direction by resource ID */ + public void setSpiResourceId(int direction, int resourceId) { + mFlow[direction].mSpiResourceId = resourceId; + } + + /** Set the encryption algorithm for a given direction */ + public void setEncryption(int direction, IpSecAlgorithm encryption) { + mFlow[direction].mEncryption = encryption; + } + + /** Set the authentication algorithm for a given direction */ + public void setAuthentication(int direction, IpSecAlgorithm authentication) { + mFlow[direction].mAuthentication = authentication; + } + + public void setNetwork(Network network) { + mNetwork = network; + } + + public void setEncapType(int encapType) { + mEncapType = encapType; + } + + public void setEncapSocketResourceId(int resourceId) { + mEncapSocketResourceId = resourceId; + } + + public void setEncapRemotePort(int port) { + mEncapRemotePort = port; + } + + public void setNattKeepaliveInterval(int interval) { + mNattKeepaliveInterval = interval; + } // Transport or Tunnel public int getMode() { - return mode; + return mMode; } - public InetAddress getLocalAddress() { - return localAddress; + public String getLocalAddress() { + return mLocalAddress; } public int getSpiResourceId(int direction) { - return flow[direction].spiResourceId; + return mFlow[direction].mSpiResourceId; } - public InetAddress getRemoteAddress() { - return remoteAddress; + public String getRemoteAddress() { + return mRemoteAddress; } public IpSecAlgorithm getEncryption(int direction) { - return flow[direction].encryption; + return mFlow[direction].mEncryption; } public IpSecAlgorithm getAuthentication(int direction) { - return flow[direction].authentication; + return mFlow[direction].mAuthentication; } public Network getNetwork() { - return network; + return mNetwork; } public int getEncapType() { - return encapType; + return mEncapType; } - public int getEncapLocalResourceId() { - return encapLocalPortResourceId; + public int getEncapSocketResourceId() { + return mEncapSocketResourceId; } public int getEncapRemotePort() { - return encapRemotePort; + return mEncapRemotePort; } public int getNattKeepaliveInterval() { - return nattKeepaliveInterval; + return mNattKeepaliveInterval; } // Parcelable Methods @@ -127,82 +185,68 @@ public final class IpSecConfig implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { - // TODO: Use a byte array or other better method for storing IPs that can also include scope - out.writeString((localAddress != null) ? localAddress.getHostAddress() : null); - // TODO: Use a byte array or other better method for storing IPs that can also include scope - out.writeString((remoteAddress != null) ? remoteAddress.getHostAddress() : null); - out.writeParcelable(network, flags); - out.writeInt(flow[IpSecTransform.DIRECTION_IN].spiResourceId); - out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].encryption, flags); - out.writeParcelable(flow[IpSecTransform.DIRECTION_IN].authentication, flags); - out.writeInt(flow[IpSecTransform.DIRECTION_OUT].spiResourceId); - out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].encryption, flags); - out.writeParcelable(flow[IpSecTransform.DIRECTION_OUT].authentication, flags); - out.writeInt(encapType); - out.writeInt(encapLocalPortResourceId); - out.writeInt(encapRemotePort); + out.writeInt(mMode); + out.writeString(mLocalAddress); + out.writeString(mRemoteAddress); + out.writeParcelable(mNetwork, flags); + out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags); + out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags); + out.writeInt(mEncapType); + out.writeInt(mEncapSocketResourceId); + out.writeInt(mEncapRemotePort); } - // Package Private: Used by the IpSecTransform.Builder; - // there should be no public constructor for this object - IpSecConfig() {} - - private static InetAddress readInetAddressFromParcel(Parcel in) { - String addrString = in.readString(); - if (addrString == null) { - return null; - } - try { - return InetAddress.getByName(addrString); - } catch (UnknownHostException e) { - Log.wtf(TAG, "Invalid IpAddress " + addrString); - return null; - } - } + @VisibleForTesting + public IpSecConfig() {} private IpSecConfig(Parcel in) { - localAddress = readInetAddressFromParcel(in); - remoteAddress = readInetAddressFromParcel(in); - network = (Network) in.readParcelable(Network.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_IN].spiResourceId = in.readInt(); - flow[IpSecTransform.DIRECTION_IN].encryption = + mMode = in.readInt(); + mLocalAddress = in.readString(); + mRemoteAddress = in.readString(); + mNetwork = (Network) in.readParcelable(Network.class.getClassLoader()); + mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt(); + mFlow[IpSecTransform.DIRECTION_IN].mEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_IN].authentication = + mFlow[IpSecTransform.DIRECTION_IN].mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_OUT].spiResourceId = in.readInt(); - flow[IpSecTransform.DIRECTION_OUT].encryption = + mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt(); + mFlow[IpSecTransform.DIRECTION_OUT].mEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - flow[IpSecTransform.DIRECTION_OUT].authentication = + mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - encapType = in.readInt(); - encapLocalPortResourceId = in.readInt(); - encapRemotePort = in.readInt(); + mEncapType = in.readInt(); + mEncapSocketResourceId = in.readInt(); + mEncapRemotePort = in.readInt(); } @Override public String toString() { StringBuilder strBuilder = new StringBuilder(); strBuilder - .append("{mode=") - .append(mode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT") - .append(", localAddress=") - .append(localAddress) - .append(", remoteAddress=") - .append(remoteAddress) - .append(", network=") - .append(network) - .append(", encapType=") - .append(encapType) - .append(", encapLocalPortResourceId=") - .append(encapLocalPortResourceId) - .append(", encapRemotePort=") - .append(encapRemotePort) - .append(", nattKeepaliveInterval=") - .append(nattKeepaliveInterval) - .append(", flow[OUT]=") - .append(flow[IpSecTransform.DIRECTION_OUT]) - .append(", flow[IN]=") - .append(flow[IpSecTransform.DIRECTION_IN]) + .append("{mMode=") + .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT") + .append(", mLocalAddress=") + .append(mLocalAddress) + .append(", mRemoteAddress=") + .append(mRemoteAddress) + .append(", mNetwork=") + .append(mNetwork) + .append(", mEncapType=") + .append(mEncapType) + .append(", mEncapSocketResourceId=") + .append(mEncapSocketResourceId) + .append(", mEncapRemotePort=") + .append(mEncapRemotePort) + .append(", mNattKeepaliveInterval=") + .append(mNattKeepaliveInterval) + .append(", mFlow[OUT]=") + .append(mFlow[IpSecTransform.DIRECTION_OUT]) + .append(", mFlow[IN]=") + .append(mFlow[IpSecTransform.DIRECTION_IN]) .append("}"); return strBuilder.toString(); diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index d7908c8cee..d7b325613f 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -26,6 +26,8 @@ import android.os.RemoteException; import android.util.AndroidException; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + import dalvik.system.CloseGuard; import java.io.FileDescriptor; @@ -188,7 +190,8 @@ public final class IpSecManager { } /** @hide */ - int getResourceId() { + @VisibleForTesting + public int getResourceId() { return mResourceId; } } @@ -489,7 +492,8 @@ public final class IpSecManager { } /** @hide */ - int getResourceId() { + @VisibleForTesting + public int getResourceId() { return mResourceId; } }; diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 62fd65b9c1..529cf1a495 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -68,10 +68,10 @@ public final class IpSecTransform implements AutoCloseable { public @interface TransformDirection {} /** @hide */ - public static final int MODE_TUNNEL = 0; + public static final int MODE_TRANSPORT = 0; /** @hide */ - public static final int MODE_TRANSPORT = 1; + public static final int MODE_TUNNEL = 1; /** @hide */ public static final int ENCAP_NONE = 0; @@ -113,7 +113,11 @@ public final class IpSecTransform implements AutoCloseable { return IIpSecService.Stub.asInterface(b); } - private void checkResultStatusAndThrow(int status) + /** + * Checks the result status and throws an appropriate exception if + * the status is not Status.OK. + */ + private void checkResultStatus(int status) throws IOException, IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException { switch (status) { @@ -141,7 +145,7 @@ public final class IpSecTransform implements AutoCloseable { IpSecTransformResponse result = svc.createTransportModeTransform(mConfig, new Binder()); int status = result.status; - checkResultStatusAndThrow(status); + checkResultStatus(status); mResourceId = result.resourceId; /* Keepalive will silently fail if not needed by the config; but, if needed and @@ -243,61 +247,20 @@ public final class IpSecTransform implements AutoCloseable { /* Package */ void startKeepalive(Context c) { - // FIXME: NO_KEEPALIVE needs to be a constant - if (mConfig.getNattKeepaliveInterval() == 0) { - return; - } - - ConnectivityManager cm = - (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); - - if (mKeepalive != null) { - Log.wtf(TAG, "Keepalive already started for this IpSecTransform."); - return; - } - - synchronized (mKeepaliveSyncLock) { - mKeepalive = - cm.startNattKeepalive( - mConfig.getNetwork(), - mConfig.getNattKeepaliveInterval(), - mKeepaliveCallback, - mConfig.getLocalAddress(), - 0x1234, /* FIXME: get the real port number again, - which we need to retrieve from the provided - EncapsulationSocket, and which isn't currently - stashed in IpSecConfig */ - mConfig.getRemoteAddress()); - try { - // FIXME: this is still a horrible way to fudge the synchronous callback - mKeepaliveSyncLock.wait(2000); - } catch (InterruptedException e) { - } - } - if (mKeepaliveStatus != ConnectivityManager.PacketKeepalive.SUCCESS) { - throw new UnsupportedOperationException("Packet Keepalive cannot be started"); + if (mConfig.getNattKeepaliveInterval() != 0) { + Log.wtf(TAG, "Keepalive not yet supported."); } } - /* Package */ - int getResourceId() { + /** @hide */ + @VisibleForTesting + public int getResourceId() { return mResourceId; } /* Package */ void stopKeepalive() { - if (mKeepalive == null) { - return; - } - mKeepalive.stop(); - synchronized (mKeepaliveSyncLock) { - if (mKeepaliveStatus == ConnectivityManager.PacketKeepalive.SUCCESS) { - try { - mKeepaliveSyncLock.wait(2000); - } catch (InterruptedException e) { - } - } - } + return; } /** @@ -323,7 +286,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setEncryption( @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.flow[direction].encryption = algo; + mConfig.setEncryption(direction, algo); return this; } @@ -338,7 +301,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setAuthentication( @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.flow[direction].authentication = algo; + mConfig.setAuthentication(direction, algo); return this; } @@ -361,9 +324,7 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setSpi( @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) { - // TODO: convert to using the resource Id of the SPI. Then build() can validate - // the owner in the IpSecService - mConfig.flow[direction].spiResourceId = spi.getResourceId(); + mConfig.setSpiResourceId(direction, spi.getResourceId()); return this; } @@ -378,7 +339,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi public IpSecTransform.Builder setUnderlyingNetwork(Network net) { - mConfig.network = net; + mConfig.setNetwork(net); return this; } @@ -395,10 +356,9 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setIpv4Encapsulation( IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { - // TODO: check encap type is valid. - mConfig.encapType = ENCAP_ESPINUDP; - mConfig.encapLocalPortResourceId = localSocket.getResourceId(); - mConfig.encapRemotePort = remotePort; + mConfig.setEncapType(ENCAP_ESPINUDP); + mConfig.setEncapSocketResourceId(localSocket.getResourceId()); + mConfig.setEncapRemotePort(remotePort); return this; } @@ -416,7 +376,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) { - mConfig.nattKeepaliveInterval = intervalSeconds; + mConfig.setNattKeepaliveInterval(intervalSeconds); return this; } @@ -451,8 +411,8 @@ public final class IpSecTransform implements AutoCloseable { IpSecManager.SpiUnavailableException, IOException { //FIXME: argument validation here //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); - mConfig.mode = MODE_TRANSPORT; - mConfig.remoteAddress = remoteAddress; + mConfig.setMode(MODE_TRANSPORT); + mConfig.setRemoteAddress(remoteAddress.getHostAddress()); return new IpSecTransform(mContext, mConfig).activate(); } @@ -473,9 +433,9 @@ public final class IpSecTransform implements AutoCloseable { InetAddress localAddress, InetAddress remoteAddress) { //FIXME: argument validation here //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); - mConfig.localAddress = localAddress; - mConfig.remoteAddress = remoteAddress; - mConfig.mode = MODE_TUNNEL; + mConfig.setLocalAddress(localAddress.getHostAddress()); + mConfig.setRemoteAddress(remoteAddress.getHostAddress()); + mConfig.setMode(MODE_TUNNEL); return new IpSecTransform(mContext, mConfig); } @@ -489,14 +449,5 @@ public final class IpSecTransform implements AutoCloseable { mContext = context; mConfig = new IpSecConfig(); } - - /** - * Return an {@link IpSecConfig} object for testing purposes. - * @hide - */ - @VisibleForTesting - public IpSecConfig getIpSecConfig() { - return mConfig; - } } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 305683139f..555874c0e1 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -33,6 +33,7 @@ import android.net.IpSecSpiResponse; import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecUdpEncapResponse; +import android.net.NetworkUtils; import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; @@ -42,11 +43,14 @@ import android.os.ServiceSpecificException; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseArray; + import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; + import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -54,6 +58,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.concurrent.atomic.AtomicInteger; + import libcore.io.IoUtils; /** @hide */ @@ -252,7 +257,11 @@ public class IpSecService extends IIpSecService.Stub { return (mReferenceCount.get() > 0); } - public void checkOwnerOrSystemAndThrow() { + /** + * Ensures that the caller is either the owner of this resource or has the system UID and + * throws a SecurityException otherwise. + */ + public void checkOwnerOrSystem() { if (uid != Binder.getCallingUid() && android.os.Process.SYSTEM_UID != Binder.getCallingUid()) { throw new SecurityException("Only the owner may access managed resources!"); @@ -340,7 +349,7 @@ public class IpSecService extends IIpSecService.Stub { // The value should never be null unless the resource doesn't exist // (since we do not allow null resources to be added). if (val != null) { - val.checkOwnerOrSystemAndThrow(); + val.checkOwnerOrSystem(); } return val; } @@ -405,12 +414,8 @@ public class IpSecService extends IIpSecService.Stub { .ipSecDeleteSecurityAssociation( mResourceId, direction, - (mConfig.getLocalAddress() != null) - ? mConfig.getLocalAddress().getHostAddress() - : "", - (mConfig.getRemoteAddress() != null) - ? mConfig.getRemoteAddress().getHostAddress() - : "", + mConfig.getLocalAddress(), + mConfig.getRemoteAddress(), spi); } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception @@ -638,11 +643,45 @@ public class IpSecService extends IIpSecService.Stub { } } + /** + * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be + * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1. + */ + private static void checkInetAddress(String inetAddress) { + if (TextUtils.isEmpty(inetAddress)) { + throw new IllegalArgumentException("Unspecified address"); + } + + InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress); + + if (checkAddr.isAnyLocalAddress()) { + throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress); + } + } + + /** + * Checks the user-provided direction field and throws an IllegalArgumentException if it is not + * DIRECTION_IN or DIRECTION_OUT + */ + private static void checkDirection(int direction) { + switch (direction) { + case IpSecTransform.DIRECTION_OUT: + case IpSecTransform.DIRECTION_IN: + return; + } + throw new IllegalArgumentException("Invalid Direction: " + direction); + } + @Override /** Get a new SPI and maintain the reservation in the system server */ public synchronized IpSecSpiResponse reserveSecurityParameterIndex( int direction, String remoteAddress, int requestedSpi, IBinder binder) throws RemoteException { + checkDirection(direction); + checkInetAddress(remoteAddress); + /* requestedSpi can be anything in the int range, so no check is needed. */ + checkNotNull(binder, "Null Binder passed to reserveSecurityParameterIndex"); + int resourceId = mNextResourceId.getAndIncrement(); int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; @@ -651,9 +690,7 @@ public class IpSecService extends IIpSecService.Stub { try { if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).spi.isAvailable()) { return new IpSecSpiResponse( - IpSecManager.Status.RESOURCE_UNAVAILABLE, - INVALID_RESOURCE_ID, - spi); + IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi); } spi = mSrvConfig @@ -751,6 +788,8 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException( "Specified port number must be a valid non-reserved UDP port"); } + checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); + int resourceId = mNextResourceId.getAndIncrement(); FileDescriptor sockFd = null; try { @@ -791,6 +830,67 @@ public class IpSecService extends IIpSecService.Stub { releaseManagedResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); } + /** + * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an + * IllegalArgumentException if they are not. + */ + private void checkIpSecConfig(IpSecConfig config) { + if (config.getLocalAddress() == null) { + throw new IllegalArgumentException("Invalid null Local InetAddress"); + } + + if (config.getRemoteAddress() == null) { + throw new IllegalArgumentException("Invalid null Remote InetAddress"); + } + + switch (config.getMode()) { + case IpSecTransform.MODE_TRANSPORT: + if (!config.getLocalAddress().isEmpty()) { + throw new IllegalArgumentException("Non-empty Local Address"); + } + // Must be valid, and not a wildcard + checkInetAddress(config.getRemoteAddress()); + break; + case IpSecTransform.MODE_TUNNEL: + break; + default: + throw new IllegalArgumentException( + "Invalid IpSecTransform.mode: " + config.getMode()); + } + + switch (config.getEncapType()) { + case IpSecTransform.ENCAP_NONE: + break; + case IpSecTransform.ENCAP_ESPINUDP: + case IpSecTransform.ENCAP_ESPINUDP_NON_IKE: + if (mUdpSocketRecords.get(config.getEncapSocketResourceId()) == null) { + throw new IllegalStateException( + "No Encapsulation socket for Resource Id: " + + config.getEncapSocketResourceId()); + } + + int port = config.getEncapRemotePort(); + if (port <= 0 || port > 0xFFFF) { + throw new IllegalArgumentException("Invalid remote UDP port: " + port); + } + break; + default: + throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType()); + } + + for (int direction : DIRECTIONS) { + IpSecAlgorithm crypt = config.getEncryption(direction); + IpSecAlgorithm auth = config.getAuthentication(direction); + if (crypt == null && auth == null) { + throw new IllegalArgumentException("Encryption and Authentication are both null"); + } + + if (mSpiRecords.get(config.getSpiResourceId(direction)) == null) { + throw new IllegalStateException("No SPI for specified Resource Id"); + } + } + } + /** * Create a transport mode transform, which represent two security associations (one in each * direction) in the kernel. The transform will be cached by the system server and must be freed @@ -801,17 +901,19 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized IpSecTransformResponse createTransportModeTransform( IpSecConfig c, IBinder binder) throws RemoteException { + checkIpSecConfig(c); + checkNotNull(binder, "Null Binder passed to createTransportModeTransform"); int resourceId = mNextResourceId.getAndIncrement(); if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).transform.isAvailable()) { return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } SpiRecord[] spis = new SpiRecord[DIRECTIONS.length]; - // TODO: Basic input validation here since it's coming over the Binder + int encapType, encapLocalPort = 0, encapRemotePort = 0; UdpSocketRecord socketRecord = null; encapType = c.getEncapType(); if (encapType != IpSecTransform.ENCAP_NONE) { - socketRecord = mUdpSocketRecords.get(c.getEncapLocalResourceId()); + socketRecord = mUdpSocketRecords.get(c.getEncapSocketResourceId()); encapLocalPort = socketRecord.getPort(); encapRemotePort = c.getEncapRemotePort(); } @@ -823,20 +925,15 @@ public class IpSecService extends IIpSecService.Stub { spis[direction] = mSpiRecords.get(c.getSpiResourceId(direction)); int spi = spis[direction].getSpi(); try { - mSrvConfig.getNetdInstance() + mSrvConfig + .getNetdInstance() .ipSecAddSecurityAssociation( resourceId, c.getMode(), direction, - (c.getLocalAddress() != null) - ? c.getLocalAddress().getHostAddress() - : "", - (c.getRemoteAddress() != null) - ? c.getRemoteAddress().getHostAddress() - : "", - (c.getNetwork() != null) - ? c.getNetwork().getNetworkHandle() - : 0, + c.getLocalAddress(), + c.getRemoteAddress(), + (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0, spi, (auth != null) ? auth.getName() : "", (auth != null) ? auth.getKey() : null, @@ -899,12 +996,8 @@ public class IpSecService extends IIpSecService.Stub { socket.getFileDescriptor(), resourceId, direction, - (c.getLocalAddress() != null) - ? c.getLocalAddress().getHostAddress() - : "", - (c.getRemoteAddress() != null) - ? c.getRemoteAddress().getHostAddress() - : "", + c.getLocalAddress(), + c.getRemoteAddress(), info.getSpiRecord(direction).getSpi()); } } catch (ServiceSpecificException e) { From ffc2fa53f59bb3ae23a87a3834565a358100f414 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 25 Sep 2017 19:33:13 -0700 Subject: [PATCH 055/881] Add equals() for IpSecAlgorithm and IpSecConfig Add equality testing methods to support tests for parceling and un-parceling IpSecConfig. Bug: 38397094 Test: runtest -x IpSecConfigTest.java Change-Id: I31e318334d39ed6e9daf5ec8f3be7dcec75e12ad --- core/java/android/net/IpSecAlgorithm.java | 17 ++++++++------ core/java/android/net/IpSecConfig.java | 27 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index ead406c20c..79310e295a 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -24,6 +24,7 @@ import com.android.internal.util.HexDump; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Arrays; /** * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to @@ -75,13 +76,7 @@ public final class IpSecAlgorithm implements Parcelable { public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; /** @hide */ - @StringDef({ - CRYPT_AES_CBC, - AUTH_HMAC_MD5, - AUTH_HMAC_SHA1, - AUTH_HMAC_SHA256, - AUTH_HMAC_SHA512 - }) + @StringDef({CRYPT_AES_CBC, AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, AUTH_HMAC_SHA512}) @Retention(RetentionPolicy.SOURCE) public @interface AlgorithmName {} @@ -197,4 +192,12 @@ public final class IpSecAlgorithm implements Parcelable { .append("}") .toString(); } + + /** package */ + static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return (lhs.mName.equals(rhs.mName) + && Arrays.equals(lhs.mKey, rhs.mKey) + && lhs.mTruncLenBits == rhs.mTruncLenBits); + } }; diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 56224afc27..ceccc07c3c 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -62,6 +62,13 @@ public final class IpSecConfig implements Parcelable { .append("}") .toString(); } + + static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return (lhs.mSpiResourceId == rhs.mSpiResourceId + && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) + && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)); + } } private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()}; @@ -198,6 +205,7 @@ public final class IpSecConfig implements Parcelable { out.writeInt(mEncapType); out.writeInt(mEncapSocketResourceId); out.writeInt(mEncapRemotePort); + out.writeInt(mNattKeepaliveInterval); } @VisibleForTesting @@ -221,6 +229,7 @@ public final class IpSecConfig implements Parcelable { mEncapType = in.readInt(); mEncapSocketResourceId = in.readInt(); mEncapRemotePort = in.readInt(); + mNattKeepaliveInterval = in.readInt(); } @Override @@ -262,4 +271,22 @@ public final class IpSecConfig implements Parcelable { return new IpSecConfig[size]; } }; + + @VisibleForTesting + public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return (lhs.mMode == rhs.mMode + && lhs.mLocalAddress.equals(rhs.mLocalAddress) + && lhs.mRemoteAddress.equals(rhs.mRemoteAddress) + && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork)) + || (lhs.mNetwork == rhs.mNetwork)) + && lhs.mEncapType == rhs.mEncapType + && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId + && lhs.mEncapRemotePort == rhs.mEncapRemotePort + && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval + && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT], + rhs.mFlow[IpSecTransform.DIRECTION_OUT]) + && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN], + rhs.mFlow[IpSecTransform.DIRECTION_IN])); + } } From 71d62fd62392ce8a4e86e2d0d6ee7dc55d8c7be8 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 4 Oct 2017 12:58:55 -0700 Subject: [PATCH 056/881] Cosmetic Cleanups for IpSecService This is a follow-up CL to address comments on aosp/466677 -Rename ManagedResourceArray.get() -Comment cleanup Bug: 38397094 Test: runtest frameworks-net Change-Id: I6fbdd89c4a864fe1d8a19c68947f582d7b1f0f21 --- core/java/android/net/IpSecConfig.java | 3 ++- core/java/android/net/IpSecTransform.java | 2 -- .../java/com/android/server/IpSecService.java | 15 ++++++++------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index ceccc07c3c..632b7fc07f 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -34,7 +34,7 @@ public final class IpSecConfig implements Parcelable { // Preventing this from being null simplifies Java->Native binder private String mRemoteAddress = ""; - // The underlying network interface that represents the "gateway" Network + // The underlying Network that represents the "gateway" Network // for outbound packets. It may also be used to select packets. private Network mNetwork; @@ -273,6 +273,7 @@ public final class IpSecConfig implements Parcelable { }; @VisibleForTesting + /** Equals method used for testing */ public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) { if (lhs == null || rhs == null) return (lhs == rhs); return (lhs.mMode == rhs.mMode diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 529cf1a495..e15a2c672c 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -409,8 +409,6 @@ public final class IpSecTransform implements AutoCloseable { public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress) throws IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException, IOException { - //FIXME: argument validation here - //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); mConfig.setMode(MODE_TRANSPORT); mConfig.setRemoteAddress(remoteAddress.getHostAddress()); return new IpSecTransform(mContext, mConfig).activate(); diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 555874c0e1..2e1f142a7d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -344,7 +344,7 @@ public class IpSecService extends IIpSecService.Stub { private class ManagedResourceArray { SparseArray mArray = new SparseArray<>(); - T get(int key) { + T getAndCheckOwner(int key) { T val = mArray.get(key); // The value should never be null unless the resource doesn't exist // (since we do not allow null resources to be added). @@ -723,7 +723,7 @@ public class IpSecService extends IIpSecService.Stub { throws RemoteException { // We want to non-destructively get so that we can check credentials before removing // this from the records. - T record = resArray.get(resourceId); + T record = resArray.getAndCheckOwner(resourceId); if (record == null) { throw new IllegalArgumentException( @@ -863,7 +863,8 @@ public class IpSecService extends IIpSecService.Stub { break; case IpSecTransform.ENCAP_ESPINUDP: case IpSecTransform.ENCAP_ESPINUDP_NON_IKE: - if (mUdpSocketRecords.get(config.getEncapSocketResourceId()) == null) { + if (mUdpSocketRecords.getAndCheckOwner( + config.getEncapSocketResourceId()) == null) { throw new IllegalStateException( "No Encapsulation socket for Resource Id: " + config.getEncapSocketResourceId()); @@ -885,7 +886,7 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Encryption and Authentication are both null"); } - if (mSpiRecords.get(config.getSpiResourceId(direction)) == null) { + if (mSpiRecords.getAndCheckOwner(config.getSpiResourceId(direction)) == null) { throw new IllegalStateException("No SPI for specified Resource Id"); } } @@ -913,7 +914,7 @@ public class IpSecService extends IIpSecService.Stub { UdpSocketRecord socketRecord = null; encapType = c.getEncapType(); if (encapType != IpSecTransform.ENCAP_NONE) { - socketRecord = mUdpSocketRecords.get(c.getEncapSocketResourceId()); + socketRecord = mUdpSocketRecords.getAndCheckOwner(c.getEncapSocketResourceId()); encapLocalPort = socketRecord.getPort(); encapRemotePort = c.getEncapRemotePort(); } @@ -922,7 +923,7 @@ public class IpSecService extends IIpSecService.Stub { IpSecAlgorithm auth = c.getAuthentication(direction); IpSecAlgorithm crypt = c.getEncryption(direction); - spis[direction] = mSpiRecords.get(c.getSpiResourceId(direction)); + spis[direction] = mSpiRecords.getAndCheckOwner(c.getSpiResourceId(direction)); int spi = spis[direction].getSpi(); try { mSrvConfig @@ -976,7 +977,7 @@ public class IpSecService extends IIpSecService.Stub { // Synchronize liberally here because we are using ManagedResources in this block TransformRecord info; // FIXME: this code should be factored out into a security check + getter - info = mTransformRecords.get(resourceId); + info = mTransformRecords.getAndCheckOwner(resourceId); if (info == null) { throw new IllegalArgumentException("Transform " + resourceId + " is not active"); From be4309663578d49babb43435e1288584b365be30 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 22 Aug 2017 21:42:33 -0700 Subject: [PATCH 057/881] Add support for AES-GCM-ESP as an IPSec algorithm Allows native AES-GCM-ESP to be used as an IPSec transport/tunnel mode algorithm with kernel support Bug: 63589918 Test: IPsecService tests added, existing ones pass Change-Id: Ie1a9a902be205f269aa37bf956198f2e5b177c21 --- core/java/android/net/IpSecAlgorithm.java | 24 ++++++++++++++--- core/java/android/net/IpSecConfig.java | 20 ++++++++++++++ core/java/android/net/IpSecTransform.java | 27 +++++++++++++++++++ .../java/com/android/server/IpSecService.java | 14 ++++++++-- 4 files changed, 80 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 79310e295a..16b1452311 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -31,7 +31,6 @@ import java.util.Arrays; * RFC 4301. */ public final class IpSecAlgorithm implements Parcelable { - /** * AES-CBC Encryption/Ciphering Algorithm. * @@ -68,6 +67,7 @@ public final class IpSecAlgorithm implements Parcelable { *

Valid truncation lengths are multiples of 8 bits from 192 to (default) 384. */ public static final String AUTH_HMAC_SHA384 = "hmac(sha384)"; + /** * SHA512 HMAC Authentication/Integrity Algorithm * @@ -75,8 +75,24 @@ public final class IpSecAlgorithm implements Parcelable { */ public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; + /** + * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm. + * + *

Valid lengths for this key are {128, 192, 256}. + * + *

Valid ICV (truncation) lengths are {64, 96, 128}. + */ + public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))"; + /** @hide */ - @StringDef({CRYPT_AES_CBC, AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, AUTH_HMAC_SHA512}) + @StringDef({ + CRYPT_AES_CBC, + AUTH_HMAC_MD5, + AUTH_HMAC_SHA1, + AUTH_HMAC_SHA256, + AUTH_HMAC_SHA512, + AUTH_CRYPT_AES_GCM + }) @Retention(RetentionPolicy.SOURCE) public @interface AlgorithmName {} @@ -102,7 +118,7 @@ public final class IpSecAlgorithm implements Parcelable { * @param algoName precise name of the algorithm to be used. * @param key non-null Key padded to a multiple of 8 bits. * @param truncLenBits the number of bits of output hash to use; only meaningful for - * Authentication. + * Authentication or Authenticated Encryption (equivalent to ICV length). */ public IpSecAlgorithm(@AlgorithmName String algoName, byte[] key, int truncLenBits) { if (!isTruncationLengthValid(algoName, truncLenBits)) { @@ -175,6 +191,8 @@ public final class IpSecAlgorithm implements Parcelable { return (truncLenBits >= 192 && truncLenBits <= 384); case AUTH_HMAC_SHA512: return (truncLenBits >= 256 && truncLenBits <= 512); + case AUTH_CRYPT_AES_GCM: + return (truncLenBits == 64 || truncLenBits == 96 || truncLenBits == 128); default: return false; } diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 632b7fc07f..61b13a922d 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -50,6 +50,9 @@ public final class IpSecConfig implements Parcelable { // Authentication Algorithm private IpSecAlgorithm mAuthentication; + // Authenticated Encryption Algorithm + private IpSecAlgorithm mAuthenticatedEncryption; + @Override public String toString() { return new StringBuilder() @@ -59,6 +62,8 @@ public final class IpSecConfig implements Parcelable { .append(mEncryption) .append(", mAuthentication=") .append(mAuthentication) + .append(", mAuthenticatedEncryption=") + .append(mAuthenticatedEncryption) .append("}") .toString(); } @@ -118,6 +123,11 @@ public final class IpSecConfig implements Parcelable { mFlow[direction].mAuthentication = authentication; } + /** Set the authenticated encryption algorithm for a given direction */ + public void setAuthenticatedEncryption(int direction, IpSecAlgorithm authenticatedEncryption) { + mFlow[direction].mAuthenticatedEncryption = authenticatedEncryption; + } + public void setNetwork(Network network) { mNetwork = network; } @@ -163,6 +173,10 @@ public final class IpSecConfig implements Parcelable { return mFlow[direction].mAuthentication; } + public IpSecAlgorithm getAuthenticatedEncryption(int direction) { + return mFlow[direction].mAuthenticatedEncryption; + } + public Network getNetwork() { return mNetwork; } @@ -199,9 +213,11 @@ public final class IpSecConfig implements Parcelable { out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId); out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags); out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption, flags); out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId); out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags); out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags); + out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption, flags); out.writeInt(mEncapType); out.writeInt(mEncapSocketResourceId); out.writeInt(mEncapRemotePort); @@ -221,11 +237,15 @@ public final class IpSecConfig implements Parcelable { (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); mFlow[IpSecTransform.DIRECTION_IN].mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); + mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption = + (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt(); mFlow[IpSecTransform.DIRECTION_OUT].mEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); + mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption = + (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); mEncapType = in.readInt(); mEncapSocketResourceId = in.readInt(); mEncapRemotePort = in.readInt(); diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index e15a2c672c..48b5bd5c3d 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -281,6 +281,8 @@ public final class IpSecTransform implements AutoCloseable { *

If encryption is set for a given direction without also providing an SPI for that * direction, creation of an IpSecTransform will fail upon calling a build() method. * + *

Authenticated encryption is mutually exclusive with encryption and authentication. + * * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. */ @@ -296,6 +298,8 @@ public final class IpSecTransform implements AutoCloseable { *

If authentication is set for a given direction without also providing an SPI for that * direction, creation of an IpSecTransform will fail upon calling a build() method. * + *

Authenticated encryption is mutually exclusive with encryption and authentication. + * * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. */ @@ -305,6 +309,29 @@ public final class IpSecTransform implements AutoCloseable { return this; } + /** + * Add an authenticated encryption algorithm to the transform for the given direction. + * + *

If an authenticated encryption algorithm is set for a given direction without also + * providing an SPI for that direction, creation of an IpSecTransform will fail upon calling + * a build() method. + * + *

The Authenticated Encryption (AE) class of algorithms are also known as Authenticated + * Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as + * referred to in RFC 4301) + * + *

Authenticated encryption is mutually exclusive with encryption and authentication. + * + * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} + * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to + * be applied. + */ + public IpSecTransform.Builder setAuthenticatedEncryption( + @TransformDirection int direction, IpSecAlgorithm algo) { + mConfig.setAuthenticatedEncryption(direction, algo); + return this; + } + /** * Set the SPI, which uniquely identifies a particular IPsec session from others. Because * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 2e1f142a7d..cf1d33c861 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -882,8 +882,14 @@ public class IpSecService extends IIpSecService.Stub { for (int direction : DIRECTIONS) { IpSecAlgorithm crypt = config.getEncryption(direction); IpSecAlgorithm auth = config.getAuthentication(direction); - if (crypt == null && auth == null) { - throw new IllegalArgumentException("Encryption and Authentication are both null"); + IpSecAlgorithm authenticatedEncryption = config.getAuthenticatedEncryption(direction); + if (authenticatedEncryption == null && crypt == null && auth == null) { + throw new IllegalArgumentException( + "No Encryption or Authentication algorithms specified"); + } else if (authenticatedEncryption != null && (auth != null || crypt != null)) { + throw new IllegalArgumentException( + "Authenticated Encryption is mutually" + + " exclusive with other Authentication or Encryption algorithms"); } if (mSpiRecords.getAndCheckOwner(config.getSpiResourceId(direction)) == null) { @@ -922,6 +928,7 @@ public class IpSecService extends IIpSecService.Stub { for (int direction : DIRECTIONS) { IpSecAlgorithm auth = c.getAuthentication(direction); IpSecAlgorithm crypt = c.getEncryption(direction); + IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(direction); spis[direction] = mSpiRecords.getAndCheckOwner(c.getSpiResourceId(direction)); int spi = spis[direction].getSpi(); @@ -942,6 +949,9 @@ public class IpSecService extends IIpSecService.Stub { (crypt != null) ? crypt.getName() : "", (crypt != null) ? crypt.getKey() : null, (crypt != null) ? crypt.getTruncationLengthBits() : 0, + (authCrypt != null) ? authCrypt.getName() : "", + (authCrypt != null) ? authCrypt.getKey() : null, + (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, encapType, encapLocalPort, encapRemotePort); From 0225c3c6d14a574527df3bd869075f27cc61fe41 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 10 Oct 2017 20:44:28 -0700 Subject: [PATCH 058/881] Return a port from bindToPort() in IpSecService When binding to a random port, the port number was not being returned, so the user is incorrectly receiving a port of zero. Return the port number that was ultimately bound. Bug: 67662580 Test: Ran CTS test on aosp_angler-eng Change-Id: I22f4e5cdc83d43dc453788889990feb34e451bd3 --- services/core/java/com/android/server/IpSecService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 2e1f142a7d..3d54ee6b6e 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -754,7 +754,7 @@ public class IpSecService extends IIpSecService.Stub { * and re-binding, during which the system could *technically* hand that port out to someone * else. */ - private void bindToRandomPort(FileDescriptor sockFd) throws IOException { + private int bindToRandomPort(FileDescriptor sockFd) throws IOException { for (int i = MAX_PORT_BIND_ATTEMPTS; i > 0; i--) { try { FileDescriptor probeSocket = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -763,7 +763,7 @@ public class IpSecService extends IIpSecService.Stub { Os.close(probeSocket); Log.v(TAG, "Binding to port " + port); Os.bind(sockFd, INADDR_ANY, port); - return; + return port; } catch (ErrnoException e) { // Someone miraculously claimed the port just after we closed probeSocket. if (e.errno == OsConstants.EADDRINUSE) { @@ -803,7 +803,7 @@ public class IpSecService extends IIpSecService.Stub { Log.v(TAG, "Binding to port " + port); Os.bind(sockFd, INADDR_ANY, port); } else { - bindToRandomPort(sockFd); + port = bindToRandomPort(sockFd); } // This code is common to both the unspecified and specified port cases Os.setsockoptInt( From 8f3f6aad44a6a8e0981a37fae12dfb0de8f714af Mon Sep 17 00:00:00 2001 From: Elvis Chien Date: Fri, 29 Sep 2017 15:47:05 +0800 Subject: [PATCH 059/881] ethernet: Fix the connect fail issue when switch DHCP to Static config at Ethernet interface. add different logic to handle static ip configuration. Bug: b/64914694 Test: follow the following steps to switch ethernet config 1.Plug Ethernet cable ,Ethernet succeed to access internet with DHCP mode 2.Change Ethernet IP settings to Static 3.Input correct ip , gateway, prefix length, DNS 4.UI show Connected, but failed to access Internet. Change-Id: I223bca85814e94745fbb8b50ca677eb7032e9bb3 (cherry picked from commit 44a107bc8f058c6ac1aab6fbfbf60bf8f3474711) --- .../ethernet/EthernetNetworkFactory.java | 100 +++++++----------- 1 file changed, 39 insertions(+), 61 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index d6d0defd32..2d54fd20e4 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -248,25 +248,6 @@ class EthernetNetworkFactory { return true; } - private boolean setStaticIpAddress(StaticIpConfiguration staticConfig) { - if (staticConfig.ipAddress != null && - staticConfig.gateway != null && - staticConfig.dnsServers.size() > 0) { - try { - Log.i(TAG, "Applying static IPv4 configuration to " + mIface + ": " + staticConfig); - InterfaceConfiguration config = mNMService.getInterfaceConfig(mIface); - config.setLinkAddress(staticConfig.ipAddress); - mNMService.setInterfaceConfig(mIface, config); - return true; - } catch(RemoteException|IllegalStateException e) { - Log.e(TAG, "Setting static IP address failed: " + e.getMessage()); - } - } else { - Log.e(TAG, "Invalid static IP configuration."); - } - return false; - } - public void updateAgent() { if (mNetworkAgent == null) return; if (DBG) { @@ -332,55 +313,52 @@ class EthernetNetworkFactory { mNetworkInfo)); } - LinkProperties linkProperties; - IpConfiguration config = mEthernetManager.getConfiguration(); - if (config.getIpAssignment() == IpAssignment.STATIC) { - if (!setStaticIpAddress(config.getStaticIpConfiguration())) { - // We've already logged an error. - return; - } - linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface); - } else { - mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); - IpManager.Callback ipmCallback = new IpManager.Callback() { - @Override - public void onProvisioningSuccess(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStarted(newLp)); - } - - @Override - public void onProvisioningFailure(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStopped(newLp)); - } - - @Override - public void onLinkPropertiesChange(LinkProperties newLp) { - mHandler.post(() -> updateLinkProperties(newLp)); - } - }; - - stopIpManager(); - mIpManager = new IpManager(mContext, mIface, ipmCallback); - - if (config.getProxySettings() == ProxySettings.STATIC || - config.getProxySettings() == ProxySettings.PAC) { - mIpManager.setHttpProxy(config.getHttpProxy()); + mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); + IpManager.Callback ipmCallback = new IpManager.Callback() { + @Override + public void onProvisioningSuccess(LinkProperties newLp) { + mHandler.post(() -> onIpLayerStarted(newLp)); } - final String tcpBufferSizes = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_tcp_buffers); - if (!TextUtils.isEmpty(tcpBufferSizes)) { - mIpManager.setTcpBufferSizes(tcpBufferSizes); + @Override + public void onProvisioningFailure(LinkProperties newLp) { + mHandler.post(() -> onIpLayerStopped(newLp)); } - final ProvisioningConfiguration provisioningConfiguration = - mIpManager.buildProvisioningConfiguration() - .withProvisioningTimeoutMs(0) - .build(); - mIpManager.startProvisioning(provisioningConfiguration); + @Override + public void onLinkPropertiesChange(LinkProperties newLp) { + mHandler.post(() -> updateLinkProperties(newLp)); + } + }; + + stopIpManager(); + mIpManager = new IpManager(mContext, mIface, ipmCallback); + + if (config.getProxySettings() == ProxySettings.STATIC || + config.getProxySettings() == ProxySettings.PAC) { + mIpManager.setHttpProxy(config.getHttpProxy()); } + + final String tcpBufferSizes = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_tcp_buffers); + if (!TextUtils.isEmpty(tcpBufferSizes)) { + mIpManager.setTcpBufferSizes(tcpBufferSizes); + } + + final ProvisioningConfiguration provisioningConfiguration; + if (config.getIpAssignment() == IpAssignment.STATIC) { + provisioningConfiguration = IpManager.buildProvisioningConfiguration() + .withStaticConfiguration(config.getStaticIpConfiguration()) + .build(); + } else { + provisioningConfiguration = mIpManager.buildProvisioningConfiguration() + .withProvisioningTimeoutMs(0) + .build(); + } + + mIpManager.startProvisioning(provisioningConfiguration); } /** From dae8417c18253100849b25083df262008f096612 Mon Sep 17 00:00:00 2001 From: Manoj Boopathi Raj Date: Thu, 26 Oct 2017 11:49:02 -0700 Subject: [PATCH 060/881] Fixed NullPointerException in IpSecService-Netd binder layer Replaced null with empty byte array in createTransportModeTransform for null auth.getKey, crypt.getKey() and authCrypt.getKey() Test: Ran CTS test Bug: 68052730 Change-Id: I5110b1297b4bfbb5766e8ecfd3d64f8110b52945 --- services/core/java/com/android/server/IpSecService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index a139ac4f3f..1154fbe609 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -944,13 +944,13 @@ public class IpSecService extends IIpSecService.Stub { (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0, spi, (auth != null) ? auth.getName() : "", - (auth != null) ? auth.getKey() : null, + (auth != null) ? auth.getKey() : new byte[] {}, (auth != null) ? auth.getTruncationLengthBits() : 0, (crypt != null) ? crypt.getName() : "", - (crypt != null) ? crypt.getKey() : null, + (crypt != null) ? crypt.getKey() : new byte[] {}, (crypt != null) ? crypt.getTruncationLengthBits() : 0, (authCrypt != null) ? authCrypt.getName() : "", - (authCrypt != null) ? authCrypt.getKey() : null, + (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, encapType, encapLocalPort, From 3789667cc2f9c456310572475d54e2aa62a21a45 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 27 Oct 2017 17:56:52 -0600 Subject: [PATCH 061/881] Define NOT_ROAMING network capability. The "roaming" state of a network really belongs on NetworkCapabilities instead of being published through NetworkInfo.isRoaming(). One major reason is to support developers creating NetworkRequests for a non-roaming network. Test: bit FrameworksNetTests:android.net.,com.android.server.net.,com.android.server.connectivity. Bug: 68397798, 16207332 Change-Id: I0722d7b38d0478de3834b869552f48403af9d553 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 2d54fd20e4..0bbe3b5e3c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -427,6 +427,8 @@ class EthernetNetworkFactory { mNetworkCapabilities = new NetworkCapabilities(); mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); + mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); // We have no useful data on bandwidth. Say 100M up and 100M down. :-( mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000); From 1c09bde6ad24b7bee76c99ae0b8894644196f87a Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 27 Oct 2017 17:22:59 -0600 Subject: [PATCH 062/881] Define NOT_ROAMING network capability. The "roaming" state of a network really belongs on NetworkCapabilities instead of being published through NetworkInfo.isRoaming(). One major reason is to support developers creating NetworkRequests for a non-roaming network. Watch for any capability changes that network statistics are interested in (either metered or roaming) and notify it to perform an update pass; fixes bug where we previously only triggered on roaming changes. Fix bug in VPNs where metered/roaming capabilities of underlying networks weren't being propagated; this was probably preventing some jobs from running over unmetered networks, and causing other jobs to run over roaming networks! Also passes along link bandwidth information from underlying networks, and propegates any changes to underlying networks. Fix race condition by reading prevNc inside lock. Utility methods correctly calculate min/max link bandwidth values. Test: bit FrameworksNetTests:android.net.,com.android.server.net.,com.android.server.connectivity.,com.android.server.ConnectivityServiceTest Bug: 68397798, 16207332 Change-Id: I3e1a6544c902bf3a79356b72d3616af1fd2b0f49 --- core/java/android/net/NetworkIdentity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 0775bdaaf3..df404b7dce 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -189,7 +189,8 @@ public class NetworkIdentity implements Comparable { String subscriberId = null; String networkId = null; - boolean roaming = false; + boolean roaming = !state.networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); boolean metered = !state.networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_METERED); @@ -203,7 +204,6 @@ public class NetworkIdentity implements Comparable { } subscriberId = state.subscriberId; - roaming = state.networkInfo.isRoaming(); } else if (type == TYPE_WIFI) { if (state.networkId != null) { From debeb8779d2257a1c9ed47d34bcb7553e7886f09 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 1 Nov 2017 17:14:25 -0700 Subject: [PATCH 063/881] Update documentation for AES-GCM-ESP keymat length Added notes that keymat length must include 32 bits of salt. Bug: 68672051 Test: Frameworks-net unit tests & IpSecManager CTS tests run Change-Id: I0ae0c5be8a45b2374783b3bd1fa8bf930f15e687 --- core/java/android/net/IpSecAlgorithm.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 16b1452311..64f8f39e2b 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -78,7 +78,11 @@ public final class IpSecAlgorithm implements Parcelable { /** * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm. * - *

Valid lengths for this key are {128, 192, 256}. + *

Valid lengths for keying material are {160, 224, 288}. + * + *

As per RFC4106 (Section 8.1), keying material consists of a 128, 192, or 256 bit AES key + * followed by a 32-bit salt. RFC compliance requires that the salt must be unique per + * invocation with the same key. * *

Valid ICV (truncation) lengths are {64, 96, 128}. */ From 8d88a143924b808ac72fdda0073d29bff3319259 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 7 Nov 2017 17:17:45 -0800 Subject: [PATCH 064/881] Fix signature for finalize() to resolve API Lint error The API linter on goog/master noticed that this method is listed in the public API even though it's protected. The change is probably related to a signature change from the internal finalize method which throws a Throwable. Fix the method in IpSecManager to throw Throwable, which should fix the current.txt and resolve the lint error. Bug: 69006767 Test: compilation, make update-api Change-Id: I173d014baaa505c365b7916fcb52f2a8b4af9373 --- core/java/android/net/IpSecManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index d7b325613f..eccd5f47f2 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -136,7 +136,7 @@ public final class IpSecManager { } @Override - protected void finalize() { + protected void finalize() throws Throwable { if (mCloseGuard != null) { mCloseGuard.warnIfOpen(); } From 92ea134c15512137b9e7f9a0a097f4202c3fe547 Mon Sep 17 00:00:00 2001 From: Ricky Wai Date: Thu, 9 Nov 2017 15:22:59 +0000 Subject: [PATCH 065/881] Hide NetworkStatsFactory class Test: Able to compile Change-Id: I37f385c773120405c437643b5de406772a684dcd --- core/java/com/android/internal/net/NetworkStatsFactory.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 3d3e148fb3..5eda81baa3 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -43,6 +43,8 @@ import java.util.Objects; /** * Creates {@link NetworkStats} instances by parsing various {@code /proc/} * files as needed. + * + * @hide */ public class NetworkStatsFactory { private static final String TAG = "NetworkStatsFactory"; From 745d586d48be8e72b384f53eced19b5f21d0c4cc Mon Sep 17 00:00:00 2001 From: Jonathan Basseri Date: Fri, 21 Apr 2017 15:53:51 -0700 Subject: [PATCH 066/881] Javadoc cleanup of IpSecManager API. This changes only comments and annotations, which results in minor API changes. Bug: 63777932 Test: `make update-api` and visually inspect generated HTML. Change-Id: I7a7a9244eade6cc55aca17a47e0a838cd6f84cc9 --- core/java/android/net/IpSecAlgorithm.java | 62 ++--- core/java/android/net/IpSecConfig.java | 10 +- core/java/android/net/IpSecManager.java | 272 ++++++++++++++-------- core/java/android/net/IpSecTransform.java | 177 +++++++------- 4 files changed, 299 insertions(+), 222 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 64f8f39e2b..d6e62cf1f8 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -15,6 +15,7 @@ */ package android.net; +import android.annotation.NonNull; import android.annotation.StringDef; import android.os.Build; import android.os.Parcel; @@ -27,8 +28,10 @@ import java.lang.annotation.RetentionPolicy; import java.util.Arrays; /** - * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to - * RFC 4301. + * This class represents a single algorithm that can be used by an {@link IpSecTransform}. + * + * @see RFC 4301, Security Architecture for the + * Internet Protocol */ public final class IpSecAlgorithm implements Parcelable { /** @@ -39,16 +42,16 @@ public final class IpSecAlgorithm implements Parcelable { public static final String CRYPT_AES_CBC = "cbc(aes)"; /** - * MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in new - * applications and is provided for legacy compatibility with 3gpp infrastructure. + * MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in + * new applications and is provided for legacy compatibility with 3gpp infrastructure. * *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 128. */ public static final String AUTH_HMAC_MD5 = "hmac(md5)"; /** - * SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in - * new applications and is provided for legacy compatibility with 3gpp infrastructure. + * SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in + * new applications and is provided for legacy compatibility with 3gpp infrastructure. * *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 160. */ @@ -69,7 +72,7 @@ public final class IpSecAlgorithm implements Parcelable { public static final String AUTH_HMAC_SHA384 = "hmac(sha384)"; /** - * SHA512 HMAC Authentication/Integrity Algorithm + * SHA512 HMAC Authentication/Integrity Algorithm. * *

Valid truncation lengths are multiples of 8 bits from 256 to (default) 512. */ @@ -80,9 +83,9 @@ public final class IpSecAlgorithm implements Parcelable { * *

Valid lengths for keying material are {160, 224, 288}. * - *

As per RFC4106 (Section 8.1), keying material consists of a 128, 192, or 256 bit AES key - * followed by a 32-bit salt. RFC compliance requires that the salt must be unique per - * invocation with the same key. + *

As per RFC4106 (Section + * 8.1), keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit + * salt. RFC compliance requires that the salt must be unique per invocation with the same key. * *

Valid ICV (truncation) lengths are {64, 96, 128}. */ @@ -105,48 +108,47 @@ public final class IpSecAlgorithm implements Parcelable { private final int mTruncLenBits; /** - * Specify a IpSecAlgorithm of one of the supported types including the truncation length of the - * algorithm + * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are + * defined as constants in this class. * - * @param algorithm type for IpSec. - * @param key non-null Key padded to a multiple of 8 bits. + * @param algorithm name of the algorithm. + * @param key key padded to a multiple of 8 bits. */ - public IpSecAlgorithm(String algorithm, byte[] key) { + public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key) { this(algorithm, key, key.length * 8); } /** - * Specify a IpSecAlgorithm of one of the supported types including the truncation length of the - * algorithm + * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are + * defined as constants in this class. * - * @param algoName precise name of the algorithm to be used. - * @param key non-null Key padded to a multiple of 8 bits. - * @param truncLenBits the number of bits of output hash to use; only meaningful for - * Authentication or Authenticated Encryption (equivalent to ICV length). + *

This constructor only supports algorithms that use a truncation length. i.e. + * Authentication and Authenticated Encryption algorithms. + * + * @param algorithm name of the algorithm. + * @param key key padded to a multiple of 8 bits. + * @param truncLenBits number of bits of output hash to use. */ - public IpSecAlgorithm(@AlgorithmName String algoName, byte[] key, int truncLenBits) { - if (!isTruncationLengthValid(algoName, truncLenBits)) { + public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) { + if (!isTruncationLengthValid(algorithm, truncLenBits)) { throw new IllegalArgumentException("Unknown algorithm or invalid length"); } - mName = algoName; + mName = algorithm; mKey = key.clone(); mTruncLenBits = Math.min(truncLenBits, key.length * 8); } - /** Retrieve the algorithm name */ + /** Get the algorithm name */ public String getName() { return mName; } - /** Retrieve the key for this algorithm */ + /** Get the key for this algorithm */ public byte[] getKey() { return mKey.clone(); } - /** - * Retrieve the truncation length, in bits, for the key in this algo. By default this will be - * the length in bits of the key. - */ + /** Get the truncation length of this algorithm, in bits */ public int getTruncationLengthBits() { return mTruncLenBits; } diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 61b13a922d..e6cd3fc130 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -20,7 +20,12 @@ import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; -/** @hide */ +/** + * This class encapsulates all the configuration parameters needed to create IPsec transforms and + * policies. + * + * @hide + */ public final class IpSecConfig implements Parcelable { private static final String TAG = "IpSecConfig"; @@ -38,6 +43,9 @@ public final class IpSecConfig implements Parcelable { // for outbound packets. It may also be used to select packets. private Network mNetwork; + /** + * This class captures the parameters that specifically apply to inbound or outbound traffic. + */ public static class Flow { // Minimum requirements for identifying a transform // SPI identifying the IPsec flow in packet processing diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index eccd5f47f2..a9e60ec88a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -19,6 +19,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.annotation.SystemService; +import android.annotation.TestApi; import android.content.Context; import android.os.Binder; import android.os.ParcelFileDescriptor; @@ -37,22 +38,28 @@ import java.net.InetAddress; import java.net.Socket; /** - * This class contains methods for managing IPsec sessions, which will perform kernel-space - * encryption and decryption of socket or Network traffic. + * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply + * confidentiality (encryption) and integrity (authentication) to IP traffic. * - *

An IpSecManager may be obtained by calling {@link - * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link - * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE} + *

Note that not all aspects of IPsec are permitted by this API. Applications may create + * transport mode security associations and apply them to individual sockets. Applications looking + * to create a VPN should use {@link VpnService}. + * + * @see RFC 4301, Security Architecture for the + * Internet Protocol */ @SystemService(Context.IPSEC_SERVICE) public final class IpSecManager { private static final String TAG = "IpSecManager"; /** - * The Security Parameter Index, SPI, 0 indicates an unknown or invalid index. + * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. * *

No IPsec packet may contain an SPI of 0. + * + * @hide */ + @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; /** @hide */ @@ -66,10 +73,12 @@ public final class IpSecManager { public static final int INVALID_RESOURCE_ID = 0; /** - * Indicates that the combination of remote InetAddress and SPI was non-unique for a given - * request. If encountered, selection of a new SPI is required before a transform may be - * created. Note, this should happen very rarely if the SPI is chosen to be sufficiently random - * or reserved using reserveSecurityParameterIndex. + * Thrown to indicate that a requested SPI is in use. + * + *

The combination of remote {@code InetAddress} and SPI must be unique across all apps on + * one device. If this error is encountered, a new SPI is required before a transform may be + * created. This error can be avoided by calling {@link + * IpSecManager#reserveSecurityParameterIndex}. */ public static final class SpiUnavailableException extends AndroidException { private final int mSpi; @@ -78,24 +87,26 @@ public final class IpSecManager { * Construct an exception indicating that a transform with the given SPI is already in use * or otherwise unavailable. * - * @param msg Description indicating the colliding SPI + * @param msg description indicating the colliding SPI * @param spi the SPI that could not be used due to a collision */ SpiUnavailableException(String msg, int spi) { - super(msg + "(spi: " + spi + ")"); + super(msg + " (spi: " + spi + ")"); mSpi = spi; } - /** Retrieve the SPI that caused a collision */ + /** Get the SPI that caused a collision. */ public int getSpi() { return mSpi; } } /** - * Indicates that the requested system resource for IPsec, such as a socket or other system - * resource is unavailable. If this exception is thrown, try releasing allocated objects of the - * type requested. + * Thrown to indicate that an IPsec resource is unavailable. + * + *

This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link + * IpSecTransform}, or other system resources. If this exception is thrown, users should release + * allocated objects of the type requested. */ public static final class ResourceUnavailableException extends AndroidException { @@ -106,6 +117,13 @@ public final class IpSecManager { private final IIpSecService mService; + /** + * This class represents a reserved SPI. + * + *

Objects of this type are used to track reserved security parameter indices. They can be + * obtained by calling {@link IpSecManager#reserveSecurityParameterIndex} and must be released + * by calling {@link #close()} when they are no longer needed. + */ public static final class SecurityParameterIndex implements AutoCloseable { private final IIpSecService mService; private final InetAddress mRemoteAddress; @@ -113,7 +131,7 @@ public final class IpSecManager { private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; private int mResourceId; - /** Return the underlying SPI held by this object */ + /** Get the underlying SPI held by this object. */ public int getSpi() { return mSpi; } @@ -135,6 +153,7 @@ public final class IpSecManager { mCloseGuard.close(); } + /** Check that the SPI was closed properly. */ @Override protected void finalize() throws Throwable { if (mCloseGuard != null) { @@ -197,13 +216,13 @@ public final class IpSecManager { } /** - * Reserve an SPI for traffic bound towards the specified remote address. + * Reserve a random SPI for traffic bound to or from the specified remote address. * *

If successful, this SPI is guaranteed available until released by a call to {@link * SecurityParameterIndex#close()}. * * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} - * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress. + * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress * @return the reserved SecurityParameterIndex * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated * for this user @@ -223,17 +242,18 @@ public final class IpSecManager { } /** - * Reserve an SPI for traffic bound towards the specified remote address. + * Reserve the requested SPI for traffic bound to or from the specified remote address. * *

If successful, this SPI is guaranteed available until released by a call to {@link * SecurityParameterIndex#close()}. * * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} - * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress. - * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. + * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress + * @param requestedSpi the requested SPI, or '0' to allocate a random SPI * @return the reserved SecurityParameterIndex * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated * for this user + * @throws SpiUnavailableException indicating that the requested SPI could not be reserved */ public SecurityParameterIndex reserveSecurityParameterIndex( int direction, InetAddress remoteAddress, int requestedSpi) @@ -245,16 +265,28 @@ public final class IpSecManager { } /** - * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec - * encapsulation of the traffic flowing between the socket and the remote InetAddress of that - * transform. For security reasons, attempts to send traffic to any IP address other than the - * address associated with that transform will throw an IOException. In addition, if the - * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to - * send() or receive() until the transform is removed from the socket by calling {@link - * #removeTransportModeTransform(Socket, IpSecTransform)}; + * Apply an IPsec transform to a stream socket. + * + *

This applies transport mode encapsulation to the given socket. Once applied, I/O on the + * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When + * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * unprotected traffic can resume on that socket. + * + *

For security reasons, the destination address of any traffic on the socket must match the + * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any + * other IP address will result in an IOException. In addition, reads and writes on the socket + * will throw IOException if the user deactivates the transform (by calling {@link + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * + *

Rekey Procedure

When applying a new tranform to a socket, the previous transform + * will be removed. However, inbound traffic on the old transform will continue to be decrypted + * until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap + * allows rekey procedures where both transforms are valid until both endpoints are using the + * new transform and all in-flight packets have been received. * * @param socket a stream socket - * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform. + * @param transform a transport mode {@code IpSecTransform} + * @throws IOException indicating that the transform could not be applied * @hide */ public void applyTransportModeTransform(Socket socket, IpSecTransform transform) @@ -265,16 +297,28 @@ public final class IpSecManager { } /** - * Apply an active Transport Mode IPsec Transform to a datagram socket to perform IPsec - * encapsulation of the traffic flowing between the socket and the remote InetAddress of that - * transform. For security reasons, attempts to send traffic to any IP address other than the - * address associated with that transform will throw an IOException. In addition, if the - * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to - * send() or receive() until the transform is removed from the socket by calling {@link - * #removeTransportModeTransform(DatagramSocket, IpSecTransform)}; + * Apply an IPsec transform to a datagram socket. + * + *

This applies transport mode encapsulation to the given socket. Once applied, I/O on the + * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When + * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * unprotected traffic can resume on that socket. + * + *

For security reasons, the destination address of any traffic on the socket must match the + * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any + * other IP address will result in an IOException. In addition, reads and writes on the socket + * will throw IOException if the user deactivates the transform (by calling {@link + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * + *

Rekey Procedure

When applying a new tranform to a socket, the previous transform + * will be removed. However, inbound traffic on the old transform will continue to be decrypted + * until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap + * allows rekey procedures where both transforms are valid until both endpoints are using the + * new transform and all in-flight packets have been received. * * @param socket a datagram socket - * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform. + * @param transform a transport mode {@code IpSecTransform} + * @throws IOException indicating that the transform could not be applied * @hide */ public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) @@ -285,16 +329,28 @@ public final class IpSecManager { } /** - * Apply an active Transport Mode IPsec Transform to a stream socket to perform IPsec - * encapsulation of the traffic flowing between the socket and the remote InetAddress of that - * transform. For security reasons, attempts to send traffic to any IP address other than the - * address associated with that transform will throw an IOException. In addition, if the - * IpSecTransform is later deactivated, the socket will throw an IOException on any calls to - * send() or receive() until the transform is removed from the socket by calling {@link - * #removeTransportModeTransform(FileDescriptor, IpSecTransform)}; + * Apply an IPsec transform to a socket. + * + *

This applies transport mode encapsulation to the given socket. Once applied, I/O on the + * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When + * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * unprotected traffic can resume on that socket. + * + *

For security reasons, the destination address of any traffic on the socket must match the + * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any + * other IP address will result in an IOException. In addition, reads and writes on the socket + * will throw IOException if the user deactivates the transform (by calling {@link + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * + *

Rekey Procedure

When applying a new tranform to a socket, the previous transform + * will be removed. However, inbound traffic on the old transform will continue to be decrypted + * until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap + * allows rekey procedures where both transforms are valid until both endpoints are using the + * new transform and all in-flight packets have been received. * * @param socket a socket file descriptor - * @param transform an {@link IpSecTransform}, which must be an active Transport Mode transform. + * @param transform a transport mode {@code IpSecTransform} + * @throws IOException indicating that the transform could not be applied */ public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) throws IOException { @@ -323,6 +379,7 @@ public final class IpSecManager { * Applications should probably not use this API directly. Instead, they should use {@link * VpnService} to provide VPN capability in a more generic fashion. * + * TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. * @param net a {@link Network} that will be tunneled via IP Sec. * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform. * @hide @@ -330,14 +387,19 @@ public final class IpSecManager { public void applyTunnelModeTransform(Network net, IpSecTransform transform) {} /** - * Remove a transform from a given stream socket. Once removed, traffic on the socket will not - * be encypted. This allows sockets that have been used for IPsec to be reclaimed for - * communication in the clear in the event socket reuse is desired. This operation will succeed - * regardless of the underlying state of a transform. If a transform is removed, communication - * on all sockets to which that transform was applied will fail until this method is called. + * Remove an IPsec transform from a stream socket. * - * @param socket a socket that previously had a transform applied to it. + *

Once removed, traffic on the socket will not be encrypted. This operation will succeed + * regardless of the state of the transform. Removing a transform from a socket allows the + * socket to be reused for communication in the clear. + * + *

If an {@code IpSecTransform} object applied to this socket was deallocated by calling + * {@link IpSecTransform#close()}, then communication on the socket will fail until this method + * is called. + * + * @param socket a socket that previously had a transform applied to it * @param transform the IPsec Transform that was previously applied to the given socket + * @throws IOException indicating that the transform could not be removed from the socket * @hide */ public void removeTransportModeTransform(Socket socket, IpSecTransform transform) @@ -348,14 +410,19 @@ public final class IpSecManager { } /** - * Remove a transform from a given datagram socket. Once removed, traffic on the socket will not - * be encypted. This allows sockets that have been used for IPsec to be reclaimed for - * communication in the clear in the event socket reuse is desired. This operation will succeed - * regardless of the underlying state of a transform. If a transform is removed, communication - * on all sockets to which that transform was applied will fail until this method is called. + * Remove an IPsec transform from a datagram socket. * - * @param socket a socket that previously had a transform applied to it. + *

Once removed, traffic on the socket will not be encrypted. This operation will succeed + * regardless of the state of the transform. Removing a transform from a socket allows the + * socket to be reused for communication in the clear. + * + *

If an {@code IpSecTransform} object applied to this socket was deallocated by calling + * {@link IpSecTransform#close()}, then communication on the socket will fail until this method + * is called. + * + * @param socket a socket that previously had a transform applied to it * @param transform the IPsec Transform that was previously applied to the given socket + * @throws IOException indicating that the transform could not be removed from the socket * @hide */ public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) @@ -366,14 +433,19 @@ public final class IpSecManager { } /** - * Remove a transform from a given stream socket. Once removed, traffic on the socket will not - * be encypted. This allows sockets that have been used for IPsec to be reclaimed for - * communication in the clear in the event socket reuse is desired. This operation will succeed - * regardless of the underlying state of a transform. If a transform is removed, communication - * on all sockets to which that transform was applied will fail until this method is called. + * Remove an IPsec transform from a socket. * - * @param socket a socket file descriptor that previously had a transform applied to it. + *

Once removed, traffic on the socket will not be encrypted. This operation will succeed + * regardless of the state of the transform. Removing a transform from a socket allows the + * socket to be reused for communication in the clear. + * + *

If an {@code IpSecTransform} object applied to this socket was deallocated by calling + * {@link IpSecTransform#close()}, then communication on the socket will fail until this method + * is called. + * + * @param socket a socket that previously had a transform applied to it * @param transform the IPsec Transform that was previously applied to the given socket + * @throws IOException indicating that the transform could not be removed from the socket */ public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) throws IOException { @@ -382,7 +454,7 @@ public final class IpSecManager { } } - /* Call down to activate a transform */ + /* Call down to remove a transform */ private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { try { mService.removeTransportModeTransform(pfd, transform.getResourceId()); @@ -397,6 +469,7 @@ public final class IpSecManager { * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is * lost, all traffic will drop. * + * TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. * @param net a network that currently has transform applied to it. * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given * network @@ -405,11 +478,18 @@ public final class IpSecManager { public void removeTunnelModeTransform(Network net, IpSecTransform transform) {} /** - * Class providing access to a system-provided UDP Encapsulation Socket, which may be used for - * IKE signalling as well as for inbound and outbound UDP encapsulated IPsec traffic. + * This class provides access to a UDP encapsulation Socket. * - *

The socket provided by this class cannot be re-bound or closed via the inner - * FileDescriptor. Instead, disposing of this socket requires a call to close(). + *

{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2 + * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link + * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the + * caller. The caller should not close the {@code FileDescriptor} returned by {@link + * #getSocket}, but should use {@link #close} instead. + * + *

Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic + * of the next user who binds to that port. To prevent this scenario, these sockets are held + * open by the system so that they may only be closed by calling {@link #close} or when the user + * process exits. */ public static final class UdpEncapsulationSocket implements AutoCloseable { private final ParcelFileDescriptor mPfd; @@ -443,7 +523,7 @@ public final class IpSecManager { mCloseGuard.open("constructor"); } - /** Access the inner UDP Encapsulation Socket */ + /** Get the wrapped socket. */ public FileDescriptor getSocket() { if (mPfd == null) { return null; @@ -451,22 +531,19 @@ public final class IpSecManager { return mPfd.getFileDescriptor(); } - /** Retrieve the port number of the inner encapsulation socket */ + /** Get the bound port of the wrapped socket. */ public int getPort() { return mPort; } - @Override /** - * Release the resources that have been reserved for this Socket. + * Close this socket. * - *

This method closes the underlying socket, reducing a user's allocated sockets in the - * system. This must be done as part of cleanup following use of a socket. Failure to do so - * will cause the socket to count against a total allocation limit for IpSec and eventually - * fail due to resource limits. - * - * @param fd a file descriptor previously returned as a UDP Encapsulation socket. + *

This closes the wrapped socket. Open encapsulation sockets count against a user's + * resource limits, and forgetting to close them eventually will result in {@link + * ResourceUnavailableException} being thrown. */ + @Override public void close() throws IOException { try { mService.closeUdpEncapsulationSocket(mResourceId); @@ -483,6 +560,7 @@ public final class IpSecManager { mCloseGuard.close(); } + /** Check that the socket was closed properly. */ @Override protected void finalize() throws Throwable { if (mCloseGuard != null) { @@ -499,21 +577,14 @@ public final class IpSecManager { }; /** - * Open a socket that is bound to a free UDP port on the system. + * Open a socket for UDP encapsulation and bind to the given port. * - *

By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by - * the caller. This provides safe access to a socket on a port that can later be used as a UDP - * Encapsulation port. + *

See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. * - *

This socket reservation works in conjunction with IpSecTransforms, which may re-use the - * socket port. Explicitly opening this port is only necessary if communication is desired on - * that port. - * - * @param port a local UDP port to be reserved for UDP Encapsulation. is provided, then this - * method will bind to the specified port or fail. To retrieve the port number, call {@link - * android.system.Os#getsockname(FileDescriptor)}. - * @return a {@link UdpEncapsulationSocket} that is bound to the requested port for the lifetime - * of the object. + * @param port a local UDP port + * @return a socket that is bound to the given port + * @throws IOException indicating that the socket could not be opened or bound + * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open */ // Returning a socket in this fashion that has been created and bound by the system // is the only safe way to ensure that a socket is both accessible to the user and @@ -533,17 +604,16 @@ public final class IpSecManager { } /** - * Open a socket that is bound to a port selected by the system. + * Open a socket for UDP encapsulation. * - *

By binding in this manner and holding the FileDescriptor, the socket cannot be un-bound by - * the caller. This provides safe access to a socket on a port that can later be used as a UDP - * Encapsulation port. + *

See {@link UdpEncapsulationSocket} for the proper way to close the returned socket. * - *

This socket reservation works in conjunction with IpSecTransforms, which may re-use the - * socket port. Explicitly opening this port is only necessary if communication is desired on - * that port. + *

The local port of the returned socket can be obtained by calling {@link + * UdpEncapsulationSocket#getPort()}. * - * @return a {@link UdpEncapsulationSocket} that is bound to an arbitrarily selected port + * @return a socket that is bound to a local port + * @throws IOException indicating that the socket could not be opened or bound + * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open */ // Returning a socket in this fashion that has been created and bound by the system // is the only safe way to ensure that a socket is both accessible to the user and @@ -556,7 +626,7 @@ public final class IpSecManager { } /** - * Retrieve an instance of an IpSecManager within you application context + * Construct an instance of IpSecManager within an application context. * * @param context the application context for this manager * @hide diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 48b5bd5c3d..cda4ec762c 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -38,27 +38,29 @@ import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; /** - * This class represents an IpSecTransform, which encapsulates both properties and state of IPsec. + * This class represents an IPsec transform, which comprises security associations in one or both + * directions. * - *

IpSecTransforms must be built from an IpSecTransform.Builder, and they must persist throughout - * the lifetime of the underlying transform. If a transform object leaves scope, the underlying - * transform may be disabled automatically, with likely undesirable results. + *

Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform} + * object encapsulates the properties and state of an inbound and outbound IPsec security + * association. That includes, but is not limited to, algorithm choice, key material, and allocated + * system resources. * - *

An IpSecTransform may either represent a tunnel mode transform that operates on a wide array - * of traffic or may represent a transport mode transform operating on a Socket or Sockets. + * @see RFC 4301, Security Architecture for the + * Internet Protocol */ public final class IpSecTransform implements AutoCloseable { private static final String TAG = "IpSecTransform"; /** - * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies - * to traffic towards the host. + * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute + * applies to traffic towards the host. */ public static final int DIRECTION_IN = 0; /** - * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies - * to traffic from the host. + * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute + * applies to traffic from the host. */ public static final int DIRECTION_OUT = 1; @@ -77,16 +79,16 @@ public final class IpSecTransform implements AutoCloseable { public static final int ENCAP_NONE = 0; /** - * IpSec traffic will be encapsulated within a UDP header with an additional 8-byte header pad - * (of '0'-value bytes) that prevents traffic from being interpreted as IKE or as ESP over UDP. + * IPsec traffic will be encapsulated within UDP, but with 8 zero-value bytes between the UDP + * header and payload. This prevents traffic from being interpreted as ESP or IKEv2. * * @hide */ public static final int ENCAP_ESPINUDP_NON_IKE = 1; /** - * IpSec traffic will be encapsulated within UDP as per RFC3498. + * IPsec traffic will be encapsulated within UDP as per + * RFC 3498. * * @hide */ @@ -165,13 +167,14 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Deactivate an IpSecTransform and free all resources for that transform that are managed by - * the system for this Transform. + * Deactivate this {@code IpSecTransform} and free allocated resources. * - *

Deactivating a transform while it is still applied to any Socket will result in sockets - * refusing to send or receive data. This method will silently succeed if the specified - * transform has already been removed; thus, it is always safe to attempt cleanup when a - * transform is no longer needed. + *

Deactivating a transform while it is still applied to a socket will result in errors on + * that socket. Make sure to remove transforms by calling {@link + * IpSecManager#removeTransportModeTransform}. Note, removing an {@code IpSecTransform} from a + * socket will not deactivate it (because one transform may be applied to multiple sockets). + * + *

It is safe to call this method on a transform that has already been deactivated. */ public void close() { Log.d(TAG, "Removing Transform with Id " + mResourceId); @@ -197,6 +200,7 @@ public final class IpSecTransform implements AutoCloseable { } } + /** Check that the transform was closed properly. */ @Override protected void finalize() throws Throwable { if (mCloseGuard != null) { @@ -264,65 +268,63 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Builder object to facilitate the creation of IpSecTransform objects. - * - *

Apply additional properties to the transform and then call a build() method to return an - * IpSecTransform object. - * - * @see Builder#buildTransportModeTransform(InetAddress) + * This class is used to build {@link IpSecTransform} objects. */ public static class Builder { private Context mContext; private IpSecConfig mConfig; /** - * Add an encryption algorithm to the transform for the given direction. + * Set the encryption algorithm for the given direction. * - *

If encryption is set for a given direction without also providing an SPI for that - * direction, creation of an IpSecTransform will fail upon calling a build() method. + *

If encryption is set for a direction without also providing an SPI for that direction, + * creation of an {@code IpSecTransform} will fail when attempting to build the transform. * - *

Authenticated encryption is mutually exclusive with encryption and authentication. + *

Encryption is mutually exclusive with authenticated encryption. * - * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} + * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. */ public IpSecTransform.Builder setEncryption( @TransformDirection int direction, IpSecAlgorithm algo) { + // TODO: throw IllegalArgumentException if algo is not an encryption algorithm. mConfig.setEncryption(direction, algo); return this; } /** - * Add an authentication/integrity algorithm to the transform. + * Set the authentication (integrity) algorithm for the given direction. * - *

If authentication is set for a given direction without also providing an SPI for that - * direction, creation of an IpSecTransform will fail upon calling a build() method. + *

If authentication is set for a direction without also providing an SPI for that + * direction, creation of an {@code IpSecTransform} will fail when attempting to build the + * transform. * - *

Authenticated encryption is mutually exclusive with encryption and authentication. + *

Authentication is mutually exclusive with authenticated encryption. * - * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} + * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. */ public IpSecTransform.Builder setAuthentication( @TransformDirection int direction, IpSecAlgorithm algo) { + // TODO: throw IllegalArgumentException if algo is not an authentication algorithm. mConfig.setAuthentication(direction, algo); return this; } /** - * Add an authenticated encryption algorithm to the transform for the given direction. + * Set the authenticated encryption algorithm for the given direction. * *

If an authenticated encryption algorithm is set for a given direction without also - * providing an SPI for that direction, creation of an IpSecTransform will fail upon calling - * a build() method. + * providing an SPI for that direction, creation of an {@code IpSecTransform} will fail when + * attempting to build the transform. * *

The Authenticated Encryption (AE) class of algorithms are also known as Authenticated * Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as - * referred to in RFC 4301) + * referred to in RFC 4301). * *

Authenticated encryption is mutually exclusive with encryption and authentication. * - * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} + * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to * be applied. */ @@ -333,19 +335,16 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Set the SPI, which uniquely identifies a particular IPsec session from others. Because - * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a - * given destination address. + * Set the SPI for the given direction. * - *

Care should be chosen when selecting an SPI to ensure that is is as unique as - * possible. To reserve a value call {@link IpSecManager#reserveSecurityParameterIndex(int, - * InetAddress, int)}. Otherwise, SPI collisions would prevent a transform from being - * activated. IpSecManager#reserveSecurityParameterIndex(int, InetAddres$s, int)}. + *

Because IPsec operates at the IP layer, this 32-bit identifier uniquely identifies + * packets to a given destination address. To prevent SPI collisions, values should be + * reserved by calling {@link IpSecManager#reserveSecurityParameterIndex}. * - *

Unless an SPI is set for a given direction, traffic in that direction will be - * sent/received without any IPsec applied. + *

If the SPI and algorithms are omitted for one direction, traffic in that direction + * will not be encrypted or authenticated. * - * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT} + * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed * traffic */ @@ -356,11 +355,10 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Specify the network on which this transform will emit its traffic; (otherwise it will - * emit on the default network). + * Set the {@link Network} which will carry tunneled traffic. * - *

Restricts the transformed traffic to a particular {@link Network}. This is required in - * tunnel mode. + *

Restricts the transformed traffic to a particular {@link Network}. This is required + * for tunnel mode, otherwise tunneled traffic would be sent on the default network. * * @hide */ @@ -371,15 +369,18 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Add UDP encapsulation to an IPv4 transform + * Add UDP encapsulation to an IPv4 transform. * - *

This option allows IPsec traffic to pass through NAT. Refer to RFC 3947 and 3948 for - * details on how UDP should be applied to IPsec. + *

This allows IPsec traffic to pass through a NAT. * - * @param localSocket a {@link IpSecManager.UdpEncapsulationSocket} for sending and - * receiving encapsulating traffic. - * @param remotePort the UDP port number of the remote that will send and receive - * encapsulated traffic. In the case of IKE, this is likely port 4500. + * @see RFC 3948, UDP Encapsulation of IPsec + * ESP Packets + * @see RFC 7296 section 2.23, + * NAT Traversal of IKEv2 + * + * @param localSocket a socket for sending and receiving encapsulated traffic + * @param remotePort the UDP port number of the remote host that will send and receive + * encapsulated traffic. In the case of IKEv2, this should be port 4500. */ public IpSecTransform.Builder setIpv4Encapsulation( IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { @@ -393,12 +394,15 @@ public final class IpSecTransform implements AutoCloseable { // TODO: Probably a better exception to throw for NATTKeepalive failure // TODO: Specify the needed NATT keepalive permission. /** - * Send a NATT Keepalive packet with a given maximum interval. This will create an offloaded - * request to do power-efficient NATT Keepalive. If NATT keepalive is requested but cannot - * be activated, then the transform will fail to activate and throw an IOException. + * Set NAT-T keepalives to be sent with a given interval. + * + *

This will set power-efficient keepalive packets to be sent by the system. If NAT-T + * keepalive is requested but cannot be activated, then creation of an {@link + * IpSecTransform} will fail when calling the build method. + * + * @param intervalSeconds the maximum number of seconds between keepalive packets. Must be + * between 20s and 3600s. * - * @param intervalSeconds the maximum number of seconds between keepalive packets, no less - * than 20s and no more than 3600s. * @hide */ @SystemApi @@ -408,36 +412,29 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Build and return an active {@link IpSecTransform} object as a Transport Mode Transform. - * Some parameters have interdependencies that are checked at build time. If a well-formed - * transform cannot be created from the supplied parameters, this method will throw an - * Exception. + * Build a transport mode {@link IpSecTransform}. * - *

Upon a successful return from this call, the provided IpSecTransform will be active - * and may be applied to sockets. If too many IpSecTransform objects are active for a given - * user this operation will fail and throw ResourceUnavailableException. To avoid these - * exceptions, unused Transform objects must be cleaned up by calling {@link - * IpSecTransform#close()} when they are no longer needed. + *

This builds and activates a transport mode transform. Note that an active transform + * will not affect any network traffic until it has been applied to one or more sockets. * - * @param remoteAddress the {@link InetAddress} that, when matched on traffic to/from this - * socket will cause the transform to be applied. - *

Note that an active transform will not impact any network traffic until it has - * been applied to one or more Sockets. Calling this method is a necessary precondition - * for applying it to a socket, but is not sufficient to actually apply IPsec. + * @see IpSecManager#applyTransportModeTransform + * + * @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use + * this transform * @throws IllegalArgumentException indicating that a particular combination of transform - * properties is invalid. - * @throws IpSecManager.ResourceUnavailableException in the event that no more Transforms - * may be allocated - * @throws SpiUnavailableException if the SPI collides with an existing transform - * (unlikely). - * @throws ResourceUnavailableException if the current user currently has exceeded the - * number of allowed active transforms. + * properties is invalid + * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms are + * active + * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI + * collides with an existing transform + * @throws IOException indicating other errors */ public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress) throws IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException, IOException { mConfig.setMode(MODE_TRANSPORT); mConfig.setRemoteAddress(remoteAddress.getHostAddress()); + // FIXME: modifying a builder after calling build can change the built transform. return new IpSecTransform(mContext, mConfig).activate(); } @@ -465,9 +462,9 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Create a new IpSecTransform.Builder to construct an IpSecTransform + * Create a new IpSecTransform.Builder. * - * @param context current Context + * @param context current context */ public Builder(@NonNull Context context) { Preconditions.checkNotNull(context); From 7175f27cbe603e241d3c16ab34c1a304381350ee Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 9 Nov 2017 16:49:33 -0800 Subject: [PATCH 067/881] Validate IpSecAlgorithm Length Improve the Validation of IpSecAlgorithm by explicitly checking the length in addition to the truncation length (previously an oversight). In addition, we now check the lengths during un-parceling, which will catch someone maliciously manually building a parcel and passing it, bypassing the checks in the constructor. Bug: 68780091 Test: runtest -x IpSecAlgorithmTest.java Change-Id: I8172762617264d34f47d5144336464510f07a701 --- core/java/android/net/IpSecAlgorithm.java | 72 ++++++++++++++++------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index d6e62cf1f8..f82627b942 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -21,6 +21,7 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.HexDump; import java.lang.annotation.Retention; @@ -34,6 +35,8 @@ import java.util.Arrays; * Internet Protocol */ public final class IpSecAlgorithm implements Parcelable { + private static final String TAG = "IpSecAlgorithm"; + /** * AES-CBC Encryption/Ciphering Algorithm. * @@ -45,6 +48,7 @@ public final class IpSecAlgorithm implements Parcelable { * MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in * new applications and is provided for legacy compatibility with 3gpp infrastructure. * + *

Keys for this algorithm must be 128 bits in length. *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 128. */ public static final String AUTH_HMAC_MD5 = "hmac(md5)"; @@ -53,6 +57,7 @@ public final class IpSecAlgorithm implements Parcelable { * SHA1 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in * new applications and is provided for legacy compatibility with 3gpp infrastructure. * + *

Keys for this algorithm must be 160 bits in length. *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 160. */ public static final String AUTH_HMAC_SHA1 = "hmac(sha1)"; @@ -60,6 +65,7 @@ public final class IpSecAlgorithm implements Parcelable { /** * SHA256 HMAC Authentication/Integrity Algorithm. * + *

Keys for this algorithm must be 256 bits in length. *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 256. */ public static final String AUTH_HMAC_SHA256 = "hmac(sha256)"; @@ -67,6 +73,7 @@ public final class IpSecAlgorithm implements Parcelable { /** * SHA384 HMAC Authentication/Integrity Algorithm. * + *

Keys for this algorithm must be 384 bits in length. *

Valid truncation lengths are multiples of 8 bits from 192 to (default) 384. */ public static final String AUTH_HMAC_SHA384 = "hmac(sha384)"; @@ -74,6 +81,7 @@ public final class IpSecAlgorithm implements Parcelable { /** * SHA512 HMAC Authentication/Integrity Algorithm. * + *

Keys for this algorithm must be 512 bits in length. *

Valid truncation lengths are multiples of 8 bits from 256 to (default) 512. */ public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; @@ -130,12 +138,10 @@ public final class IpSecAlgorithm implements Parcelable { * @param truncLenBits number of bits of output hash to use. */ public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) { - if (!isTruncationLengthValid(algorithm, truncLenBits)) { - throw new IllegalArgumentException("Unknown algorithm or invalid length"); - } mName = algorithm; mKey = key.clone(); - mTruncLenBits = Math.min(truncLenBits, key.length * 8); + mTruncLenBits = truncLenBits; + checkValidOrThrow(mName, mKey.length * 8, mTruncLenBits); } /** Get the algorithm name */ @@ -169,7 +175,11 @@ public final class IpSecAlgorithm implements Parcelable { public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecAlgorithm createFromParcel(Parcel in) { - return new IpSecAlgorithm(in); + final String name = in.readString(); + final byte[] key = in.createByteArray(); + final int truncLenBits = in.readInt(); + + return new IpSecAlgorithm(name, key, truncLenBits); } public IpSecAlgorithm[] newArray(int size) { @@ -177,30 +187,47 @@ public final class IpSecAlgorithm implements Parcelable { } }; - private IpSecAlgorithm(Parcel in) { - mName = in.readString(); - mKey = in.createByteArray(); - mTruncLenBits = in.readInt(); - } + private static void checkValidOrThrow(String name, int keyLen, int truncLen) { + boolean isValidLen = true; + boolean isValidTruncLen = true; - private static boolean isTruncationLengthValid(String algo, int truncLenBits) { - switch (algo) { + switch(name) { case CRYPT_AES_CBC: - return (truncLenBits == 128 || truncLenBits == 192 || truncLenBits == 256); + isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256; + break; case AUTH_HMAC_MD5: - return (truncLenBits >= 96 && truncLenBits <= 128); + isValidLen = keyLen == 128; + isValidTruncLen = truncLen >= 96 && truncLen <= 128; + break; case AUTH_HMAC_SHA1: - return (truncLenBits >= 96 && truncLenBits <= 160); + isValidLen = keyLen == 160; + isValidTruncLen = truncLen >= 96 && truncLen <= 160; + break; case AUTH_HMAC_SHA256: - return (truncLenBits >= 96 && truncLenBits <= 256); + isValidLen = keyLen == 256; + isValidTruncLen = truncLen >= 96 && truncLen <= 256; + break; case AUTH_HMAC_SHA384: - return (truncLenBits >= 192 && truncLenBits <= 384); + isValidLen = keyLen == 384; + isValidTruncLen = truncLen >= 192 && truncLen <= 384; + break; case AUTH_HMAC_SHA512: - return (truncLenBits >= 256 && truncLenBits <= 512); + isValidLen = keyLen == 512; + isValidTruncLen = truncLen >= 256 && truncLen <= 512; + break; case AUTH_CRYPT_AES_GCM: - return (truncLenBits == 64 || truncLenBits == 96 || truncLenBits == 128); + // The keying material for GCM is a key plus a 32-bit salt + isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32; + break; default: - return false; + throw new IllegalArgumentException("Couldn't find an algorithm: " + name); + } + + if (!isValidLen) { + throw new IllegalArgumentException("Invalid key material keyLength: " + keyLen); + } + if (!isValidTruncLen) { + throw new IllegalArgumentException("Invalid truncation keyLength: " + truncLen); } } @@ -217,8 +244,9 @@ public final class IpSecAlgorithm implements Parcelable { .toString(); } - /** package */ - static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) { + /** @hide */ + @VisibleForTesting + public static boolean equals(IpSecAlgorithm lhs, IpSecAlgorithm rhs) { if (lhs == null || rhs == null) return (lhs == rhs); return (lhs.mName.equals(rhs.mName) && Arrays.equals(lhs.mKey, rhs.mKey) From 152b263678b431d3e666ffa322827d608faf51f2 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 29 Nov 2017 11:18:23 -0700 Subject: [PATCH 068/881] API for apps to tag sockets with their own UID. This enables app A to create a socket, pass it to app B, and have app B accept blame for the traffic performed on that socket. Also adds helpful public APIs for tagging raw FileDescriptor sockets instead of making developers go through shady SocketImpl wrappers. Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AppSecurityTests#testAppFailAccessPrivateData Bug: 63932076 Change-Id: I08925c843974675fc82e4080cec2eaab9ab7cd41 --- core/java/android/net/TrafficStats.java | 39 +++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index c339856f43..954e59c2c4 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.DownloadManager; import android.app.backup.BackupManager; @@ -30,6 +31,8 @@ import com.android.server.NetworkManagementSocketTagger; import dalvik.system.SocketTagger; +import java.io.FileDescriptor; +import java.io.IOException; import java.net.DatagramSocket; import java.net.Socket; import java.net.SocketException; @@ -263,15 +266,26 @@ public class TrafficStats { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); } + /** + * Set specific UID to use when accounting {@link Socket} traffic + * originating from the current thread as the calling UID. Designed for use + * when another application is performing operations on your behalf. + *

+ * Changes only take effect during subsequent calls to + * {@link #tagSocket(Socket)}. + */ + public static void setThreadStatsUidSelf() { + setThreadStatsUid(android.os.Process.myUid()); + } + /** * Clear any active UID set to account {@link Socket} traffic originating * from the current thread. * * @see #setThreadStatsUid(int) - * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) + @SuppressLint("Doclava125") public static void clearThreadStatsUid() { NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); } @@ -315,6 +329,27 @@ public class TrafficStats { SocketTagger.get().untag(socket); } + /** + * Tag the given {@link FileDescriptor} socket with any statistics + * parameters active for the current thread. Subsequent calls always replace + * any existing parameters. When finished, call + * {@link #untagFileDescriptor(FileDescriptor)} to remove statistics + * parameters. + * + * @see #setThreadStatsTag(int) + */ + public static void tagFileDescriptor(FileDescriptor fd) throws IOException { + SocketTagger.get().tag(fd); + } + + /** + * Remove any statistics parameters from the given {@link FileDescriptor} + * socket. + */ + public static void untagFileDescriptor(FileDescriptor fd) throws IOException { + SocketTagger.get().untag(fd); + } + /** * Start profiling data usage for current UID. Only one profiling session * can be active at a time. From f33f4845b3ca71f9962ef2aedad77942b3c2d1c0 Mon Sep 17 00:00:00 2001 From: Jonathan Basseri Date: Thu, 16 Nov 2017 10:58:01 -0800 Subject: [PATCH 069/881] Use consistent naming for allocating SPI. Throughout the IPsec code (API, system server, netd) we use "reserve" SPI and "allocate" SPI interchangeably. This renames to use "allocate" everywhere for self-consistency and consistency with the kernel (ALLOCSPI). In javadoc, I am leaving the word "reserve" in several places because it is still an accurate description of how the method behaves. Bug: 69128142 Test: TreeHugger should be enough Change-Id: I8ea603b4612303b0393beef04032671fa53d2106 --- core/java/android/net/IIpSecService.aidl | 2 +- core/java/android/net/IpSecManager.java | 59 +++++++++++-------- core/java/android/net/IpSecTransform.java | 22 +++---- .../java/com/android/server/IpSecService.java | 6 +- 4 files changed, 45 insertions(+), 44 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 0b1ea98f2e..d9b57db180 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -30,7 +30,7 @@ import android.os.ParcelFileDescriptor; */ interface IIpSecService { - IpSecSpiResponse reserveSecurityParameterIndex( + IpSecSpiResponse allocateSecurityParameterIndex( int direction, in String remoteAddress, int requestedSpi, in IBinder binder); void releaseSecurityParameterIndex(int resourceId); diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index a9e60ec88a..6a4b891478 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -46,7 +46,7 @@ import java.net.Socket; * to create a VPN should use {@link VpnService}. * * @see RFC 4301, Security Architecture for the - * Internet Protocol + * Internet Protocol */ @SystemService(Context.IPSEC_SERVICE) public final class IpSecManager { @@ -59,8 +59,7 @@ public final class IpSecManager { * * @hide */ - @TestApi - public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; + @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; /** @hide */ public interface Status { @@ -78,7 +77,7 @@ public final class IpSecManager { *

The combination of remote {@code InetAddress} and SPI must be unique across all apps on * one device. If this error is encountered, a new SPI is required before a transform may be * created. This error can be avoided by calling {@link - * IpSecManager#reserveSecurityParameterIndex}. + * IpSecManager#allocateSecurityParameterIndex}. */ public static final class SpiUnavailableException extends AndroidException { private final int mSpi; @@ -121,7 +120,7 @@ public final class IpSecManager { * This class represents a reserved SPI. * *

Objects of this type are used to track reserved security parameter indices. They can be - * obtained by calling {@link IpSecManager#reserveSecurityParameterIndex} and must be released + * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released * by calling {@link #close()} when they are no longer needed. */ public static final class SecurityParameterIndex implements AutoCloseable { @@ -170,7 +169,7 @@ public final class IpSecManager { mRemoteAddress = remoteAddress; try { IpSecSpiResponse result = - mService.reserveSecurityParameterIndex( + mService.allocateSecurityParameterIndex( direction, remoteAddress.getHostAddress(), spi, new Binder()); if (result == null) { @@ -228,7 +227,7 @@ public final class IpSecManager { * for this user * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved */ - public SecurityParameterIndex reserveSecurityParameterIndex( + public SecurityParameterIndex allocateSecurityParameterIndex( int direction, InetAddress remoteAddress) throws ResourceUnavailableException { try { return new SecurityParameterIndex( @@ -255,7 +254,7 @@ public final class IpSecManager { * for this user * @throws SpiUnavailableException indicating that the requested SPI could not be reserved */ - public SecurityParameterIndex reserveSecurityParameterIndex( + public SecurityParameterIndex allocateSecurityParameterIndex( int direction, InetAddress remoteAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { @@ -273,16 +272,18 @@ public final class IpSecManager { * unprotected traffic can resume on that socket. * *

For security reasons, the destination address of any traffic on the socket must match the - * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any + * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any * other IP address will result in an IOException. In addition, reads and writes on the socket * will throw IOException if the user deactivates the transform (by calling {@link * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. * - *

Rekey Procedure

When applying a new tranform to a socket, the previous transform - * will be removed. However, inbound traffic on the old transform will continue to be decrypted - * until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap - * allows rekey procedures where both transforms are valid until both endpoints are using the - * new transform and all in-flight packets have been received. + *

Rekey Procedure

+ * + *

When applying a new tranform to a socket, the previous transform will be removed. However, + * inbound traffic on the old transform will continue to be decrypted until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures + * where both transforms are valid until both endpoints are using the new transform and all + * in-flight packets have been received. * * @param socket a stream socket * @param transform a transport mode {@code IpSecTransform} @@ -310,11 +311,13 @@ public final class IpSecManager { * will throw IOException if the user deactivates the transform (by calling {@link * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. * - *

Rekey Procedure

When applying a new tranform to a socket, the previous transform - * will be removed. However, inbound traffic on the old transform will continue to be decrypted - * until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap - * allows rekey procedures where both transforms are valid until both endpoints are using the - * new transform and all in-flight packets have been received. + *

Rekey Procedure

+ * + *

When applying a new tranform to a socket, the previous transform will be removed. However, + * inbound traffic on the old transform will continue to be decrypted until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures + * where both transforms are valid until both endpoints are using the new transform and all + * in-flight packets have been received. * * @param socket a datagram socket * @param transform a transport mode {@code IpSecTransform} @@ -342,11 +345,13 @@ public final class IpSecManager { * will throw IOException if the user deactivates the transform (by calling {@link * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. * - *

Rekey Procedure

When applying a new tranform to a socket, the previous transform - * will be removed. However, inbound traffic on the old transform will continue to be decrypted - * until that transform is deallocated by calling {@link IpSecTransform#close()}. This overlap - * allows rekey procedures where both transforms are valid until both endpoints are using the - * new transform and all in-flight packets have been received. + *

Rekey Procedure

+ * + *

When applying a new tranform to a socket, the previous transform will be removed. However, + * inbound traffic on the old transform will continue to be decrypted until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures + * where both transforms are valid until both endpoints are using the new transform and all + * in-flight packets have been received. * * @param socket a socket file descriptor * @param transform a transport mode {@code IpSecTransform} @@ -379,7 +384,8 @@ public final class IpSecManager { * Applications should probably not use this API directly. Instead, they should use {@link * VpnService} to provide VPN capability in a more generic fashion. * - * TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. + *

TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. + * * @param net a {@link Network} that will be tunneled via IP Sec. * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform. * @hide @@ -469,7 +475,8 @@ public final class IpSecManager { * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is * lost, all traffic will drop. * - * TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. + *

TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. + * * @param net a network that currently has transform applied to it. * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given * network diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index cda4ec762c..7cd742b417 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -47,7 +47,7 @@ import java.net.InetAddress; * system resources. * * @see RFC 4301, Security Architecture for the - * Internet Protocol + * Internet Protocol */ public final class IpSecTransform implements AutoCloseable { private static final String TAG = "IpSecTransform"; @@ -116,8 +116,7 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Checks the result status and throws an appropriate exception if - * the status is not Status.OK. + * Checks the result status and throws an appropriate exception if the status is not Status.OK. */ private void checkResultStatus(int status) throws IOException, IpSecManager.ResourceUnavailableException, @@ -267,9 +266,7 @@ public final class IpSecTransform implements AutoCloseable { return; } - /** - * This class is used to build {@link IpSecTransform} objects. - */ + /** This class is used to build {@link IpSecTransform} objects. */ public static class Builder { private Context mContext; private IpSecConfig mConfig; @@ -339,7 +336,7 @@ public final class IpSecTransform implements AutoCloseable { * *

Because IPsec operates at the IP layer, this 32-bit identifier uniquely identifies * packets to a given destination address. To prevent SPI collisions, values should be - * reserved by calling {@link IpSecManager#reserveSecurityParameterIndex}. + * reserved by calling {@link IpSecManager#allocateSecurityParameterIndex}. * *

If the SPI and algorithms are omitted for one direction, traffic in that direction * will not be encrypted or authenticated. @@ -374,10 +371,9 @@ public final class IpSecTransform implements AutoCloseable { *

This allows IPsec traffic to pass through a NAT. * * @see RFC 3948, UDP Encapsulation of IPsec - * ESP Packets + * ESP Packets * @see RFC 7296 section 2.23, - * NAT Traversal of IKEv2 - * + * NAT Traversal of IKEv2 * @param localSocket a socket for sending and receiving encapsulated traffic * @param remotePort the UDP port number of the remote host that will send and receive * encapsulated traffic. In the case of IKEv2, this should be port 4500. @@ -402,7 +398,6 @@ public final class IpSecTransform implements AutoCloseable { * * @param intervalSeconds the maximum number of seconds between keepalive packets. Must be * between 20s and 3600s. - * * @hide */ @SystemApi @@ -418,7 +413,6 @@ public final class IpSecTransform implements AutoCloseable { * will not affect any network traffic until it has been applied to one or more sockets. * * @see IpSecManager#applyTransportModeTransform - * * @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use * this transform * @throws IllegalArgumentException indicating that a particular combination of transform @@ -453,8 +447,8 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform buildTunnelModeTransform( InetAddress localAddress, InetAddress remoteAddress) { - //FIXME: argument validation here - //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); + // FIXME: argument validation here + // throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); mConfig.setLocalAddress(localAddress.getHostAddress()); mConfig.setRemoteAddress(remoteAddress.getHostAddress()); mConfig.setMode(MODE_TUNNEL); diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 1154fbe609..72d2c4d608 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -672,15 +672,15 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Invalid Direction: " + direction); } - @Override /** Get a new SPI and maintain the reservation in the system server */ - public synchronized IpSecSpiResponse reserveSecurityParameterIndex( + @Override + public synchronized IpSecSpiResponse allocateSecurityParameterIndex( int direction, String remoteAddress, int requestedSpi, IBinder binder) throws RemoteException { checkDirection(direction); checkInetAddress(remoteAddress); /* requestedSpi can be anything in the int range, so no check is needed. */ - checkNotNull(binder, "Null Binder passed to reserveSecurityParameterIndex"); + checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); int resourceId = mNextResourceId.getAndIncrement(); From 59c8818d6d8d91927335b486700f109727371203 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 26 Oct 2017 19:41:43 -0700 Subject: [PATCH 070/881] Add reference counted resources to IpSecService This patch adds (but does not enable the usage of) RefcountedResource objects to IpSecService, with tests to ensure correct function. This is patch 1 of a series of patches to refactor the resource management systems in IpSecService. RefcountedResource objects allow for management of acyclical dependency trees, ensuring eventual cleanup when resources are no longer used. This cleanup may be triggered by binder death or by explicit user action. Bug: 63409385 Test: New tests written in IpSecServiceRefcountedResourceTest, explicitly testing the RefcountedResource class Change-Id: Ib5be7482b2ef5f1c8dec9be68f15e90d8b3aba6d --- .../java/com/android/server/IpSecService.java | 219 ++++++++++++++++-- 1 file changed, 199 insertions(+), 20 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 1154fbe609..92db7cc834 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -57,11 +57,23 @@ import java.io.PrintWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import libcore.io.IoUtils; -/** @hide */ +/** + * A service to manage multiple clients that want to access the IpSec API. The service is + * responsible for maintaining a list of clients and managing the resources (and related quotas) + * that each of them own. + * + *

Synchronization in IpSecService is done on all entrypoints due to potential race conditions at + * the kernel/xfrm level. Further, this allows the simplifying assumption to be made that only one + * thread is ever running at a time. + * + * @hide + */ public class IpSecService extends IIpSecService.Stub { private static final String TAG = "IpSecService"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); @@ -92,15 +104,15 @@ public class IpSecService extends IIpSecService.Stub { private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); @GuardedBy("this") - private final ManagedResourceArray mSpiRecords = new ManagedResourceArray<>(); + private final KernelResourceArray mSpiRecords = new KernelResourceArray<>(); @GuardedBy("this") - private final ManagedResourceArray mTransformRecords = - new ManagedResourceArray<>(); + private final KernelResourceArray mTransformRecords = + new KernelResourceArray<>(); @GuardedBy("this") - private final ManagedResourceArray mUdpSocketRecords = - new ManagedResourceArray<>(); + private final KernelResourceArray mUdpSocketRecords = + new KernelResourceArray<>(); interface IpSecServiceConfiguration { INetd getNetdInstance() throws RemoteException; @@ -120,6 +132,173 @@ public class IpSecService extends IIpSecService.Stub { private final IpSecServiceConfiguration mSrvConfig; + /** + * Interface for user-reference and kernel-resource cleanup. + * + *

This interface must be implemented for a resource to be reference counted. + */ + @VisibleForTesting + public interface IResource { + /** + * Invalidates a IResource object, ensuring it is invalid for the purposes of allocating new + * objects dependent on it. + * + *

Implementations of this method are expected to remove references to the IResource + * object from the IpSecService's tracking arrays. The removal from the arrays ensures that + * the resource is considered invalid for user access or allocation or use in other + * resources. + * + *

References to the IResource object may be held by other RefcountedResource objects, + * and as such, the kernel resources and quota may not be cleaned up. + */ + void invalidate() throws RemoteException; + + /** + * Releases underlying resources and related quotas. + * + *

Implementations of this method are expected to remove all system resources that are + * tracked by the IResource object. Due to other RefcountedResource objects potentially + * having references to the IResource object, releaseKernelResources may not always be + * called from releaseIfUnreferencedRecursively(). + */ + void freeUnderlyingResources() throws RemoteException; + } + + /** + * RefcountedResource manages references and dependencies in an exclusively acyclic graph. + * + *

RefcountedResource implements both explicit and implicit resource management. Creating a + * RefcountedResource object creates an explicit reference that must be freed by calling + * userRelease(). Additionally, adding this object as a child of another RefcountedResource + * object will add an implicit reference. + * + *

Resources are cleaned up when all references, both implicit and explicit, are released + * (ie, when userRelease() is called and when all parents have called releaseReference() on this + * object.) + */ + @VisibleForTesting + public class RefcountedResource implements IBinder.DeathRecipient { + private final T mResource; + private final List mChildren; + int mRefCount = 1; // starts at 1 for user's reference. + IBinder mBinder; + + RefcountedResource(T resource, IBinder binder, RefcountedResource... children) { + synchronized (IpSecService.this) { + this.mResource = resource; + this.mChildren = new ArrayList<>(children.length); + this.mBinder = binder; + + for (RefcountedResource child : children) { + mChildren.add(child); + child.mRefCount++; + } + + try { + mBinder.linkToDeath(this, 0); + } catch (RemoteException e) { + binderDied(); + } + } + } + + /** + * If the Binder object dies, this function is called to free the system resources that are + * being managed by this record and to subsequently release this record for garbage + * collection + */ + @Override + public void binderDied() { + synchronized (IpSecService.this) { + try { + userRelease(); + } catch (Exception e) { + Log.e(TAG, "Failed to release resource: " + e); + } + } + } + + public T getResource() { + return mResource; + } + + /** + * Unlinks from binder and performs IpSecService resource cleanup (removes from resource + * arrays) + * + *

If this method has been previously called, the RefcountedResource's binder field will + * be null, and the method will return without performing the cleanup a second time. + * + *

Note that calling this function does not imply that kernel resources will be freed at + * this time, or that the related quota will be returned. Such actions will only be + * performed upon the reference count reaching zero. + */ + @GuardedBy("IpSecService.this") + public void userRelease() throws RemoteException { + // Prevent users from putting reference counts into a bad state by calling + // userRelease() multiple times. + if (mBinder == null) { + return; + } + + mBinder.unlinkToDeath(this, 0); + mBinder = null; + + mResource.invalidate(); + + releaseReference(); + } + + /** + * Removes a reference to this resource. If the resultant reference count is zero, the + * underlying resources are freed, and references to all child resources are also dropped + * recursively (resulting in them freeing their resources and children, etcetera) + * + *

This method also sets the reference count to an invalid value (-1) to signify that it + * has been fully released. Any subsequent calls to this method will result in an + * IllegalStateException being thrown due to resource already having been previously + * released + */ + @VisibleForTesting + @GuardedBy("IpSecService.this") + public void releaseReference() throws RemoteException { + mRefCount--; + + if (mRefCount > 0) { + return; + } else if (mRefCount < 0) { + throw new IllegalStateException( + "Invalid operation - resource has already been released."); + } + + // Cleanup own resources + mResource.freeUnderlyingResources(); + + // Cleanup child resources as needed + for (RefcountedResource child : mChildren) { + child.releaseReference(); + } + + // Enforce that resource cleanup can only be called once + // By decrementing the refcount (from 0 to -1), the next call will throw an + // IllegalStateException - it has already been released fully. + mRefCount--; + } + + @Override + public String toString() { + return new StringBuilder() + .append("{mResource=") + .append(mResource) + .append(", mRefCount=") + .append(mRefCount) + .append(", mChildren=") + .append(mChildren) + .append("}") + .toString(); + } + } + /* Very simple counting class that looks much like a counting semaphore */ public static class ResourceTracker { private final int mMax; @@ -211,13 +390,13 @@ public class IpSecService extends IIpSecService.Stub { private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker(); /** - * The ManagedResource class provides a facility to cleanly and reliably release system - * resources. It relies on two things: an IBinder that allows ManagedResource to automatically + * The KernelResource class provides a facility to cleanly and reliably release system + * resources. It relies on two things: an IBinder that allows KernelResource to automatically * clean up in the event that the Binder dies and a user-provided resourceId that should * uniquely identify the managed resource. To use this class, the user should implement the * releaseResources() method that is responsible for releasing system resources when invoked. */ - private abstract class ManagedResource implements IBinder.DeathRecipient { + private abstract class KernelResource implements IBinder.DeathRecipient { final int pid; final int uid; private IBinder mBinder; @@ -225,7 +404,7 @@ public class IpSecService extends IIpSecService.Stub { private AtomicInteger mReferenceCount = new AtomicInteger(0); - ManagedResource(int resourceId, IBinder binder) { + KernelResource(int resourceId, IBinder binder) { super(); if (resourceId == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); @@ -341,7 +520,7 @@ public class IpSecService extends IIpSecService.Stub { /** * Minimal wrapper around SparseArray that performs ownership validation on element accesses. */ - private class ManagedResourceArray { + private class KernelResourceArray { SparseArray mArray = new SparseArray<>(); T getAndCheckOwner(int key) { @@ -369,7 +548,7 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class TransformRecord extends ManagedResource { + private final class TransformRecord extends KernelResource { private final IpSecConfig mConfig; private final SpiRecord[] mSpis; private final UdpSocketRecord mSocket; @@ -456,7 +635,7 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class SpiRecord extends ManagedResource { + private final class SpiRecord extends KernelResource { private final int mDirection; private final String mLocalAddress; private final String mRemoteAddress; @@ -544,7 +723,7 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class UdpSocketRecord extends ManagedResource { + private final class UdpSocketRecord extends KernelResource { private FileDescriptor mSocket; private final int mPort; @@ -718,8 +897,8 @@ public class IpSecService extends IIpSecService.Stub { /* This method should only be called from Binder threads. Do not call this from * within the system server as it will crash the system on failure. */ - private synchronized void releaseManagedResource( - ManagedResourceArray resArray, int resourceId, String typeName) + private synchronized void releaseKernelResource( + KernelResourceArray resArray, int resourceId, String typeName) throws RemoteException { // We want to non-destructively get so that we can check credentials before removing // this from the records. @@ -737,7 +916,7 @@ public class IpSecService extends IIpSecService.Stub { /** Release a previously allocated SPI that has been registered with the system server */ @Override public void releaseSecurityParameterIndex(int resourceId) throws RemoteException { - releaseManagedResource(mSpiRecords, resourceId, "SecurityParameterIndex"); + releaseKernelResource(mSpiRecords, resourceId, "SecurityParameterIndex"); } /** @@ -827,7 +1006,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public void closeUdpEncapsulationSocket(int resourceId) throws RemoteException { - releaseManagedResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); + releaseKernelResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); } /** @@ -974,7 +1153,7 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public void deleteTransportModeTransform(int resourceId) throws RemoteException { - releaseManagedResource(mTransformRecords, resourceId, "IpSecTransform"); + releaseKernelResource(mTransformRecords, resourceId, "IpSecTransform"); } /** @@ -984,7 +1163,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void applyTransportModeTransform( ParcelFileDescriptor socket, int resourceId) throws RemoteException { - // Synchronize liberally here because we are using ManagedResources in this block + // Synchronize liberally here because we are using KernelResources in this block TransformRecord info; // FIXME: this code should be factored out into a security check + getter info = mTransformRecords.getAndCheckOwner(resourceId); From eea9cff0d15c9d9dbcc7ec56cd3a6c59f1197bbc Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 16 Nov 2017 15:27:22 -0800 Subject: [PATCH 071/881] Convert IpSecService resources to use refcounting This is part 2 of 2 of the refcounting refactor for IpSecService resources. Switched ManagedResources to use RefcountedResource structure for managing reference counts and eventual cleanup. Further, resource arrays and quota management have been aggregated into a UserRecord for better isolation. UID access checking has been similarly moved into the UserRecordTracker, and resourceId checking has been rolled into RefcountedResourceArray's accessor methods. Bug: 63409385 Test: CTS, all unit tests run on aosp_marlin-eng, new tests added Change-Id: Iee52dd1c9d2583bb6bfaf65be87569e9d50a5b63 --- .../java/com/android/server/IpSecService.java | 472 +++++++++--------- 1 file changed, 227 insertions(+), 245 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 92db7cc834..2116d9a818 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -103,17 +103,6 @@ public class IpSecService extends IIpSecService.Stub { /** Should be a never-repeating global ID for resources */ private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); - @GuardedBy("this") - private final KernelResourceArray mSpiRecords = new KernelResourceArray<>(); - - @GuardedBy("this") - private final KernelResourceArray mTransformRecords = - new KernelResourceArray<>(); - - @GuardedBy("this") - private final KernelResourceArray mUdpSocketRecords = - new KernelResourceArray<>(); - interface IpSecServiceConfiguration { INetd getNetdInstance() throws RemoteException; @@ -158,7 +147,7 @@ public class IpSecService extends IIpSecService.Stub { * *

Implementations of this method are expected to remove all system resources that are * tracked by the IResource object. Due to other RefcountedResource objects potentially - * having references to the IResource object, releaseKernelResources may not always be + * having references to the IResource object, freeUnderlyingResources may not always be * called from releaseIfUnreferencedRecursively(). */ void freeUnderlyingResources() throws RemoteException; @@ -204,7 +193,7 @@ public class IpSecService extends IIpSecService.Stub { /** * If the Binder object dies, this function is called to free the system resources that are - * being managed by this record and to subsequently release this record for garbage + * being tracked by this record and to subsequently release this record for garbage * collection */ @Override @@ -300,7 +289,8 @@ public class IpSecService extends IIpSecService.Stub { } /* Very simple counting class that looks much like a counting semaphore */ - public static class ResourceTracker { + @VisibleForTesting + static class ResourceTracker { private final int mMax; int mCurrent; @@ -309,18 +299,18 @@ public class IpSecService extends IIpSecService.Stub { mCurrent = 0; } - synchronized boolean isAvailable() { + boolean isAvailable() { return (mCurrent < mMax); } - synchronized void take() { + void take() { if (!isAvailable()) { Log.wtf(TAG, "Too many resources allocated!"); } mCurrent++; } - synchronized void give() { + void give() { if (mCurrent <= 0) { Log.wtf(TAG, "We've released this resource too many times"); } @@ -339,40 +329,70 @@ public class IpSecService extends IIpSecService.Stub { } } - private static final class UserQuotaTracker { - /* Maximum number of UDP Encap Sockets that a single UID may possess */ + @VisibleForTesting + static final class UserRecord { + /* Type names */ + public static final String TYPENAME_SPI = "SecurityParameterIndex"; + public static final String TYPENAME_TRANSFORM = "IpSecTransform"; + public static final String TYPENAME_ENCAP_SOCKET = "UdpEncapSocket"; + + /* Maximum number of each type of resource that a single UID may possess */ public static final int MAX_NUM_ENCAP_SOCKETS = 2; - - /* Maximum number of IPsec Transforms that a single UID may possess */ public static final int MAX_NUM_TRANSFORMS = 4; - - /* Maximum number of IPsec Transforms that a single UID may possess */ public static final int MAX_NUM_SPIS = 8; - /* Record for one users's IpSecService-managed objects */ - public static class UserRecord { - public final ResourceTracker socket = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); - public final ResourceTracker transform = new ResourceTracker(MAX_NUM_TRANSFORMS); - public final ResourceTracker spi = new ResourceTracker(MAX_NUM_SPIS); + final RefcountedResourceArray mSpiRecords = + new RefcountedResourceArray<>(TYPENAME_SPI); + final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS); - @Override - public String toString() { - return new StringBuilder() - .append("{socket=") - .append(socket) - .append(", transform=") - .append(transform) - .append(", spi=") - .append(spi) - .append("}") - .toString(); - } + final RefcountedResourceArray mTransformRecords = + new RefcountedResourceArray<>(TYPENAME_TRANSFORM); + final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS); + + final RefcountedResourceArray mEncapSocketRecords = + new RefcountedResourceArray<>(TYPENAME_ENCAP_SOCKET); + final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); + + void removeSpiRecord(int resourceId) { + mSpiRecords.remove(resourceId); } + void removeTransformRecord(int resourceId) { + mTransformRecords.remove(resourceId); + } + + void removeEncapSocketRecord(int resourceId) { + mEncapSocketRecords.remove(resourceId); + } + + @Override + public String toString() { + return new StringBuilder() + .append("{mSpiQuotaTracker=") + .append(mSpiQuotaTracker) + .append(", mTransformQuotaTracker=") + .append(mTransformQuotaTracker) + .append(", mSocketQuotaTracker=") + .append(mSocketQuotaTracker) + .append(", mSpiRecords=") + .append(mSpiRecords) + .append(", mTransformRecords=") + .append(mTransformRecords) + .append(", mEncapSocketRecords=") + .append(mEncapSocketRecords) + .append("}") + .toString(); + } + } + + @VisibleForTesting + static final class UserResourceTracker { private final SparseArray mUserRecords = new SparseArray<>(); - /* a never-fail getter so that we can populate the list of UIDs as-needed */ - public synchronized UserRecord getUserRecord(int uid) { + /** Never-fail getter that populates the list of UIDs as-needed */ + public UserRecord getUserRecord(int uid) { + checkCallerUid(uid); + UserRecord r = mUserRecords.get(uid); if (r == null) { r = new UserRecord(); @@ -381,122 +401,56 @@ public class IpSecService extends IIpSecService.Stub { return r; } + /** Safety method; guards against access of other user's UserRecords */ + private void checkCallerUid(int uid) { + if (uid != Binder.getCallingUid() + && android.os.Process.SYSTEM_UID != Binder.getCallingUid()) { + throw new SecurityException("Attempted access of unowned resources"); + } + } + @Override public String toString() { return mUserRecords.toString(); } } - private final UserQuotaTracker mUserQuotaTracker = new UserQuotaTracker(); + @VisibleForTesting final UserResourceTracker mUserResourceTracker = new UserResourceTracker(); /** - * The KernelResource class provides a facility to cleanly and reliably release system - * resources. It relies on two things: an IBinder that allows KernelResource to automatically - * clean up in the event that the Binder dies and a user-provided resourceId that should - * uniquely identify the managed resource. To use this class, the user should implement the - * releaseResources() method that is responsible for releasing system resources when invoked. + * The KernelResourceRecord class provides a facility to cleanly and reliably track system + * resources. It relies on a provided resourceId that should uniquely identify the kernel + * resource. To use this class, the user should implement the invalidate() and + * freeUnderlyingResources() methods that are responsible for cleaning up IpSecService resource + * tracking arrays and kernel resources, respectively */ - private abstract class KernelResource implements IBinder.DeathRecipient { + private abstract class KernelResourceRecord implements IResource { final int pid; final int uid; - private IBinder mBinder; - protected int mResourceId; + protected final int mResourceId; - private AtomicInteger mReferenceCount = new AtomicInteger(0); - - KernelResource(int resourceId, IBinder binder) { + KernelResourceRecord(int resourceId) { super(); if (resourceId == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); } - mBinder = binder; mResourceId = resourceId; pid = Binder.getCallingPid(); uid = Binder.getCallingUid(); getResourceTracker().take(); - try { - mBinder.linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - } } - public void addReference() { - mReferenceCount.incrementAndGet(); + @Override + public abstract void invalidate() throws RemoteException; + + /** Convenience method; retrieves the user resource record for the stored UID. */ + protected UserRecord getUserRecord() { + return mUserResourceTracker.getUserRecord(uid); } - public void removeReference() { - if (mReferenceCount.decrementAndGet() < 0) { - Log.wtf(TAG, "Programming error: negative reference count"); - } - } - - public boolean isReferenced() { - return (mReferenceCount.get() > 0); - } - - /** - * Ensures that the caller is either the owner of this resource or has the system UID and - * throws a SecurityException otherwise. - */ - public void checkOwnerOrSystem() { - if (uid != Binder.getCallingUid() - && android.os.Process.SYSTEM_UID != Binder.getCallingUid()) { - throw new SecurityException("Only the owner may access managed resources!"); - } - } - - /** - * When this record is no longer needed for managing system resources this function should - * clean up all system resources and nullify the record. This function shall perform all - * necessary cleanup of the resources managed by this record. - * - *

NOTE: this function verifies ownership before allowing resources to be freed. - */ - public final void release() throws RemoteException { - synchronized (IpSecService.this) { - if (isReferenced()) { - throw new IllegalStateException( - "Cannot release a resource that has active references!"); - } - - if (mResourceId == INVALID_RESOURCE_ID) { - return; - } - - releaseResources(); - getResourceTracker().give(); - if (mBinder != null) { - mBinder.unlinkToDeath(this, 0); - } - mBinder = null; - - mResourceId = INVALID_RESOURCE_ID; - } - } - - /** - * If the Binder object dies, this function is called to free the system resources that are - * being managed by this record and to subsequently release this record for garbage - * collection - */ - public final void binderDied() { - try { - release(); - } catch (Exception e) { - Log.e(TAG, "Failed to release resource: " + e); - } - } - - /** - * Implement this method to release all system resources that are being protected by this - * record. Once the resources are released, the record should be invalidated and no longer - * used by calling release(). This should NEVER be called directly. - * - *

Calls to this are always guarded by IpSecService#this - */ - protected abstract void releaseResources() throws RemoteException; + @Override + public abstract void freeUnderlyingResources() throws RemoteException; /** Get the resource tracker for this resource */ protected abstract ResourceTracker getResourceTracker(); @@ -510,30 +464,52 @@ public class IpSecService extends IIpSecService.Stub { .append(pid) .append(", uid=") .append(uid) - .append(", mReferenceCount=") - .append(mReferenceCount.get()) .append("}") .toString(); } }; + // TODO: Move this to right after RefcountedResource. With this here, Gerrit was showing many + // more things as changed. /** - * Minimal wrapper around SparseArray that performs ownership validation on element accesses. + * Thin wrapper over SparseArray to ensure resources exist, and simplify generic typing. + * + *

RefcountedResourceArray prevents null insertions, and throws an IllegalArgumentException + * if a key is not found during a retrieval process. */ - private class KernelResourceArray { - SparseArray mArray = new SparseArray<>(); + static class RefcountedResourceArray { + SparseArray> mArray = new SparseArray<>(); + private final String mTypeName; - T getAndCheckOwner(int key) { - T val = mArray.get(key); - // The value should never be null unless the resource doesn't exist - // (since we do not allow null resources to be added). - if (val != null) { - val.checkOwnerOrSystem(); - } - return val; + public RefcountedResourceArray(String typeName) { + this.mTypeName = typeName; } - void put(int key, T obj) { + /** + * Accessor method to get inner resource object. + * + * @throws IllegalArgumentException if no resource with provided key is found. + */ + T getResourceOrThrow(int key) { + return getRefcountedResourceOrThrow(key).getResource(); + } + + /** + * Accessor method to get reference counting wrapper. + * + * @throws IllegalArgumentException if no resource with provided key is found. + */ + RefcountedResource getRefcountedResourceOrThrow(int key) { + RefcountedResource resource = mArray.get(key); + if (resource == null) { + throw new IllegalArgumentException( + String.format("No such %s found for given id: %d", mTypeName, key)); + } + + return resource; + } + + void put(int key, RefcountedResource obj) { checkNotNull(obj, "Null resources cannot be added"); mArray.put(key, obj); } @@ -548,30 +524,17 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class TransformRecord extends KernelResource { + private final class TransformRecord extends KernelResourceRecord { private final IpSecConfig mConfig; private final SpiRecord[] mSpis; - private final UdpSocketRecord mSocket; + private final EncapSocketRecord mSocket; TransformRecord( - int resourceId, - IBinder binder, - IpSecConfig config, - SpiRecord[] spis, - UdpSocketRecord socket) { - super(resourceId, binder); + int resourceId, IpSecConfig config, SpiRecord[] spis, EncapSocketRecord socket) { + super(resourceId); mConfig = config; mSpis = spis; mSocket = socket; - - for (int direction : DIRECTIONS) { - mSpis[direction].addReference(); - mSpis[direction].setOwnedByTransform(); - } - - if (mSocket != null) { - mSocket.addReference(); - } } public IpSecConfig getConfig() { @@ -584,7 +547,7 @@ public class IpSecService extends IIpSecService.Stub { /** always guarded by IpSecService#this */ @Override - protected void releaseResources() { + public void freeUnderlyingResources() { for (int direction : DIRECTIONS) { int spi = mSpis[direction].getSpi(); try { @@ -603,17 +566,17 @@ public class IpSecService extends IIpSecService.Stub { } } - for (int direction : DIRECTIONS) { - mSpis[direction].removeReference(); - } - - if (mSocket != null) { - mSocket.removeReference(); - } + getResourceTracker().give(); } + @Override + public void invalidate() throws RemoteException { + getUserRecord().removeTransformRecord(mResourceId); + } + + @Override protected ResourceTracker getResourceTracker() { - return mUserQuotaTracker.getUserRecord(this.uid).transform; + return getUserRecord().mTransformQuotaTracker; } @Override @@ -635,7 +598,7 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class SpiRecord extends KernelResource { + private final class SpiRecord extends KernelResourceRecord { private final int mDirection; private final String mLocalAddress; private final String mRemoteAddress; @@ -645,12 +608,11 @@ public class IpSecService extends IIpSecService.Stub { SpiRecord( int resourceId, - IBinder binder, int direction, String localAddress, String remoteAddress, int spi) { - super(resourceId, binder); + super(resourceId); mDirection = direction; mLocalAddress = localAddress; mRemoteAddress = remoteAddress; @@ -659,7 +621,7 @@ public class IpSecService extends IIpSecService.Stub { /** always guarded by IpSecService#this */ @Override - protected void releaseResources() { + public void freeUnderlyingResources() { if (mOwnedByTransform) { Log.d(TAG, "Cannot release Spi " + mSpi + ": Currently locked by a Transform"); // Because SPIs are "handed off" to transform, objects, they should never be @@ -682,11 +644,8 @@ public class IpSecService extends IIpSecService.Stub { } mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; - } - @Override - protected ResourceTracker getResourceTracker() { - return mUserQuotaTracker.getUserRecord(this.uid).spi; + getResourceTracker().give(); } public int getSpi() { @@ -702,6 +661,16 @@ public class IpSecService extends IIpSecService.Stub { mOwnedByTransform = true; } + @Override + public void invalidate() throws RemoteException { + getUserRecord().removeSpiRecord(mResourceId); + } + + @Override + protected ResourceTracker getResourceTracker() { + return getUserRecord().mSpiQuotaTracker; + } + @Override public String toString() { StringBuilder strBuilder = new StringBuilder(); @@ -723,27 +692,24 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class UdpSocketRecord extends KernelResource { + private final class EncapSocketRecord extends KernelResourceRecord { private FileDescriptor mSocket; private final int mPort; - UdpSocketRecord(int resourceId, IBinder binder, FileDescriptor socket, int port) { - super(resourceId, binder); + EncapSocketRecord(int resourceId, FileDescriptor socket, int port) { + super(resourceId); mSocket = socket; mPort = port; } /** always guarded by IpSecService#this */ @Override - protected void releaseResources() { + public void freeUnderlyingResources() { Log.d(TAG, "Closing port " + mPort); IoUtils.closeQuietly(mSocket); mSocket = null; - } - @Override - protected ResourceTracker getResourceTracker() { - return mUserQuotaTracker.getUserRecord(this.uid).socket; + getResourceTracker().give(); } public int getPort() { @@ -754,6 +720,16 @@ public class IpSecService extends IIpSecService.Stub { return mSocket; } + @Override + protected ResourceTracker getResourceTracker() { + return getUserRecord().mSocketQuotaTracker; + } + + @Override + public void invalidate() { + getUserRecord().removeEncapSocketRecord(mResourceId); + } + @Override public String toString() { return new StringBuilder() @@ -861,13 +837,14 @@ public class IpSecService extends IIpSecService.Stub { /* requestedSpi can be anything in the int range, so no check is needed. */ checkNotNull(binder, "Null Binder passed to reserveSecurityParameterIndex"); + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); int resourceId = mNextResourceId.getAndIncrement(); int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; String localAddress = ""; try { - if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).spi.isAvailable()) { + if (!userRecord.mSpiQuotaTracker.isAvailable()) { return new IpSecSpiResponse( IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi); } @@ -881,9 +858,11 @@ public class IpSecService extends IIpSecService.Stub { remoteAddress, requestedSpi); Log.d(TAG, "Allocated SPI " + spi); - mSpiRecords.put( + userRecord.mSpiRecords.put( resourceId, - new SpiRecord(resourceId, binder, direction, localAddress, remoteAddress, spi)); + new RefcountedResource( + new SpiRecord(resourceId, direction, localAddress, remoteAddress, spi), + binder)); } catch (ServiceSpecificException e) { // TODO: Add appropriate checks when other ServiceSpecificException types are supported return new IpSecSpiResponse( @@ -897,26 +876,17 @@ public class IpSecService extends IIpSecService.Stub { /* This method should only be called from Binder threads. Do not call this from * within the system server as it will crash the system on failure. */ - private synchronized void releaseKernelResource( - KernelResourceArray resArray, int resourceId, String typeName) + private void releaseResource(RefcountedResourceArray resArray, int resourceId) throws RemoteException { - // We want to non-destructively get so that we can check credentials before removing - // this from the records. - T record = resArray.getAndCheckOwner(resourceId); - if (record == null) { - throw new IllegalArgumentException( - typeName + " " + resourceId + " is not available to be deleted"); - } - - record.release(); - resArray.remove(resourceId); + resArray.getRefcountedResourceOrThrow(resourceId).userRelease(); } /** Release a previously allocated SPI that has been registered with the system server */ @Override - public void releaseSecurityParameterIndex(int resourceId) throws RemoteException { - releaseKernelResource(mSpiRecords, resourceId, "SecurityParameterIndex"); + public synchronized void releaseSecurityParameterIndex(int resourceId) throws RemoteException { + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + releaseResource(userRecord.mSpiRecords, resourceId); } /** @@ -969,10 +939,11 @@ public class IpSecService extends IIpSecService.Stub { } checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); int resourceId = mNextResourceId.getAndIncrement(); FileDescriptor sockFd = null; try { - if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).socket.isAvailable()) { + if (!userRecord.mSocketQuotaTracker.isAvailable()) { return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } @@ -991,8 +962,10 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mUdpSocketRecords.put( - resourceId, new UdpSocketRecord(resourceId, binder, sockFd, port)); + userRecord.mEncapSocketRecords.put( + resourceId, + new RefcountedResource( + new EncapSocketRecord(resourceId, sockFd, port), binder)); return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port, sockFd); } catch (IOException | ErrnoException e) { IoUtils.closeQuietly(sockFd); @@ -1004,9 +977,9 @@ public class IpSecService extends IIpSecService.Stub { /** close a socket that has been been allocated by and registered with the system server */ @Override - public void closeUdpEncapsulationSocket(int resourceId) throws RemoteException { - - releaseKernelResource(mUdpSocketRecords, resourceId, "UdpEncapsulationSocket"); + public synchronized void closeUdpEncapsulationSocket(int resourceId) throws RemoteException { + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + releaseResource(userRecord.mEncapSocketRecords, resourceId); } /** @@ -1014,6 +987,8 @@ public class IpSecService extends IIpSecService.Stub { * IllegalArgumentException if they are not. */ private void checkIpSecConfig(IpSecConfig config) { + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + if (config.getLocalAddress() == null) { throw new IllegalArgumentException("Invalid null Local InetAddress"); } @@ -1042,12 +1017,9 @@ public class IpSecService extends IIpSecService.Stub { break; case IpSecTransform.ENCAP_ESPINUDP: case IpSecTransform.ENCAP_ESPINUDP_NON_IKE: - if (mUdpSocketRecords.getAndCheckOwner( - config.getEncapSocketResourceId()) == null) { - throw new IllegalStateException( - "No Encapsulation socket for Resource Id: " - + config.getEncapSocketResourceId()); - } + // Retrieve encap socket record; will throw IllegalArgumentException if not found + userRecord.mEncapSocketRecords.getResourceOrThrow( + config.getEncapSocketResourceId()); int port = config.getEncapRemotePort(); if (port <= 0 || port > 0xFFFF) { @@ -1071,9 +1043,8 @@ public class IpSecService extends IIpSecService.Stub { + " exclusive with other Authentication or Encryption algorithms"); } - if (mSpiRecords.getAndCheckOwner(config.getSpiResourceId(direction)) == null) { - throw new IllegalStateException("No SPI for specified Resource Id"); - } + // Retrieve SPI record; will throw IllegalArgumentException if not found + userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId(direction)); } } @@ -1090,16 +1061,27 @@ public class IpSecService extends IIpSecService.Stub { checkIpSecConfig(c); checkNotNull(binder, "Null Binder passed to createTransportModeTransform"); int resourceId = mNextResourceId.getAndIncrement(); - if (!mUserQuotaTracker.getUserRecord(Binder.getCallingUid()).transform.isAvailable()) { + + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + + // Avoid resizing by creating a dependency array of min-size 3 (1 UDP encap + 2 SPIs) + List dependencies = new ArrayList<>(3); + + if (!userRecord.mTransformQuotaTracker.isAvailable()) { return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } SpiRecord[] spis = new SpiRecord[DIRECTIONS.length]; int encapType, encapLocalPort = 0, encapRemotePort = 0; - UdpSocketRecord socketRecord = null; + EncapSocketRecord socketRecord = null; encapType = c.getEncapType(); if (encapType != IpSecTransform.ENCAP_NONE) { - socketRecord = mUdpSocketRecords.getAndCheckOwner(c.getEncapSocketResourceId()); + RefcountedResource refcountedSocketRecord = + userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow( + c.getEncapSocketResourceId()); + dependencies.add(refcountedSocketRecord); + + socketRecord = refcountedSocketRecord.getResource(); encapLocalPort = socketRecord.getPort(); encapRemotePort = c.getEncapRemotePort(); } @@ -1109,7 +1091,12 @@ public class IpSecService extends IIpSecService.Stub { IpSecAlgorithm crypt = c.getEncryption(direction); IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(direction); - spis[direction] = mSpiRecords.getAndCheckOwner(c.getSpiResourceId(direction)); + RefcountedResource refcountedSpiRecord = + userRecord.mSpiRecords.getRefcountedResourceOrThrow( + c.getSpiResourceId(direction)); + dependencies.add(refcountedSpiRecord); + + spis[direction] = refcountedSpiRecord.getResource(); int spi = spis[direction].getSpi(); try { mSrvConfig @@ -1140,8 +1127,12 @@ public class IpSecService extends IIpSecService.Stub { } } // Both SAs were created successfully, time to construct a record and lock it away - mTransformRecords.put( - resourceId, new TransformRecord(resourceId, binder, c, spis, socketRecord)); + userRecord.mTransformRecords.put( + resourceId, + new RefcountedResource( + new TransformRecord(resourceId, c, spis, socketRecord), + binder, + dependencies.toArray(new RefcountedResource[dependencies.size()]))); return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId); } @@ -1152,8 +1143,9 @@ public class IpSecService extends IIpSecService.Stub { * other reasons. */ @Override - public void deleteTransportModeTransform(int resourceId) throws RemoteException { - releaseKernelResource(mTransformRecords, resourceId, "IpSecTransform"); + public synchronized void deleteTransportModeTransform(int resourceId) throws RemoteException { + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + releaseResource(userRecord.mTransformRecords, resourceId); } /** @@ -1163,14 +1155,10 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void applyTransportModeTransform( ParcelFileDescriptor socket, int resourceId) throws RemoteException { - // Synchronize liberally here because we are using KernelResources in this block - TransformRecord info; - // FIXME: this code should be factored out into a security check + getter - info = mTransformRecords.getAndCheckOwner(resourceId); + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - if (info == null) { - throw new IllegalArgumentException("Transform " + resourceId + " is not active"); - } + // Get transform record; if no transform is found, will throw IllegalArgumentException + TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId); // TODO: make this a function. if (info.pid != getCallingPid() || info.uid != getCallingUid()) { @@ -1202,7 +1190,7 @@ public class IpSecService extends IIpSecService.Stub { * used: reserved for future improved input validation. */ @Override - public void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId) + public synchronized void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId) throws RemoteException { try { mSrvConfig @@ -1221,13 +1209,7 @@ public class IpSecService extends IIpSecService.Stub { pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead")); pw.println(); - pw.println("mUserQuotaTracker:"); - pw.println(mUserQuotaTracker); - pw.println("mTransformRecords:"); - pw.println(mTransformRecords); - pw.println("mUdpSocketRecords:"); - pw.println(mUdpSocketRecords); - pw.println("mSpiRecords:"); - pw.println(mSpiRecords); + pw.println("mUserResourceTracker:"); + pw.println(mUserResourceTracker); } } From 2dc65324056784824acfb4c5eda00ba5191c8083 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 13 Dec 2017 20:05:05 -0700 Subject: [PATCH 072/881] Add more IntDef prefixes for auto-documenting. Test: builds, boots Bug: 70177949 Exempt-From-Owner-Approval: annotation-only changes Change-Id: I76dde6054e06f52240bd4b1a0f196dcb74623608 --- core/java/android/app/usage/NetworkStats.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 222e9a0e5e..2e44a630b0 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -129,7 +129,11 @@ public final class NetworkStats implements AutoCloseable { */ public static class Bucket { /** @hide */ - @IntDef({STATE_ALL, STATE_DEFAULT, STATE_FOREGROUND}) + @IntDef(prefix = { "STATE_" }, value = { + STATE_ALL, + STATE_DEFAULT, + STATE_FOREGROUND + }) @Retention(RetentionPolicy.SOURCE) public @interface State {} @@ -164,7 +168,11 @@ public final class NetworkStats implements AutoCloseable { public static final int UID_TETHERING = TrafficStats.UID_TETHERING; /** @hide */ - @IntDef({METERED_ALL, METERED_NO, METERED_YES}) + @IntDef(prefix = { "METERED_" }, value = { + METERED_ALL, + METERED_NO, + METERED_YES + }) @Retention(RetentionPolicy.SOURCE) public @interface Metered {} @@ -187,7 +195,11 @@ public final class NetworkStats implements AutoCloseable { public static final int METERED_YES = 0x2; /** @hide */ - @IntDef({ROAMING_ALL, ROAMING_NO, ROAMING_YES}) + @IntDef(prefix = { "ROAMING_" }, value = { + ROAMING_ALL, + ROAMING_NO, + ROAMING_YES + }) @Retention(RetentionPolicy.SOURCE) public @interface Roaming {} From f5c1f305278e13c9f88633526bc3bb1d6e62fdde Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 29 Nov 2017 11:18:23 -0700 Subject: [PATCH 073/881] [CHERRY-PICK] API for apps to tag sockets with their own UID. This enables app A to create a socket, pass it to app B, and have app B accept blame for the traffic performed on that socket. Also adds helpful public APIs for tagging raw FileDescriptor sockets instead of making developers go through shady SocketImpl wrappers. Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AppSecurityTests#testAppFailAccessPrivateData Bug: 63932076 Change-Id: I08925c843974675fc82e4080cec2eaab9ab7cd41 Merged-In: I08925c843974675fc82e4080cec2eaab9ab7cd41 (cherry picked from commit 152b263678b431d3e666ffa322827d608faf51f2) --- core/java/android/net/TrafficStats.java | 39 +++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index c339856f43..954e59c2c4 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.app.DownloadManager; import android.app.backup.BackupManager; @@ -30,6 +31,8 @@ import com.android.server.NetworkManagementSocketTagger; import dalvik.system.SocketTagger; +import java.io.FileDescriptor; +import java.io.IOException; import java.net.DatagramSocket; import java.net.Socket; import java.net.SocketException; @@ -263,15 +266,26 @@ public class TrafficStats { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); } + /** + * Set specific UID to use when accounting {@link Socket} traffic + * originating from the current thread as the calling UID. Designed for use + * when another application is performing operations on your behalf. + *

+ * Changes only take effect during subsequent calls to + * {@link #tagSocket(Socket)}. + */ + public static void setThreadStatsUidSelf() { + setThreadStatsUid(android.os.Process.myUid()); + } + /** * Clear any active UID set to account {@link Socket} traffic originating * from the current thread. * * @see #setThreadStatsUid(int) - * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) + @SuppressLint("Doclava125") public static void clearThreadStatsUid() { NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); } @@ -315,6 +329,27 @@ public class TrafficStats { SocketTagger.get().untag(socket); } + /** + * Tag the given {@link FileDescriptor} socket with any statistics + * parameters active for the current thread. Subsequent calls always replace + * any existing parameters. When finished, call + * {@link #untagFileDescriptor(FileDescriptor)} to remove statistics + * parameters. + * + * @see #setThreadStatsTag(int) + */ + public static void tagFileDescriptor(FileDescriptor fd) throws IOException { + SocketTagger.get().tag(fd); + } + + /** + * Remove any statistics parameters from the given {@link FileDescriptor} + * socket. + */ + public static void untagFileDescriptor(FileDescriptor fd) throws IOException { + SocketTagger.get().untag(fd); + } + /** * Start profiling data usage for current UID. Only one profiling session * can be active at a time. From 8231eaffb0374f2f62e9ee492c98916ec1f02255 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Sun, 3 Dec 2017 19:42:36 -0800 Subject: [PATCH 074/881] [ipsec-qtaguid] Tag sockets upon creation of encap sockets Added calls to tag encap sockets to that of the UID for which the encap socket is being created on behalf of. This ensures that all data accounting generated for the UDP-encap-ESP socket is correctly billed to the right UID. Bug: 62994731 Test: New tests added to IpSecServiceTest.java, passing Change-Id: I15365ea9c982fd7b4e3cdeff314ddfba2289c86e --- core/java/android/net/TrafficStats.java | 27 ++++++++++++ .../java/com/android/server/IpSecService.java | 41 ++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 954e59c2c4..d701550817 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -19,6 +19,7 @@ package android.net; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.app.DownloadManager; import android.app.backup.BackupManager; import android.app.usage.NetworkStatsManager; @@ -154,6 +155,8 @@ public class TrafficStats { private static Object sProfilingLock = new Object(); + private static final String LOOPBACK_IFACE = "lo"; + /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. @@ -542,6 +545,30 @@ public class TrafficStats { return nativeGetIfaceStat(iface, TYPE_RX_BYTES); } + /** {@hide} */ + @TestApi + public static long getLoopbackTxPackets() { + return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_PACKETS); + } + + /** {@hide} */ + @TestApi + public static long getLoopbackRxPackets() { + return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_PACKETS); + } + + /** {@hide} */ + @TestApi + public static long getLoopbackTxBytes() { + return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_BYTES); + } + + /** {@hide} */ + @TestApi + public static long getLoopbackRxBytes() { + return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_BYTES); + } + /** * Return number of packets transmitted since device boot. Counts packets * across all network interfaces, and always increases monotonically since diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index e9eb3b3c46..a764808368 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -34,6 +34,7 @@ import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecUdpEncapResponse; import android.net.NetworkUtils; +import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; @@ -120,6 +121,7 @@ public class IpSecService extends IIpSecService.Stub { } private final IpSecServiceConfiguration mSrvConfig; + final UidFdTagger mUidFdTagger; /** * Interface for user-reference and kernel-resource cleanup. @@ -762,8 +764,23 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting public IpSecService(Context context, IpSecServiceConfiguration config) { + this(context, config, (fd, uid) -> { + try{ + TrafficStats.setThreadStatsUid(uid); + TrafficStats.tagFileDescriptor(fd); + } finally { + TrafficStats.clearThreadStatsUid(); + } + }); + } + + /** @hide */ + @VisibleForTesting + public IpSecService( + Context context, IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { mContext = context; mSrvConfig = config; + mUidFdTagger = uidFdTagger; } public void systemReady() { @@ -924,6 +941,26 @@ public class IpSecService extends IIpSecService.Stub { throw new IOException("Failed " + MAX_PORT_BIND_ATTEMPTS + " attempts to bind to a port"); } + /** + * Functional interface to do traffic tagging of given sockets to UIDs. + * + *

Specifically used by openUdpEncapsulationSocket to ensure data usage on the UDP encap + * sockets are billed to the UID that the UDP encap socket was created on behalf of. + * + *

Separate class so that the socket tagging logic can be mocked; TrafficStats uses static + * methods that cannot be easily mocked/tested. + */ + @VisibleForTesting + public interface UidFdTagger { + /** + * Sets socket tag to assign all traffic to the provided UID. + * + *

Since the socket is created on behalf of an unprivileged application, all traffic + * should be accounted to the UID of the unprivileged application. + */ + public void tag(FileDescriptor fd, int uid) throws IOException; + } + /** * Open a socket via the system server and bind it to the specified port (random if port=0). * This will return a PFD to the user that represent a bound UDP socket. The system server will @@ -939,7 +976,8 @@ public class IpSecService extends IIpSecService.Stub { } checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int callingUid = Binder.getCallingUid(); + UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); int resourceId = mNextResourceId.getAndIncrement(); FileDescriptor sockFd = null; try { @@ -948,6 +986,7 @@ public class IpSecService extends IIpSecService.Stub { } sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + mUidFdTagger.tag(sockFd, callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); From d8d9ba425902040e763e224851a5ebea61f3e4df Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 6 Dec 2017 21:56:35 -0800 Subject: [PATCH 075/881] [ipsec-doze] Add fchown to IpSecService to support doze Encap sockets are currently created as the system server, and should be fchown'd to the user for whom it was created on behalf of. Bug: 62994731 Test: New tests added and run to IpSecService Change-Id: Icc49e709ae588981e69765fdb77537d7ffbac5fe --- .../core/java/com/android/server/IpSecService.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index a764808368..d3ab1259c9 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -988,12 +988,6 @@ public class IpSecService extends IIpSecService.Stub { sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); mUidFdTagger.tag(sockFd, callingUid); - if (port != 0) { - Log.v(TAG, "Binding to port " + port); - Os.bind(sockFd, INADDR_ANY, port); - } else { - port = bindToRandomPort(sockFd); - } // This code is common to both the unspecified and specified port cases Os.setsockoptInt( sockFd, @@ -1001,6 +995,14 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); + mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(sockFd, callingUid); + if (port != 0) { + Log.v(TAG, "Binding to port " + port); + Os.bind(sockFd, INADDR_ANY, port); + } else { + port = bindToRandomPort(sockFd); + } + userRecord.mEncapSocketRecords.put( resourceId, new RefcountedResource( From 65b99191e6f665ee5c3424da4010ed536f94f75c Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Tue, 14 Nov 2017 17:54:17 -0800 Subject: [PATCH 076/881] Use NetworkStatsService to get stats for apps Move the native implementation of TrafficStats to NetworkStatsService and apps need to get the NetworkStatsService binder interface from system_server in order to get the network usage stats since boot. This implementation can hide the detail of retrieving network traffic information from apps and the NetworkStatsService can choose which methoed it use to get the data depending on the kernel version of the device. Bug: 30950746 Test: CtsNetTestCases -t android.net.cts.TrafficStatsTest Change-Id: I53bbefd19aa0b783b9b4b42ea4d76db3e9ec07a3 --- .../android/net/INetworkStatsService.aidl | 9 ++ core/java/android/net/TrafficStats.java | 114 ++++++++++++++---- .../server/net/NetworkStatsService.java | 26 ++++ ...android_server_net_NetworkStatsService.cpp | 22 +++- 4 files changed, 146 insertions(+), 25 deletions(-) rename core/jni/android_net_TrafficStats.cpp => services/core/jni/com_android_server_net_NetworkStatsService.cpp (80%) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 91801127fd..95e7f6031c 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -67,4 +67,13 @@ interface INetworkStatsService { /** Unregisters a callback on data usage. */ void unregisterUsageRequest(in DataUsageRequest request); + /** Get the uid stats information since boot */ + long getUidStats(int uid, int type); + + /** Get the iface stats information since boot */ + long getIfaceStats(String iface, int type); + + /** Get the total network stats information since boot */ + long getTotalStats(int type); + } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index d701550817..196a3bc9c8 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -505,7 +505,12 @@ public class TrafficStats { public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - final long stat = nativeGetIfaceStat(iface, TYPE_TCP_RX_PACKETS); + long stat = UNSUPPORTED; + try { + stat = getStatsService().getIfaceStats(iface, TYPE_TCP_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } if (stat != UNSUPPORTED) { total += stat; } @@ -517,7 +522,12 @@ public class TrafficStats { public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - final long stat = nativeGetIfaceStat(iface, TYPE_TCP_TX_PACKETS); + long stat = UNSUPPORTED; + try { + stat = getStatsService().getIfaceStats(iface, TYPE_TCP_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } if (stat != UNSUPPORTED) { total += stat; } @@ -527,46 +537,78 @@ public class TrafficStats { /** {@hide} */ public static long getTxPackets(String iface) { - return nativeGetIfaceStat(iface, TYPE_TX_PACKETS); + try { + return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ public static long getRxPackets(String iface) { - return nativeGetIfaceStat(iface, TYPE_RX_PACKETS); + try { + return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ public static long getTxBytes(String iface) { - return nativeGetIfaceStat(iface, TYPE_TX_BYTES); + try { + return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ public static long getRxBytes(String iface) { - return nativeGetIfaceStat(iface, TYPE_RX_BYTES); + try { + return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackTxPackets() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_PACKETS); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackRxPackets() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_PACKETS); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackTxBytes() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_TX_BYTES); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** {@hide} */ @TestApi public static long getLoopbackRxBytes() { - return nativeGetIfaceStat(LOOPBACK_IFACE, TYPE_RX_BYTES); + try { + return getStatsService().getIfaceStats(LOOPBACK_IFACE, TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -579,7 +621,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalTxPackets() { - return nativeGetTotalStat(TYPE_TX_PACKETS); + try { + return getStatsService().getTotalStats(TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -592,7 +638,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalRxPackets() { - return nativeGetTotalStat(TYPE_RX_PACKETS); + try { + return getStatsService().getTotalStats(TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -605,7 +655,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalTxBytes() { - return nativeGetTotalStat(TYPE_TX_BYTES); + try { + return getStatsService().getTotalStats(TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -618,7 +672,11 @@ public class TrafficStats { * return {@link #UNSUPPORTED} on devices where statistics aren't available. */ public static long getTotalRxBytes() { - return nativeGetTotalStat(TYPE_RX_BYTES); + try { + return getStatsService().getTotalStats(TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -644,7 +702,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_TX_BYTES); + try { + return getStatsService().getUidStats(uid, TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -673,7 +735,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_RX_BYTES); + try { + return getStatsService().getUidStats(uid, TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -702,7 +768,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_TX_PACKETS); + try { + return getStatsService().getUidStats(uid, TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -731,7 +801,11 @@ public class TrafficStats { // unsupported value. The real filtering is done at the kernel level. final int callingUid = android.os.Process.myUid(); if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - return nativeGetUidStat(uid, TYPE_RX_PACKETS); + try { + return getStatsService().getUidStats(uid, TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } else { return UNSUPPORTED; } @@ -859,8 +933,4 @@ public class TrafficStats { private static final int TYPE_TX_PACKETS = 3; private static final int TYPE_TCP_RX_PACKETS = 4; private static final int TYPE_TCP_TX_PACKETS = 5; - - private static native long nativeGetTotalStat(int type); - private static native long nativeGetIfaceStat(String iface, int type); - private static native long nativeGetUidStat(int uid, int type); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3af5265e6f..db61ef5cd9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -873,6 +873,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + @Override + public long getUidStats(int uid, int type) { + return nativeGetUidStat(uid, type); + } + + @Override + public long getIfaceStats(String iface, int type) { + return nativeGetIfaceStat(iface, type); + } + + @Override + public long getTotalStats(int type) { + return nativeGetTotalStat(type); + } + /** * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to * reflect current {@link #mPersistThreshold} value. Always defers to @@ -1626,4 +1641,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def); } } + + private static int TYPE_RX_BYTES; + private static int TYPE_RX_PACKETS; + private static int TYPE_TX_BYTES; + private static int TYPE_TX_PACKETS; + private static int TYPE_TCP_RX_PACKETS; + private static int TYPE_TCP_TX_PACKETS; + + private static native long nativeGetTotalStat(int type); + private static native long nativeGetIfaceStat(String iface, int type); + private static native long nativeGetUidStat(int uid, int type); } diff --git a/core/jni/android_net_TrafficStats.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp similarity index 80% rename from core/jni/android_net_TrafficStats.cpp rename to services/core/jni/com_android_server_net_NetworkStatsService.cpp index d0c237da07..8de24e5565 100644 --- a/core/jni/android_net_TrafficStats.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#define LOG_TAG "TrafficStats" +#define LOG_TAG "NetworkStatsNative" #include #include @@ -191,8 +191,24 @@ static const JNINativeMethod gMethods[] = { {"nativeGetUidStat", "(II)J", (void*) getUidStat}, }; -int register_android_net_TrafficStats(JNIEnv* env) { - return RegisterMethodsOrDie(env, "android/net/TrafficStats", gMethods, NELEM(gMethods)); +int register_android_server_net_NetworkStatsService(JNIEnv* env) { + jclass netStatsService = env->FindClass("com/android/server/net/NetworkStatsService"); + jfieldID rxBytesId = env->GetStaticFieldID(netStatsService, "TYPE_RX_BYTES", "I"); + jfieldID rxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_RX_PACKETS", "I"); + jfieldID txBytesId = env->GetStaticFieldID(netStatsService, "TYPE_TX_BYTES", "I"); + jfieldID txPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TX_PACKETS", "I"); + jfieldID tcpRxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_RX_PACKETS", "I"); + jfieldID tcpTxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_TX_PACKETS", "I"); + + env->SetStaticIntField(netStatsService, rxBytesId, RX_BYTES); + env->SetStaticIntField(netStatsService, rxPacketsId, RX_PACKETS); + env->SetStaticIntField(netStatsService, txBytesId, TX_BYTES); + env->SetStaticIntField(netStatsService, txPacketsId, TX_PACKETS); + env->SetStaticIntField(netStatsService, tcpRxPacketsId, TCP_RX_PACKETS); + env->SetStaticIntField(netStatsService, tcpTxPacketsId, TCP_TX_PACKETS); + + return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods, + NELEM(gMethods)); } } From 860d1ee24786f6eed7528cb96d3c391f677d8262 Mon Sep 17 00:00:00 2001 From: Tetsutoki Shiozawa Date: Fri, 27 Oct 2017 14:03:00 +0900 Subject: [PATCH 077/881] Definitely abort reconnecting to native daemon during shutdown Symptom: System_server crashed due to unsolved "netd" service. Root cause: My previous patch was not enough for avoiding this crash. a00d4b0 Abort connecting to native daemon during shutdown listenToSocket loop can be finished without throwing exception. Solution: It's better to test shutdown condition before reconnection even though listenToSocket is finished without exception. Bug: 68742327 Change-Id: Ifdfe43d52bef891f55bd7b07cc1aa0fa248a6030 --- .../com/android/server/NativeDaemonConnector.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java index b5a8332375..ad02aad6e4 100644 --- a/services/core/java/com/android/server/NativeDaemonConnector.java +++ b/services/core/java/com/android/server/NativeDaemonConnector.java @@ -134,21 +134,23 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo mCallbackHandler = new Handler(mLooper, this); while (true) { + if (isShuttingDown()) break; try { listenToSocket(); } catch (Exception e) { loge("Error in NativeDaemonConnector: " + e); - String shutdownAct = SystemProperties.get( - ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); - if (shutdownAct != null && shutdownAct.length() > 0) { - // The device is in middle of shutdown. - break; - } + if (isShuttingDown()) break; SystemClock.sleep(5000); } } } + private static boolean isShuttingDown() { + String shutdownAct = SystemProperties.get( + ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); + return shutdownAct != null && shutdownAct.length() > 0; + } + @Override public boolean handleMessage(Message msg) { final String event = (String) msg.obj; From 36410728d9184543ecaa4205a546a4c4a31e7ab5 Mon Sep 17 00:00:00 2001 From: manojboopathi Date: Thu, 30 Nov 2017 17:11:49 -0800 Subject: [PATCH 078/881] Fix CTS Test Dual Stack Test Passing Issue CTS test should fail if IPV6 Sockets is used on IPV4 address. Unfortunately its been passing fine due to unhandled catch exception. This is fixed in this CL. Bug: 64435904 Test: Ran CTS test to verify ./run_cts.sh Change-Id: I369c1b5baaa64b64feaa3f298e61f46d1200ea17 --- services/core/java/com/android/server/IpSecService.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index d3ab1259c9..989cb886c1 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -19,6 +19,7 @@ package com.android.server; import static android.Manifest.permission.DUMP; import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; @@ -1220,7 +1221,11 @@ public class IpSecService extends IIpSecService.Stub { info.getSpiRecord(direction).getSpi()); } } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception + if (e.errorCode == EINVAL) { + throw new IllegalArgumentException(e.toString()); + } else { + throw e; + } } } From 5149f29b41220be147c1df3aa90a955dc29cb5e4 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 13 Dec 2017 18:51:35 -0800 Subject: [PATCH 079/881] IpSec Invalidate the Resource IDs on close() To facilitate error checking we should invalidate the resource IDs of all objects when we close() them. Today, the resource ID is invalidated on the Transform object but not on the SPI or Encap Socket. This CL unifies the behavior. Bug: 70641274 Test: cts - IpSecManagerTest Change-Id: I28caec3e913902c748c6a50b4ef742ccef8b1b09 --- core/java/android/net/IpSecConfig.java | 6 ------ core/java/android/net/IpSecManager.java | 8 +++++--- core/java/android/net/IpSecTransform.java | 17 +++++++++++++++-- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index e6cd3fc130..f54ceb5c14 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -102,17 +102,11 @@ public final class IpSecConfig implements Parcelable { /** Set the local IP address for Tunnel mode */ public void setLocalAddress(String localAddress) { - if (localAddress == null) { - throw new IllegalArgumentException("localAddress may not be null!"); - } mLocalAddress = localAddress; } /** Set the remote IP address for this IPsec transform */ public void setRemoteAddress(String remoteAddress) { - if (remoteAddress == null) { - throw new IllegalArgumentException("remoteAddress may not be null!"); - } mRemoteAddress = remoteAddress; } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 6a4b891478..34cfa9b215 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -69,7 +69,7 @@ public final class IpSecManager { } /** @hide */ - public static final int INVALID_RESOURCE_ID = 0; + public static final int INVALID_RESOURCE_ID = -1; /** * Thrown to indicate that a requested SPI is in use. @@ -128,7 +128,7 @@ public final class IpSecManager { private final InetAddress mRemoteAddress; private final CloseGuard mCloseGuard = CloseGuard.get(); private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; - private int mResourceId; + private int mResourceId = INVALID_RESOURCE_ID; /** Get the underlying SPI held by this object. */ public int getSpi() { @@ -146,6 +146,7 @@ public final class IpSecManager { public void close() { try { mService.releaseSecurityParameterIndex(mResourceId); + mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -501,7 +502,7 @@ public final class IpSecManager { public static final class UdpEncapsulationSocket implements AutoCloseable { private final ParcelFileDescriptor mPfd; private final IIpSecService mService; - private final int mResourceId; + private int mResourceId = INVALID_RESOURCE_ID; private final int mPort; private final CloseGuard mCloseGuard = CloseGuard.get(); @@ -554,6 +555,7 @@ public final class IpSecManager { public void close() throws IOException { try { mService.closeUdpEncapsulationSocket(mResourceId); + mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 7cd742b417..102ba6d94f 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -347,6 +347,9 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform.Builder setSpi( @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) { + if (spi.getResourceId() == INVALID_RESOURCE_ID) { + throw new IllegalArgumentException("Invalid SecurityParameterIndex"); + } mConfig.setSpiResourceId(direction, spi.getResourceId()); return this; } @@ -381,6 +384,9 @@ public final class IpSecTransform implements AutoCloseable { public IpSecTransform.Builder setIpv4Encapsulation( IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { mConfig.setEncapType(ENCAP_ESPINUDP); + if (localSocket.getResourceId() == INVALID_RESOURCE_ID) { + throw new IllegalArgumentException("Invalid UdpEncapsulationSocket"); + } mConfig.setEncapSocketResourceId(localSocket.getResourceId()); mConfig.setEncapRemotePort(remotePort); return this; @@ -426,6 +432,9 @@ public final class IpSecTransform implements AutoCloseable { public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress) throws IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException, IOException { + if (remoteAddress == null) { + throw new IllegalArgumentException("Remote address may not be null or empty!"); + } mConfig.setMode(MODE_TRANSPORT); mConfig.setRemoteAddress(remoteAddress.getHostAddress()); // FIXME: modifying a builder after calling build can change the built transform. @@ -447,8 +456,12 @@ public final class IpSecTransform implements AutoCloseable { */ public IpSecTransform buildTunnelModeTransform( InetAddress localAddress, InetAddress remoteAddress) { - // FIXME: argument validation here - // throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation"); + if (localAddress == null) { + throw new IllegalArgumentException("Local address may not be null or empty!"); + } + if (remoteAddress == null) { + throw new IllegalArgumentException("Remote address may not be null or empty!"); + } mConfig.setLocalAddress(localAddress.getHostAddress()); mConfig.setRemoteAddress(remoteAddress.getHostAddress()); mConfig.setMode(MODE_TUNNEL); From eabfcac87fbdaf8d0ab4549278c36dbea48571f1 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 13 Dec 2017 19:16:33 -0800 Subject: [PATCH 080/881] IpSecService - Convert mNextResourceId from AtomicInt to Int The mNextResourceId variable is only accessed within synchronized blocks, so there is no need to use an atomic integer to synchronize it. This eliminates the misleading notion that the variable is accessed outside of guarded blocks, which it is not. Bug: 62279167 Test: cts Change-Id: I815835622659f54d2d2d33b349b17c632ebced8d --- .../java/com/android/server/IpSecService.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 989cb886c1..5c098e3204 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -102,8 +102,14 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; - /** Should be a never-repeating global ID for resources */ - private static AtomicInteger mNextResourceId = new AtomicInteger(0x00FADED0); + /** + * The next non-repeating global ID for tracking resources between users, this service, + * and kernel data structures. Accessing this variable is not thread safe, so it is + * only read or modified within blocks synchronized on IpSecService.this. We want to + * avoid -1 (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it). + */ + @GuardedBy("IpSecService.this") + private int mNextResourceId = 1; interface IpSecServiceConfiguration { INetd getNetdInstance() throws RemoteException; @@ -856,7 +862,7 @@ public class IpSecService extends IIpSecService.Stub { checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - int resourceId = mNextResourceId.getAndIncrement(); + final int resourceId = mNextResourceId++; int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; String localAddress = ""; @@ -979,7 +985,7 @@ public class IpSecService extends IIpSecService.Stub { int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); - int resourceId = mNextResourceId.getAndIncrement(); + final int resourceId = mNextResourceId++; FileDescriptor sockFd = null; try { if (!userRecord.mSocketQuotaTracker.isAvailable()) { @@ -1102,7 +1108,7 @@ public class IpSecService extends IIpSecService.Stub { IpSecConfig c, IBinder binder) throws RemoteException { checkIpSecConfig(c); checkNotNull(binder, "Null Binder passed to createTransportModeTransform"); - int resourceId = mNextResourceId.getAndIncrement(); + final int resourceId = mNextResourceId++; UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); From aac9965a8921e3f5837996e130283b3f8a19a2a0 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 6 Nov 2017 20:49:10 -0800 Subject: [PATCH 081/881] Add validation to IpSecConfig algorithm setters Adds checks to ensure that users can only set the correct types of algorithms for the Authentication, Encryption and Authenticated Encryption algorithms. Bug: 65223935 Test: Added tests in IpSecConfigTest, and passed on aosp_marlin-eng Change-Id: I462c77d9eb5710b8d03a48866453649d3b6fc6bf --- core/java/android/net/IpSecAlgorithm.java | 25 +++++++++++++ .../java/com/android/server/IpSecService.java | 37 +++++++++++++------ 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index f82627b942..7d752e89e6 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -231,6 +231,31 @@ public final class IpSecAlgorithm implements Parcelable { } } + /** @hide */ + public boolean isAuthentication() { + switch (getName()) { + // Fallthrough + case AUTH_HMAC_MD5: + case AUTH_HMAC_SHA1: + case AUTH_HMAC_SHA256: + case AUTH_HMAC_SHA384: + case AUTH_HMAC_SHA512: + return true; + default: + return false; + } + } + + /** @hide */ + public boolean isEncryption() { + return getName().equals(CRYPT_AES_CBC); + } + + /** @hide */ + public boolean isAead() { + return getName().equals(AUTH_CRYPT_AES_GCM); + } + @Override public String toString() { return new StringBuilder() diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index d3ab1259c9..232853898d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -51,6 +51,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.IOException; @@ -1023,6 +1024,30 @@ public class IpSecService extends IIpSecService.Stub { releaseResource(userRecord.mEncapSocketRecords, resourceId); } + @VisibleForTesting + void validateAlgorithms(IpSecConfig config, int direction) throws IllegalArgumentException { + IpSecAlgorithm auth = config.getAuthentication(direction); + IpSecAlgorithm crypt = config.getEncryption(direction); + IpSecAlgorithm aead = config.getAuthenticatedEncryption(direction); + + // Validate the algorithm set + Preconditions.checkArgument( + aead != null || crypt != null || auth != null, + "No Encryption or Authentication algorithms specified"); + Preconditions.checkArgument( + auth == null || auth.isAuthentication(), + "Unsupported algorithm for Authentication"); + Preconditions.checkArgument( + crypt == null || crypt.isEncryption(), "Unsupported algorithm for Encryption"); + Preconditions.checkArgument( + aead == null || aead.isAead(), + "Unsupported algorithm for Authenticated Encryption"); + Preconditions.checkArgument( + aead == null || (auth == null && crypt == null), + "Authenticated Encryption is mutually exclusive with other Authentication " + + "or Encryption algorithms"); + } + /** * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an * IllegalArgumentException if they are not. @@ -1072,17 +1097,7 @@ public class IpSecService extends IIpSecService.Stub { } for (int direction : DIRECTIONS) { - IpSecAlgorithm crypt = config.getEncryption(direction); - IpSecAlgorithm auth = config.getAuthentication(direction); - IpSecAlgorithm authenticatedEncryption = config.getAuthenticatedEncryption(direction); - if (authenticatedEncryption == null && crypt == null && auth == null) { - throw new IllegalArgumentException( - "No Encryption or Authentication algorithms specified"); - } else if (authenticatedEncryption != null && (auth != null || crypt != null)) { - throw new IllegalArgumentException( - "Authenticated Encryption is mutually" - + " exclusive with other Authentication or Encryption algorithms"); - } + validateAlgorithms(config, direction); // Retrieve SPI record; will throw IllegalArgumentException if not found userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId(direction)); From 69f6f06d2abe63e43e03135d29c5dfa533061ddf Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Sun, 7 Jan 2018 16:47:31 -0700 Subject: [PATCH 082/881] Add DataUnit to clarify SI-vs-IEC units. Mirrors the design of TimeUnit and ChronoUnit which many developers are already familiar with, making it easy to pick up and use. Yes, this is an enum. Bug: 70915728 Test: bit FrameworksCoreTests:android.util.DataUnitTest Change-Id: Id0cfdac5c81ed89c3c9ece23c964acba4a4f8471 --- core/java/android/net/TrafficStats.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 196a3bc9c8..bda720bb6f 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -27,6 +27,7 @@ import android.content.Context; import android.media.MediaPlayer; import android.os.RemoteException; import android.os.ServiceManager; +import android.util.DataUnit; import com.android.server.NetworkManagementSocketTagger; @@ -56,15 +57,20 @@ public class TrafficStats { */ public final static int UNSUPPORTED = -1; - /** @hide */ + /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + @Deprecated public static final long KB_IN_BYTES = 1024; - /** @hide */ + /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + @Deprecated public static final long MB_IN_BYTES = KB_IN_BYTES * 1024; - /** @hide */ + /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + @Deprecated public static final long GB_IN_BYTES = MB_IN_BYTES * 1024; - /** @hide */ + /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + @Deprecated public static final long TB_IN_BYTES = GB_IN_BYTES * 1024; - /** @hide */ + /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + @Deprecated public static final long PB_IN_BYTES = TB_IN_BYTES * 1024; /** From ce6d573795c11a6cd4cd822d8772a01fa5977099 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Fri, 5 Jan 2018 19:25:13 -0800 Subject: [PATCH 083/881] Make Transforms Unidirectional Convert the IpSecTransform from being a bi-directional pair of SAs to a unidirectional single SA. This CL also removes the concept of "direction from SAs meaning that a IpSecTransform may now be applied to a socket in either direction. -Make transforms unidirectional -Add Convert allocateSpi() to use destination rather than direction and remote address -Remove directionality from builders for IpSecTransform -Change applyTransportModeTransform() to take a direction in which to apply the transform object. -Additional minor naming updates -Restrict IpSecConfig to only print keys on eng builds -Move DIRECTION constants to IpSecManager -Add sourceAddress parameter to IpSecTransform to provide additional guarantees about the source address of data; (explicit failure rather than implicit failure). -Move SPI to the build() method of IpSecTransform Bug: 71717213 Test: runtest frameworks-net, CTS - IpSecManagerTest Change-Id: I0824b37f443f4b8c62536d9801238c63ed8f2a1c --- core/java/android/net/IIpSecService.aidl | 6 +- core/java/android/net/IpSecAlgorithm.java | 8 +- core/java/android/net/IpSecConfig.java | 183 ++++------ core/java/android/net/IpSecManager.java | 119 +++--- core/java/android/net/IpSecTransform.java | 155 +++----- .../java/com/android/server/IpSecService.java | 338 ++++++++---------- 6 files changed, 371 insertions(+), 438 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index d9b57db180..3fe531fd79 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -31,7 +31,7 @@ import android.os.ParcelFileDescriptor; interface IIpSecService { IpSecSpiResponse allocateSecurityParameterIndex( - int direction, in String remoteAddress, int requestedSpi, in IBinder binder); + in String destinationAddress, int requestedSpi, in IBinder binder); void releaseSecurityParameterIndex(int resourceId); @@ -43,7 +43,7 @@ interface IIpSecService void deleteTransportModeTransform(int transformId); - void applyTransportModeTransform(in ParcelFileDescriptor socket, int transformId); + void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); - void removeTransportModeTransform(in ParcelFileDescriptor socket, int transformId); + void removeTransportModeTransforms(in ParcelFileDescriptor socket, int transformId); } diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 7d752e89e6..c69a4d4c0b 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -256,13 +256,19 @@ public final class IpSecAlgorithm implements Parcelable { return getName().equals(AUTH_CRYPT_AES_GCM); } + // Because encryption keys are sensitive and userdebug builds are used by large user pools + // such as beta testers, we only allow sensitive info such as keys on eng builds. + private static boolean isUnsafeBuild() { + return Build.IS_DEBUGGABLE && Build.IS_ENG; + } + @Override public String toString() { return new StringBuilder() .append("{mName=") .append(mName) .append(", mKey=") - .append(Build.IS_DEBUGGABLE ? HexDump.toHexString(mKey) : "") + .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "") .append(", mTruncLenBits=") .append(mTruncLenBits) .append("}") diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index f54ceb5c14..80b0af3373 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -32,59 +32,29 @@ public final class IpSecConfig implements Parcelable { // MODE_TRANSPORT or MODE_TUNNEL private int mMode = IpSecTransform.MODE_TRANSPORT; - // Needs to be valid only for tunnel mode // Preventing this from being null simplifies Java->Native binder - private String mLocalAddress = ""; + private String mSourceAddress = ""; // Preventing this from being null simplifies Java->Native binder - private String mRemoteAddress = ""; + private String mDestinationAddress = ""; // The underlying Network that represents the "gateway" Network // for outbound packets. It may also be used to select packets. private Network mNetwork; - /** - * This class captures the parameters that specifically apply to inbound or outbound traffic. - */ - public static class Flow { - // Minimum requirements for identifying a transform - // SPI identifying the IPsec flow in packet processing - // and a remote IP address - private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID; + // Minimum requirements for identifying a transform + // SPI identifying the IPsec SA in packet processing + // and a destination IP address + private int mSpiResourceId = IpSecManager.INVALID_RESOURCE_ID; - // Encryption Algorithm - private IpSecAlgorithm mEncryption; + // Encryption Algorithm + private IpSecAlgorithm mEncryption; - // Authentication Algorithm - private IpSecAlgorithm mAuthentication; + // Authentication Algorithm + private IpSecAlgorithm mAuthentication; - // Authenticated Encryption Algorithm - private IpSecAlgorithm mAuthenticatedEncryption; - - @Override - public String toString() { - return new StringBuilder() - .append("{mSpiResourceId=") - .append(mSpiResourceId) - .append(", mEncryption=") - .append(mEncryption) - .append(", mAuthentication=") - .append(mAuthentication) - .append(", mAuthenticatedEncryption=") - .append(mAuthenticatedEncryption) - .append("}") - .toString(); - } - - static boolean equals(IpSecConfig.Flow lhs, IpSecConfig.Flow rhs) { - if (lhs == null || rhs == null) return (lhs == rhs); - return (lhs.mSpiResourceId == rhs.mSpiResourceId - && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) - && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)); - } - } - - private final Flow[] mFlow = new Flow[] {new Flow(), new Flow()}; + // Authenticated Encryption Algorithm + private IpSecAlgorithm mAuthenticatedEncryption; // For tunnel mode IPv4 UDP Encapsulation // IpSecTransform#ENCAP_ESP_*, such as ENCAP_ESP_OVER_UDP_IKE @@ -100,36 +70,37 @@ public final class IpSecConfig implements Parcelable { mMode = mode; } - /** Set the local IP address for Tunnel mode */ - public void setLocalAddress(String localAddress) { - mLocalAddress = localAddress; + /** Set the source IP addres for this IPsec transform */ + public void setSourceAddress(String sourceAddress) { + mSourceAddress = sourceAddress; } - /** Set the remote IP address for this IPsec transform */ - public void setRemoteAddress(String remoteAddress) { - mRemoteAddress = remoteAddress; + /** Set the destination IP address for this IPsec transform */ + public void setDestinationAddress(String destinationAddress) { + mDestinationAddress = destinationAddress; } - /** Set the SPI for a given direction by resource ID */ - public void setSpiResourceId(int direction, int resourceId) { - mFlow[direction].mSpiResourceId = resourceId; + /** Set the SPI by resource ID */ + public void setSpiResourceId(int resourceId) { + mSpiResourceId = resourceId; } - /** Set the encryption algorithm for a given direction */ - public void setEncryption(int direction, IpSecAlgorithm encryption) { - mFlow[direction].mEncryption = encryption; + /** Set the encryption algorithm */ + public void setEncryption(IpSecAlgorithm encryption) { + mEncryption = encryption; } - /** Set the authentication algorithm for a given direction */ - public void setAuthentication(int direction, IpSecAlgorithm authentication) { - mFlow[direction].mAuthentication = authentication; + /** Set the authentication algorithm */ + public void setAuthentication(IpSecAlgorithm authentication) { + mAuthentication = authentication; } - /** Set the authenticated encryption algorithm for a given direction */ - public void setAuthenticatedEncryption(int direction, IpSecAlgorithm authenticatedEncryption) { - mFlow[direction].mAuthenticatedEncryption = authenticatedEncryption; + /** Set the authenticated encryption algorithm */ + public void setAuthenticatedEncryption(IpSecAlgorithm authenticatedEncryption) { + mAuthenticatedEncryption = authenticatedEncryption; } + /** Set the underlying network that will carry traffic for this transform */ public void setNetwork(Network network) { mNetwork = network; } @@ -155,28 +126,28 @@ public final class IpSecConfig implements Parcelable { return mMode; } - public String getLocalAddress() { - return mLocalAddress; + public String getSourceAddress() { + return mSourceAddress; } - public int getSpiResourceId(int direction) { - return mFlow[direction].mSpiResourceId; + public int getSpiResourceId() { + return mSpiResourceId; } - public String getRemoteAddress() { - return mRemoteAddress; + public String getDestinationAddress() { + return mDestinationAddress; } - public IpSecAlgorithm getEncryption(int direction) { - return mFlow[direction].mEncryption; + public IpSecAlgorithm getEncryption() { + return mEncryption; } - public IpSecAlgorithm getAuthentication(int direction) { - return mFlow[direction].mAuthentication; + public IpSecAlgorithm getAuthentication() { + return mAuthentication; } - public IpSecAlgorithm getAuthenticatedEncryption(int direction) { - return mFlow[direction].mAuthenticatedEncryption; + public IpSecAlgorithm getAuthenticatedEncryption() { + return mAuthenticatedEncryption; } public Network getNetwork() { @@ -209,17 +180,13 @@ public final class IpSecConfig implements Parcelable { @Override public void writeToParcel(Parcel out, int flags) { out.writeInt(mMode); - out.writeString(mLocalAddress); - out.writeString(mRemoteAddress); + out.writeString(mSourceAddress); + out.writeString(mDestinationAddress); out.writeParcelable(mNetwork, flags); - out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption, flags); - out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags); - out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption, flags); + out.writeInt(mSpiResourceId); + out.writeParcelable(mEncryption, flags); + out.writeParcelable(mAuthentication, flags); + out.writeParcelable(mAuthenticatedEncryption, flags); out.writeInt(mEncapType); out.writeInt(mEncapSocketResourceId); out.writeInt(mEncapRemotePort); @@ -231,22 +198,15 @@ public final class IpSecConfig implements Parcelable { private IpSecConfig(Parcel in) { mMode = in.readInt(); - mLocalAddress = in.readString(); - mRemoteAddress = in.readString(); + mSourceAddress = in.readString(); + mDestinationAddress = in.readString(); mNetwork = (Network) in.readParcelable(Network.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId = in.readInt(); - mFlow[IpSecTransform.DIRECTION_IN].mEncryption = + mSpiResourceId = in.readInt(); + mEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_IN].mAuthentication = + mAuthentication = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption = - (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt(); - mFlow[IpSecTransform.DIRECTION_OUT].mEncryption = - (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication = - (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); - mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption = + mAuthenticatedEncryption = (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader()); mEncapType = in.readInt(); mEncapSocketResourceId = in.readInt(); @@ -260,10 +220,10 @@ public final class IpSecConfig implements Parcelable { strBuilder .append("{mMode=") .append(mMode == IpSecTransform.MODE_TUNNEL ? "TUNNEL" : "TRANSPORT") - .append(", mLocalAddress=") - .append(mLocalAddress) - .append(", mRemoteAddress=") - .append(mRemoteAddress) + .append(", mSourceAddress=") + .append(mSourceAddress) + .append(", mDestinationAddress=") + .append(mDestinationAddress) .append(", mNetwork=") .append(mNetwork) .append(", mEncapType=") @@ -274,10 +234,14 @@ public final class IpSecConfig implements Parcelable { .append(mEncapRemotePort) .append(", mNattKeepaliveInterval=") .append(mNattKeepaliveInterval) - .append(", mFlow[OUT]=") - .append(mFlow[IpSecTransform.DIRECTION_OUT]) - .append(", mFlow[IN]=") - .append(mFlow[IpSecTransform.DIRECTION_IN]) + .append("{mSpiResourceId=") + .append(mSpiResourceId) + .append(", mEncryption=") + .append(mEncryption) + .append(", mAuthentication=") + .append(mAuthentication) + .append(", mAuthenticatedEncryption=") + .append(mAuthenticatedEncryption) .append("}"); return strBuilder.toString(); @@ -299,17 +263,18 @@ public final class IpSecConfig implements Parcelable { public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) { if (lhs == null || rhs == null) return (lhs == rhs); return (lhs.mMode == rhs.mMode - && lhs.mLocalAddress.equals(rhs.mLocalAddress) - && lhs.mRemoteAddress.equals(rhs.mRemoteAddress) + && lhs.mSourceAddress.equals(rhs.mSourceAddress) + && lhs.mDestinationAddress.equals(rhs.mDestinationAddress) && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork)) || (lhs.mNetwork == rhs.mNetwork)) && lhs.mEncapType == rhs.mEncapType && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId && lhs.mEncapRemotePort == rhs.mEncapRemotePort && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval - && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_OUT], - rhs.mFlow[IpSecTransform.DIRECTION_OUT]) - && IpSecConfig.Flow.equals(lhs.mFlow[IpSecTransform.DIRECTION_IN], - rhs.mFlow[IpSecTransform.DIRECTION_IN])); + && lhs.mSpiResourceId == rhs.mSpiResourceId + && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) + && IpSecAlgorithm.equals( + lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) + && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)); } } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 34cfa9b215..67d4fcac97 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -17,6 +17,7 @@ package android.net; import static com.android.internal.util.Preconditions.checkNotNull; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemService; import android.annotation.TestApi; @@ -33,6 +34,8 @@ import dalvik.system.CloseGuard; import java.io.FileDescriptor; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; @@ -52,6 +55,23 @@ import java.net.Socket; public final class IpSecManager { private static final String TAG = "IpSecManager"; + /** + * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute + * applies to traffic towards the host. + */ + public static final int DIRECTION_IN = 0; + + /** + * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute + * applies to traffic from the host. + */ + public static final int DIRECTION_OUT = 1; + + /** @hide */ + @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) + @Retention(RetentionPolicy.SOURCE) + public @interface PolicyDirection {} + /** * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. * @@ -125,7 +145,7 @@ public final class IpSecManager { */ public static final class SecurityParameterIndex implements AutoCloseable { private final IIpSecService mService; - private final InetAddress mRemoteAddress; + private final InetAddress mDestinationAddress; private final CloseGuard mCloseGuard = CloseGuard.get(); private int mSpi = INVALID_SECURITY_PARAMETER_INDEX; private int mResourceId = INVALID_RESOURCE_ID; @@ -164,14 +184,14 @@ public final class IpSecManager { } private SecurityParameterIndex( - @NonNull IIpSecService service, int direction, InetAddress remoteAddress, int spi) + @NonNull IIpSecService service, InetAddress destinationAddress, int spi) throws ResourceUnavailableException, SpiUnavailableException { mService = service; - mRemoteAddress = remoteAddress; + mDestinationAddress = destinationAddress; try { IpSecSpiResponse result = mService.allocateSecurityParameterIndex( - direction, remoteAddress.getHostAddress(), spi, new Binder()); + destinationAddress.getHostAddress(), spi, new Binder()); if (result == null) { throw new NullPointerException("Received null response from IpSecService"); @@ -216,25 +236,23 @@ public final class IpSecManager { } /** - * Reserve a random SPI for traffic bound to or from the specified remote address. + * Reserve a random SPI for traffic bound to or from the specified destination address. * *

If successful, this SPI is guaranteed available until released by a call to {@link * SecurityParameterIndex#close()}. * - * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} - * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress + * @param destinationAddress the destination address for traffic bearing the requested SPI. + * For inbound traffic, the destination should be an address currently assigned on-device. * @return the reserved SecurityParameterIndex - * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated - * for this user - * @throws SpiUnavailableException indicating that a particular SPI cannot be reserved + * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * currently allocated for this user */ - public SecurityParameterIndex allocateSecurityParameterIndex( - int direction, InetAddress remoteAddress) throws ResourceUnavailableException { + public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress) + throws ResourceUnavailableException { try { return new SecurityParameterIndex( mService, - direction, - remoteAddress, + destinationAddress, IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); } catch (SpiUnavailableException unlikely) { throw new ResourceUnavailableException("No SPIs available"); @@ -242,26 +260,27 @@ public final class IpSecManager { } /** - * Reserve the requested SPI for traffic bound to or from the specified remote address. + * Reserve the requested SPI for traffic bound to or from the specified destination address. * *

If successful, this SPI is guaranteed available until released by a call to {@link * SecurityParameterIndex#close()}. * - * @param direction {@link IpSecTransform#DIRECTION_IN} or {@link IpSecTransform#DIRECTION_OUT} - * @param remoteAddress address of the remote. SPIs must be unique for each remoteAddress + * @param destinationAddress the destination address for traffic bearing the requested SPI. + * For inbound traffic, the destination should be an address currently assigned on-device. * @param requestedSpi the requested SPI, or '0' to allocate a random SPI * @return the reserved SecurityParameterIndex - * @throws ResourceUnavailableException indicating that too many SPIs are currently allocated - * for this user - * @throws SpiUnavailableException indicating that the requested SPI could not be reserved + * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * currently allocated for this user + * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be + * reserved */ public SecurityParameterIndex allocateSecurityParameterIndex( - int direction, InetAddress remoteAddress, int requestedSpi) + InetAddress destinationAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); } - return new SecurityParameterIndex(mService, direction, remoteAddress, requestedSpi); + return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); } /** @@ -269,14 +288,14 @@ public final class IpSecManager { * *

This applies transport mode encapsulation to the given socket. Once applied, I/O on the * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When - * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, * unprotected traffic can resume on that socket. * *

For security reasons, the destination address of any traffic on the socket must match the * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any * other IP address will result in an IOException. In addition, reads and writes on the socket * will throw IOException if the user deactivates the transform (by calling {@link - * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * *

Rekey Procedure

* @@ -287,14 +306,15 @@ public final class IpSecManager { * in-flight packets have been received. * * @param socket a stream socket + * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied - * @hide */ - public void applyTransportModeTransform(Socket socket, IpSecTransform transform) + public void applyTransportModeTransform( + Socket socket, int direction, IpSecTransform transform) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { - applyTransportModeTransform(pfd, transform); + applyTransportModeTransform(pfd, direction, transform); } } @@ -303,14 +323,14 @@ public final class IpSecManager { * *

This applies transport mode encapsulation to the given socket. Once applied, I/O on the * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When - * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, * unprotected traffic can resume on that socket. * *

For security reasons, the destination address of any traffic on the socket must match the * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any * other IP address will result in an IOException. In addition, reads and writes on the socket * will throw IOException if the user deactivates the transform (by calling {@link - * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * *

Rekey Procedure

* @@ -321,14 +341,14 @@ public final class IpSecManager { * in-flight packets have been received. * * @param socket a datagram socket + * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied - * @hide */ - public void applyTransportModeTransform(DatagramSocket socket, IpSecTransform transform) - throws IOException { + public void applyTransportModeTransform( + DatagramSocket socket, int direction, IpSecTransform transform) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { - applyTransportModeTransform(pfd, transform); + applyTransportModeTransform(pfd, direction, transform); } } @@ -337,14 +357,14 @@ public final class IpSecManager { * *

This applies transport mode encapsulation to the given socket. Once applied, I/O on the * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When - * the transform is removed from the socket by calling {@link #removeTransportModeTransform}, + * the transform is removed from the socket by calling {@link #removeTransportModeTransforms}, * unprotected traffic can resume on that socket. * *

For security reasons, the destination address of any traffic on the socket must match the * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any * other IP address will result in an IOException. In addition, reads and writes on the socket * will throw IOException if the user deactivates the transform (by calling {@link - * IpSecTransform#close()}) without calling {@link #removeTransportModeTransform}. + * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * *

Rekey Procedure

* @@ -355,24 +375,27 @@ public final class IpSecManager { * in-flight packets have been received. * * @param socket a socket file descriptor + * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform(FileDescriptor socket, IpSecTransform transform) + public void applyTransportModeTransform( + FileDescriptor socket, int direction, IpSecTransform transform) throws IOException { // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() // constructor takes control and closes the user's FD when we exit the method // This is behaviorally the same as the other versions, but the PFD constructor does not // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup(). try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { - applyTransportModeTransform(pfd, transform); + applyTransportModeTransform(pfd, direction, transform); } } /* Call down to activate a transform */ - private void applyTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { + private void applyTransportModeTransform( + ParcelFileDescriptor pfd, int direction, IpSecTransform transform) throws IOException { try { - mService.applyTransportModeTransform(pfd, transform.getResourceId()); + mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -407,12 +430,11 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket - * @hide */ - public void removeTransportModeTransform(Socket socket, IpSecTransform transform) + public void removeTransportModeTransforms(Socket socket, IpSecTransform transform) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { - removeTransportModeTransform(pfd, transform); + removeTransportModeTransforms(pfd, transform); } } @@ -430,12 +452,11 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket - * @hide */ - public void removeTransportModeTransform(DatagramSocket socket, IpSecTransform transform) + public void removeTransportModeTransforms(DatagramSocket socket, IpSecTransform transform) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { - removeTransportModeTransform(pfd, transform); + removeTransportModeTransforms(pfd, transform); } } @@ -454,17 +475,17 @@ public final class IpSecManager { * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransform(FileDescriptor socket, IpSecTransform transform) + public void removeTransportModeTransforms(FileDescriptor socket, IpSecTransform transform) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { - removeTransportModeTransform(pfd, transform); + removeTransportModeTransforms(pfd, transform); } } /* Call down to remove a transform */ - private void removeTransportModeTransform(ParcelFileDescriptor pfd, IpSecTransform transform) { + private void removeTransportModeTransforms(ParcelFileDescriptor pfd, IpSecTransform transform) { try { - mService.removeTransportModeTransform(pfd, transform.getResourceId()); + mService.removeTransportModeTransforms(pfd, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 102ba6d94f..7b9b483092 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -38,13 +38,11 @@ import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; /** - * This class represents an IPsec transform, which comprises security associations in one or both - * directions. + * This class represents a transform, which roughly corresponds to an IPsec Security Association. * *

Transforms are created using {@link IpSecTransform.Builder}. Each {@code IpSecTransform} - * object encapsulates the properties and state of an inbound and outbound IPsec security - * association. That includes, but is not limited to, algorithm choice, key material, and allocated - * system resources. + * object encapsulates the properties and state of an IPsec security association. That includes, + * but is not limited to, algorithm choice, key material, and allocated system resources. * * @see RFC 4301, Security Architecture for the * Internet Protocol @@ -52,23 +50,6 @@ import java.net.InetAddress; public final class IpSecTransform implements AutoCloseable { private static final String TAG = "IpSecTransform"; - /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic towards the host. - */ - public static final int DIRECTION_IN = 0; - - /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic from the host. - */ - public static final int DIRECTION_OUT = 1; - - /** @hide */ - @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) - @Retention(RetentionPolicy.SOURCE) - public @interface TransformDirection {} - /** @hide */ public static final int MODE_TRANSPORT = 0; @@ -170,7 +151,7 @@ public final class IpSecTransform implements AutoCloseable { * *

Deactivating a transform while it is still applied to a socket will result in errors on * that socket. Make sure to remove transforms by calling {@link - * IpSecManager#removeTransportModeTransform}. Note, removing an {@code IpSecTransform} from a + * IpSecManager#removeTransportModeTransforms}. Note, removing an {@code IpSecTransform} from a * socket will not deactivate it (because one transform may be applied to multiple sockets). * *

It is safe to call this method on a transform that has already been deactivated. @@ -272,85 +253,49 @@ public final class IpSecTransform implements AutoCloseable { private IpSecConfig mConfig; /** - * Set the encryption algorithm for the given direction. - * - *

If encryption is set for a direction without also providing an SPI for that direction, - * creation of an {@code IpSecTransform} will fail when attempting to build the transform. + * Set the encryption algorithm. * *

Encryption is mutually exclusive with authenticated encryption. * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. */ - public IpSecTransform.Builder setEncryption( - @TransformDirection int direction, IpSecAlgorithm algo) { + public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an encryption algorithm. - mConfig.setEncryption(direction, algo); + Preconditions.checkNotNull(algo); + mConfig.setEncryption(algo); return this; } /** - * Set the authentication (integrity) algorithm for the given direction. - * - *

If authentication is set for a direction without also providing an SPI for that - * direction, creation of an {@code IpSecTransform} will fail when attempting to build the - * transform. + * Set the authentication (integrity) algorithm. * *

Authentication is mutually exclusive with authenticated encryption. * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. */ - public IpSecTransform.Builder setAuthentication( - @TransformDirection int direction, IpSecAlgorithm algo) { + public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an authentication algorithm. - mConfig.setAuthentication(direction, algo); + Preconditions.checkNotNull(algo); + mConfig.setAuthentication(algo); return this; } /** - * Set the authenticated encryption algorithm for the given direction. + * Set the authenticated encryption algorithm. * - *

If an authenticated encryption algorithm is set for a given direction without also - * providing an SPI for that direction, creation of an {@code IpSecTransform} will fail when - * attempting to build the transform. - * - *

The Authenticated Encryption (AE) class of algorithms are also known as Authenticated - * Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as - * referred to in RFC 4301). + *

The Authenticated Encryption (AE) class of algorithms are also known as + * Authenticated Encryption with Associated Data (AEAD) algorithms, or Combined mode + * algorithms (as referred to in + * RFC 4301). * *

Authenticated encryption is mutually exclusive with encryption and authentication. * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to * be applied. */ - public IpSecTransform.Builder setAuthenticatedEncryption( - @TransformDirection int direction, IpSecAlgorithm algo) { - mConfig.setAuthenticatedEncryption(direction, algo); - return this; - } - - /** - * Set the SPI for the given direction. - * - *

Because IPsec operates at the IP layer, this 32-bit identifier uniquely identifies - * packets to a given destination address. To prevent SPI collisions, values should be - * reserved by calling {@link IpSecManager#allocateSecurityParameterIndex}. - * - *

If the SPI and algorithms are omitted for one direction, traffic in that direction - * will not be encrypted or authenticated. - * - * @param direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} - * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed - * traffic - */ - public IpSecTransform.Builder setSpi( - @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) { - if (spi.getResourceId() == INVALID_RESOURCE_ID) { - throw new IllegalArgumentException("Invalid SecurityParameterIndex"); - } - mConfig.setSpiResourceId(direction, spi.getResourceId()); + public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) { + Preconditions.checkNotNull(algo); + mConfig.setAuthenticatedEncryption(algo); return this; } @@ -363,7 +308,8 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi - public IpSecTransform.Builder setUnderlyingNetwork(Network net) { + public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) { + Preconditions.checkNotNull(net); mConfig.setNetwork(net); return this; } @@ -382,7 +328,8 @@ public final class IpSecTransform implements AutoCloseable { * encapsulated traffic. In the case of IKEv2, this should be port 4500. */ public IpSecTransform.Builder setIpv4Encapsulation( - IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { + @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { + Preconditions.checkNotNull(localSocket); mConfig.setEncapType(ENCAP_ESPINUDP); if (localSocket.getResourceId() == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Invalid UdpEncapsulationSocket"); @@ -419,24 +366,33 @@ public final class IpSecTransform implements AutoCloseable { * will not affect any network traffic until it has been applied to one or more sockets. * * @see IpSecManager#applyTransportModeTransform - * @param remoteAddress the remote {@code InetAddress} of traffic on sockets that will use - * this transform + * @param sourceAddress the source {@code InetAddress} of traffic on sockets that will use + * this transform; this address must belong to the Network used by all sockets that + * utilize this transform; if provided, then only traffic originating from the + * specified source address will be processed. + * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed + * traffic * @throws IllegalArgumentException indicating that a particular combination of transform * properties is invalid - * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms are - * active + * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms + * are active * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI * collides with an existing transform * @throws IOException indicating other errors */ - public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress) + public IpSecTransform buildTransportModeTransform( + @NonNull InetAddress sourceAddress, + @NonNull IpSecManager.SecurityParameterIndex spi) throws IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException, IOException { - if (remoteAddress == null) { - throw new IllegalArgumentException("Remote address may not be null or empty!"); + Preconditions.checkNotNull(sourceAddress); + Preconditions.checkNotNull(spi); + if (spi.getResourceId() == INVALID_RESOURCE_ID) { + throw new IllegalArgumentException("Invalid SecurityParameterIndex"); } mConfig.setMode(MODE_TRANSPORT); - mConfig.setRemoteAddress(remoteAddress.getHostAddress()); + mConfig.setSourceAddress(sourceAddress.getHostAddress()); + mConfig.setSpiResourceId(spi.getResourceId()); // FIXME: modifying a builder after calling build can change the built transform. return new IpSecTransform(mContext, mConfig).activate(); } @@ -445,26 +401,33 @@ public final class IpSecTransform implements AutoCloseable { * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some * parameters have interdependencies that are checked at build time. * - * @param localAddress the {@link InetAddress} that provides the local endpoint for this + * @param sourceAddress the {@link InetAddress} that provides the source address for this * IPsec tunnel. This is almost certainly an address belonging to the {@link Network} * that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}. - * @param remoteAddress the {@link InetAddress} representing the remote endpoint of this - * IPsec tunnel. + * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed + * traffic * @throws IllegalArgumentException indicating that a particular combination of transform * properties is invalid. + * @throws IpSecManager.ResourceUnavailableException indicating that too many transforms + * are active + * @throws IpSecManager.SpiUnavailableException indicating the rare case where an SPI + * collides with an existing transform + * @throws IOException indicating other errors * @hide */ public IpSecTransform buildTunnelModeTransform( - InetAddress localAddress, InetAddress remoteAddress) { - if (localAddress == null) { - throw new IllegalArgumentException("Local address may not be null or empty!"); + @NonNull InetAddress sourceAddress, + @NonNull IpSecManager.SecurityParameterIndex spi) + throws IpSecManager.ResourceUnavailableException, + IpSecManager.SpiUnavailableException, IOException { + Preconditions.checkNotNull(sourceAddress); + Preconditions.checkNotNull(spi); + if (spi.getResourceId() == INVALID_RESOURCE_ID) { + throw new IllegalArgumentException("Invalid SecurityParameterIndex"); } - if (remoteAddress == null) { - throw new IllegalArgumentException("Remote address may not be null or empty!"); - } - mConfig.setLocalAddress(localAddress.getHostAddress()); - mConfig.setRemoteAddress(remoteAddress.getHostAddress()); mConfig.setMode(MODE_TUNNEL); + mConfig.setSourceAddress(sourceAddress.getHostAddress()); + mConfig.setSpiResourceId(spi.getResourceId()); return new IpSecTransform(mContext, mConfig); } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 02cfe3dc75..9d228c3d0a 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -25,6 +25,7 @@ import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; import android.content.Context; +import android.net.ConnectivityManager; import android.net.IIpSecService; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -62,7 +63,6 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; import libcore.io.IoUtils; @@ -83,7 +83,7 @@ public class IpSecService extends IIpSecService.Stub { private static final String NETD_SERVICE_NAME = "netd"; private static final int[] DIRECTIONS = - new int[] {IpSecTransform.DIRECTION_OUT, IpSecTransform.DIRECTION_IN}; + new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN}; private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms private static final int MAX_PORT_BIND_ATTEMPTS = 10; @@ -104,10 +104,10 @@ public class IpSecService extends IIpSecService.Stub { private final Context mContext; /** - * The next non-repeating global ID for tracking resources between users, this service, - * and kernel data structures. Accessing this variable is not thread safe, so it is - * only read or modified within blocks synchronized on IpSecService.this. We want to - * avoid -1 (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it). + * The next non-repeating global ID for tracking resources between users, this service, and + * kernel data structures. Accessing this variable is not thread safe, so it is only read or + * modified within blocks synchronized on IpSecService.this. We want to avoid -1 + * (INVALID_RESOURCE_ID) and 0 (we probably forgot to initialize it). */ @GuardedBy("IpSecService.this") private int mNextResourceId = 1; @@ -536,14 +536,14 @@ public class IpSecService extends IIpSecService.Stub { private final class TransformRecord extends KernelResourceRecord { private final IpSecConfig mConfig; - private final SpiRecord[] mSpis; + private final SpiRecord mSpi; private final EncapSocketRecord mSocket; TransformRecord( - int resourceId, IpSecConfig config, SpiRecord[] spis, EncapSocketRecord socket) { + int resourceId, IpSecConfig config, SpiRecord spi, EncapSocketRecord socket) { super(resourceId); mConfig = config; - mSpis = spis; + mSpi = spi; mSocket = socket; } @@ -551,29 +551,26 @@ public class IpSecService extends IIpSecService.Stub { return mConfig; } - public SpiRecord getSpiRecord(int direction) { - return mSpis[direction]; + public SpiRecord getSpiRecord() { + return mSpi; } /** always guarded by IpSecService#this */ @Override public void freeUnderlyingResources() { - for (int direction : DIRECTIONS) { - int spi = mSpis[direction].getSpi(); - try { - mSrvConfig - .getNetdInstance() - .ipSecDeleteSecurityAssociation( - mResourceId, - direction, - mConfig.getLocalAddress(), - mConfig.getRemoteAddress(), - spi); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { - Log.e(TAG, "Failed to delete SA with ID: " + mResourceId); - } + int spi = mSpi.getSpi(); + try { + mSrvConfig + .getNetdInstance() + .ipSecDeleteSecurityAssociation( + mResourceId, + mConfig.getSourceAddress(), + mConfig.getDestinationAddress(), + spi); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (RemoteException e) { + Log.e(TAG, "Failed to delete SA with ID: " + mResourceId); } getResourceTracker().give(); @@ -597,10 +594,8 @@ public class IpSecService extends IIpSecService.Stub { .append(super.toString()) .append(", mSocket=") .append(mSocket) - .append(", mSpis[OUT].mResourceId=") - .append(mSpis[IpSecTransform.DIRECTION_OUT].mResourceId) - .append(", mSpis[IN].mResourceId=") - .append(mSpis[IpSecTransform.DIRECTION_IN].mResourceId) + .append(", mSpi.mResourceId=") + .append(mSpi.mResourceId) .append(", mConfig=") .append(mConfig) .append("}"); @@ -609,23 +604,16 @@ public class IpSecService extends IIpSecService.Stub { } private final class SpiRecord extends KernelResourceRecord { - private final int mDirection; - private final String mLocalAddress; - private final String mRemoteAddress; + private final String mSourceAddress; + private final String mDestinationAddress; private int mSpi; private boolean mOwnedByTransform = false; - SpiRecord( - int resourceId, - int direction, - String localAddress, - String remoteAddress, - int spi) { + SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) { super(resourceId); - mDirection = direction; - mLocalAddress = localAddress; - mRemoteAddress = remoteAddress; + mSourceAddress = sourceAddress; + mDestinationAddress = destinationAddress; mSpi = spi; } @@ -646,7 +634,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - mResourceId, mDirection, mLocalAddress, mRemoteAddress, mSpi); + mResourceId, mSourceAddress, mDestinationAddress, mSpi); } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception } catch (RemoteException e) { @@ -662,6 +650,10 @@ public class IpSecService extends IIpSecService.Stub { return mSpi; } + public String getDestinationAddress() { + return mDestinationAddress; + } + public void setOwnedByTransform() { if (mOwnedByTransform) { // Programming error @@ -689,12 +681,10 @@ public class IpSecService extends IIpSecService.Stub { .append(super.toString()) .append(", mSpi=") .append(mSpi) - .append(", mDirection=") - .append(mDirection) - .append(", mLocalAddress=") - .append(mLocalAddress) - .append(", mRemoteAddress=") - .append(mRemoteAddress) + .append(", mSourceAddress=") + .append(mSourceAddress) + .append(", mDestinationAddress=") + .append(mDestinationAddress) .append(", mOwnedByTransform=") .append(mOwnedByTransform) .append("}"); @@ -772,14 +762,17 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting public IpSecService(Context context, IpSecServiceConfiguration config) { - this(context, config, (fd, uid) -> { - try{ - TrafficStats.setThreadStatsUid(uid); - TrafficStats.tagFileDescriptor(fd); - } finally { - TrafficStats.clearThreadStatsUid(); - } - }); + this( + context, + config, + (fd, uid) -> { + try { + TrafficStats.setThreadStatsUid(uid); + TrafficStats.tagFileDescriptor(fd); + } finally { + TrafficStats.clearThreadStatsUid(); + } + }); } /** @hide */ @@ -845,8 +838,8 @@ public class IpSecService extends IIpSecService.Stub { */ private static void checkDirection(int direction) { switch (direction) { - case IpSecTransform.DIRECTION_OUT: - case IpSecTransform.DIRECTION_IN: + case IpSecManager.DIRECTION_OUT: + case IpSecManager.DIRECTION_IN: return; } throw new IllegalArgumentException("Invalid Direction: " + direction); @@ -855,10 +848,8 @@ public class IpSecService extends IIpSecService.Stub { /** Get a new SPI and maintain the reservation in the system server */ @Override public synchronized IpSecSpiResponse allocateSecurityParameterIndex( - int direction, String remoteAddress, int requestedSpi, IBinder binder) - throws RemoteException { - checkDirection(direction); - checkInetAddress(remoteAddress); + String destinationAddress, int requestedSpi, IBinder binder) throws RemoteException { + checkInetAddress(destinationAddress); /* requestedSpi can be anything in the int range, so no check is needed. */ checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); @@ -866,28 +857,21 @@ public class IpSecService extends IIpSecService.Stub { final int resourceId = mNextResourceId++; int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; - String localAddress = ""; - try { if (!userRecord.mSpiQuotaTracker.isAvailable()) { return new IpSecSpiResponse( IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi); } + spi = mSrvConfig .getNetdInstance() - .ipSecAllocateSpi( - resourceId, - direction, - localAddress, - remoteAddress, - requestedSpi); + .ipSecAllocateSpi(resourceId, "", destinationAddress, requestedSpi); Log.d(TAG, "Allocated SPI " + spi); userRecord.mSpiRecords.put( resourceId, new RefcountedResource( - new SpiRecord(resourceId, direction, localAddress, remoteAddress, spi), - binder)); + new SpiRecord(resourceId, "", destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { // TODO: Add appropriate checks when other ServiceSpecificException types are supported return new IpSecSpiResponse( @@ -1032,27 +1016,27 @@ public class IpSecService extends IIpSecService.Stub { } @VisibleForTesting - void validateAlgorithms(IpSecConfig config, int direction) throws IllegalArgumentException { - IpSecAlgorithm auth = config.getAuthentication(direction); - IpSecAlgorithm crypt = config.getEncryption(direction); - IpSecAlgorithm aead = config.getAuthenticatedEncryption(direction); + void validateAlgorithms(IpSecConfig config) throws IllegalArgumentException { + IpSecAlgorithm auth = config.getAuthentication(); + IpSecAlgorithm crypt = config.getEncryption(); + IpSecAlgorithm aead = config.getAuthenticatedEncryption(); - // Validate the algorithm set - Preconditions.checkArgument( - aead != null || crypt != null || auth != null, - "No Encryption or Authentication algorithms specified"); - Preconditions.checkArgument( - auth == null || auth.isAuthentication(), - "Unsupported algorithm for Authentication"); - Preconditions.checkArgument( + // Validate the algorithm set + Preconditions.checkArgument( + aead != null || crypt != null || auth != null, + "No Encryption or Authentication algorithms specified"); + Preconditions.checkArgument( + auth == null || auth.isAuthentication(), + "Unsupported algorithm for Authentication"); + Preconditions.checkArgument( crypt == null || crypt.isEncryption(), "Unsupported algorithm for Encryption"); - Preconditions.checkArgument( - aead == null || aead.isAead(), - "Unsupported algorithm for Authenticated Encryption"); - Preconditions.checkArgument( - aead == null || (auth == null && crypt == null), - "Authenticated Encryption is mutually exclusive with other Authentication " - + "or Encryption algorithms"); + Preconditions.checkArgument( + aead == null || aead.isAead(), + "Unsupported algorithm for Authenticated Encryption"); + Preconditions.checkArgument( + aead == null || (auth == null && crypt == null), + "Authenticated Encryption is mutually exclusive with other Authentication " + + "or Encryption algorithms"); } /** @@ -1062,29 +1046,6 @@ public class IpSecService extends IIpSecService.Stub { private void checkIpSecConfig(IpSecConfig config) { UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - if (config.getLocalAddress() == null) { - throw new IllegalArgumentException("Invalid null Local InetAddress"); - } - - if (config.getRemoteAddress() == null) { - throw new IllegalArgumentException("Invalid null Remote InetAddress"); - } - - switch (config.getMode()) { - case IpSecTransform.MODE_TRANSPORT: - if (!config.getLocalAddress().isEmpty()) { - throw new IllegalArgumentException("Non-empty Local Address"); - } - // Must be valid, and not a wildcard - checkInetAddress(config.getRemoteAddress()); - break; - case IpSecTransform.MODE_TUNNEL: - break; - default: - throw new IllegalArgumentException( - "Invalid IpSecTransform.mode: " + config.getMode()); - } - switch (config.getEncapType()) { case IpSecTransform.ENCAP_NONE: break; @@ -1103,11 +1064,36 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Invalid Encap Type: " + config.getEncapType()); } - for (int direction : DIRECTIONS) { - validateAlgorithms(config, direction); + validateAlgorithms(config); - // Retrieve SPI record; will throw IllegalArgumentException if not found - userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId(direction)); + // Retrieve SPI record; will throw IllegalArgumentException if not found + SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId()); + + // If no remote address is supplied, then use one from the SPI. + if (TextUtils.isEmpty(config.getDestinationAddress())) { + config.setDestinationAddress(s.getDestinationAddress()); + } + + // All remote addresses must match + if (!config.getDestinationAddress().equals(s.getDestinationAddress())) { + throw new IllegalArgumentException("Mismatched remote addresseses."); + } + + // This check is technically redundant due to the chain of custody between the SPI and + // the IpSecConfig, but in the future if the dest is allowed to be set explicitly in + // the transform, this will prevent us from messing up. + checkInetAddress(config.getDestinationAddress()); + + // Require a valid source address for all transforms. + checkInetAddress(config.getSourceAddress()); + + switch (config.getMode()) { + case IpSecTransform.MODE_TRANSPORT: + case IpSecTransform.MODE_TUNNEL: + break; + default: + throw new IllegalArgumentException( + "Invalid IpSecTransform.mode: " + config.getMode()); } } @@ -1127,13 +1113,12 @@ public class IpSecService extends IIpSecService.Stub { UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - // Avoid resizing by creating a dependency array of min-size 3 (1 UDP encap + 2 SPIs) - List dependencies = new ArrayList<>(3); + // Avoid resizing by creating a dependency array of min-size 2 (1 UDP encap + 1 SPI) + List dependencies = new ArrayList<>(2); if (!userRecord.mTransformQuotaTracker.isAvailable()) { return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } - SpiRecord[] spis = new SpiRecord[DIRECTIONS.length]; int encapType, encapLocalPort = 0, encapRemotePort = 0; EncapSocketRecord socketRecord = null; @@ -1149,51 +1134,46 @@ public class IpSecService extends IIpSecService.Stub { encapRemotePort = c.getEncapRemotePort(); } - for (int direction : DIRECTIONS) { - IpSecAlgorithm auth = c.getAuthentication(direction); - IpSecAlgorithm crypt = c.getEncryption(direction); - IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(direction); + IpSecAlgorithm auth = c.getAuthentication(); + IpSecAlgorithm crypt = c.getEncryption(); + IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(); - RefcountedResource refcountedSpiRecord = - userRecord.mSpiRecords.getRefcountedResourceOrThrow( - c.getSpiResourceId(direction)); - dependencies.add(refcountedSpiRecord); + RefcountedResource refcountedSpiRecord = + userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId()); + dependencies.add(refcountedSpiRecord); + SpiRecord spiRecord = refcountedSpiRecord.getResource(); - spis[direction] = refcountedSpiRecord.getResource(); - int spi = spis[direction].getSpi(); - try { - mSrvConfig - .getNetdInstance() - .ipSecAddSecurityAssociation( - resourceId, - c.getMode(), - direction, - c.getLocalAddress(), - c.getRemoteAddress(), - (c.getNetwork() != null) ? c.getNetwork().getNetworkHandle() : 0, - spi, - (auth != null) ? auth.getName() : "", - (auth != null) ? auth.getKey() : new byte[] {}, - (auth != null) ? auth.getTruncationLengthBits() : 0, - (crypt != null) ? crypt.getName() : "", - (crypt != null) ? crypt.getKey() : new byte[] {}, - (crypt != null) ? crypt.getTruncationLengthBits() : 0, - (authCrypt != null) ? authCrypt.getName() : "", - (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, - (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, - encapType, - encapLocalPort, - encapRemotePort); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); - } + try { + mSrvConfig + .getNetdInstance() + .ipSecAddSecurityAssociation( + resourceId, + c.getMode(), + c.getSourceAddress(), + c.getDestinationAddress(), + (c.getNetwork() != null) ? c.getNetwork().netId : 0, + spiRecord.getSpi(), + (auth != null) ? auth.getName() : "", + (auth != null) ? auth.getKey() : new byte[] {}, + (auth != null) ? auth.getTruncationLengthBits() : 0, + (crypt != null) ? crypt.getName() : "", + (crypt != null) ? crypt.getKey() : new byte[] {}, + (crypt != null) ? crypt.getTruncationLengthBits() : 0, + (authCrypt != null) ? authCrypt.getName() : "", + (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, + (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, + encapType, + encapLocalPort, + encapRemotePort); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } // Both SAs were created successfully, time to construct a record and lock it away userRecord.mTransformRecords.put( resourceId, new RefcountedResource( - new TransformRecord(resourceId, c, spis, socketRecord), + new TransformRecord(resourceId, c, spiRecord, socketRecord), binder, dependencies.toArray(new RefcountedResource[dependencies.size()]))); return new IpSecTransformResponse(IpSecManager.Status.OK, resourceId); @@ -1217,9 +1197,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void applyTransportModeTransform( - ParcelFileDescriptor socket, int resourceId) throws RemoteException { + ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException { UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - + checkDirection(direction); // Get transform record; if no transform is found, will throw IllegalArgumentException TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId); @@ -1230,17 +1210,15 @@ public class IpSecService extends IIpSecService.Stub { IpSecConfig c = info.getConfig(); try { - for (int direction : DIRECTIONS) { - mSrvConfig - .getNetdInstance() - .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), - resourceId, - direction, - c.getLocalAddress(), - c.getRemoteAddress(), - info.getSpiRecord(direction).getSpi()); - } + mSrvConfig + .getNetdInstance() + .ipSecApplyTransportModeTransform( + socket.getFileDescriptor(), + resourceId, + direction, + c.getSourceAddress(), + c.getDestinationAddress(), + info.getSpiRecord().getSpi()); } catch (ServiceSpecificException e) { if (e.errorCode == EINVAL) { throw new IllegalArgumentException(e.toString()); @@ -1251,14 +1229,14 @@ public class IpSecService extends IIpSecService.Stub { } /** - * Remove a transport mode transform from a socket, applying the default (empty) policy. This - * will ensure that NO IPsec policy is applied to the socket (would be the equivalent of - * applying a policy that performs no IPsec). Today the resourceId parameter is passed but not - * used: reserved for future improved input validation. + * Remove transport mode transforms from a socket, applying the default (empty) policy. This + * ensures that NO IPsec policy is applied to the socket (would be the equivalent of applying a + * policy that performs no IPsec). Today the resourceId parameter is passed but not used: + * reserved for future improved input validation. */ @Override - public synchronized void removeTransportModeTransform(ParcelFileDescriptor socket, int resourceId) - throws RemoteException { + public synchronized void removeTransportModeTransforms( + ParcelFileDescriptor socket, int resourceId) throws RemoteException { try { mSrvConfig .getNetdInstance() From 16e0b07615454e9203feffb8cc89851471fad5a6 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 16 Jan 2018 12:08:43 -0800 Subject: [PATCH 084/881] Prevent Closure of Underlying Socket FDs The version of applyTransportModeTransform() and removeTransportModeTransform() that accepted Socket and DatagramSocket were closing the underlying FDs upon return. It's unclear whether this is due to a behavior change elsewhere in ParcelFileDescriptor, but either way, converting to using getFileDescriptor$ and then calling dup() explicitly rather than relying on ParcelFileDescriptor seems like a better idea anyway. Bug: 72047396 Test: CTS - IpSecManagerTest.testCreateTransform() Change-Id: Ia2f02564e1289f25bf113dbb861fcfd2240537a7 --- core/java/android/net/IpSecManager.java | 35 ++++--------------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 67d4fcac97..2202df3baf 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -313,9 +313,7 @@ public final class IpSecManager { public void applyTransportModeTransform( Socket socket, int direction, IpSecTransform transform) throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { - applyTransportModeTransform(pfd, direction, transform); - } + applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } /** @@ -347,9 +345,7 @@ public final class IpSecManager { */ public void applyTransportModeTransform( DatagramSocket socket, int direction, IpSecTransform transform) throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { - applyTransportModeTransform(pfd, direction, transform); - } + applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } /** @@ -383,18 +379,8 @@ public final class IpSecManager { FileDescriptor socket, int direction, IpSecTransform transform) throws IOException { // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() - // constructor takes control and closes the user's FD when we exit the method - // This is behaviorally the same as the other versions, but the PFD constructor does not - // dup() automatically, whereas PFD.fromSocket() and PDF.fromDatagramSocket() do dup(). + // constructor takes control and closes the user's FD when we exit the method. try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { - applyTransportModeTransform(pfd, direction, transform); - } - } - - /* Call down to activate a transform */ - private void applyTransportModeTransform( - ParcelFileDescriptor pfd, int direction, IpSecTransform transform) throws IOException { - try { mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -433,9 +419,7 @@ public final class IpSecManager { */ public void removeTransportModeTransforms(Socket socket, IpSecTransform transform) throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket)) { - removeTransportModeTransforms(pfd, transform); - } + removeTransportModeTransforms(socket.getFileDescriptor$(), transform); } /** @@ -455,9 +439,7 @@ public final class IpSecManager { */ public void removeTransportModeTransforms(DatagramSocket socket, IpSecTransform transform) throws IOException { - try (ParcelFileDescriptor pfd = ParcelFileDescriptor.fromDatagramSocket(socket)) { - removeTransportModeTransforms(pfd, transform); - } + removeTransportModeTransforms(socket.getFileDescriptor$(), transform); } /** @@ -478,13 +460,6 @@ public final class IpSecManager { public void removeTransportModeTransforms(FileDescriptor socket, IpSecTransform transform) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { - removeTransportModeTransforms(pfd, transform); - } - } - - /* Call down to remove a transform */ - private void removeTransportModeTransforms(ParcelFileDescriptor pfd, IpSecTransform transform) { - try { mService.removeTransportModeTransforms(pfd, transform.getResourceId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); From 24f3bb8c6d120444b49cf50bb9790ffb5ddb961f Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 17 Jan 2018 01:00:20 -0800 Subject: [PATCH 085/881] IpSec - API Tweak for removeTransportModeTransform Because IpSecTransforms are now unidirectional, and because the only mechanism for removing Transforms removes it from both directions, the API can no longer use the Transform parameter to meaningfully validate that the caller had applied a transform. Since that functionality was as-yet unimplemented and is now infeasible, the transform parameter is removed. Bug: 72079356 Test: cts - IpSecManagerTest; runtest frameworks-net Change-Id: If19b0d34bdc6daf31a40d6d62bff326dcbca08c0 --- core/java/android/net/IIpSecService.aidl | 2 +- core/java/android/net/IpSecManager.java | 30 ++++++++----------- .../java/com/android/server/IpSecService.java | 4 +-- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 3fe531fd79..790c80b1d9 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -45,5 +45,5 @@ interface IIpSecService void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); - void removeTransportModeTransforms(in ParcelFileDescriptor socket, int transformId); + void removeTransportModeTransforms(in ParcelFileDescriptor socket); } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 2202df3baf..2cda58c99a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -405,62 +405,56 @@ public final class IpSecManager { /** * Remove an IPsec transform from a stream socket. * - *

Once removed, traffic on the socket will not be encrypted. This operation will succeed - * regardless of the state of the transform. Removing a transform from a socket allows the - * socket to be reused for communication in the clear. + *

Once removed, traffic on the socket will not be encrypted. Removing transforms from a + * socket allows the socket to be reused for communication in the clear. * *

If an {@code IpSecTransform} object applied to this socket was deallocated by calling * {@link IpSecTransform#close()}, then communication on the socket will fail until this method * is called. * * @param socket a socket that previously had a transform applied to it - * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(Socket socket, IpSecTransform transform) + public void removeTransportModeTransforms(Socket socket) throws IOException { - removeTransportModeTransforms(socket.getFileDescriptor$(), transform); + removeTransportModeTransforms(socket.getFileDescriptor$()); } /** * Remove an IPsec transform from a datagram socket. * - *

Once removed, traffic on the socket will not be encrypted. This operation will succeed - * regardless of the state of the transform. Removing a transform from a socket allows the - * socket to be reused for communication in the clear. + *

Once removed, traffic on the socket will not be encrypted. Removing transforms from a + * socket allows the socket to be reused for communication in the clear. * *

If an {@code IpSecTransform} object applied to this socket was deallocated by calling * {@link IpSecTransform#close()}, then communication on the socket will fail until this method * is called. * * @param socket a socket that previously had a transform applied to it - * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(DatagramSocket socket, IpSecTransform transform) + public void removeTransportModeTransforms(DatagramSocket socket) throws IOException { - removeTransportModeTransforms(socket.getFileDescriptor$(), transform); + removeTransportModeTransforms(socket.getFileDescriptor$()); } /** * Remove an IPsec transform from a socket. * - *

Once removed, traffic on the socket will not be encrypted. This operation will succeed - * regardless of the state of the transform. Removing a transform from a socket allows the - * socket to be reused for communication in the clear. + *

Once removed, traffic on the socket will not be encrypted. Removing transforms from a + * socket allows the socket to be reused for communication in the clear. * *

If an {@code IpSecTransform} object applied to this socket was deallocated by calling * {@link IpSecTransform#close()}, then communication on the socket will fail until this method * is called. * * @param socket a socket that previously had a transform applied to it - * @param transform the IPsec Transform that was previously applied to the given socket * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(FileDescriptor socket, IpSecTransform transform) + public void removeTransportModeTransforms(FileDescriptor socket) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { - mService.removeTransportModeTransforms(pfd, transform.getResourceId()); + mService.removeTransportModeTransforms(pfd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 9d228c3d0a..46a35ec800 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1235,8 +1235,8 @@ public class IpSecService extends IIpSecService.Stub { * reserved for future improved input validation. */ @Override - public synchronized void removeTransportModeTransforms( - ParcelFileDescriptor socket, int resourceId) throws RemoteException { + public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) + throws RemoteException { try { mSrvConfig .getNetdInstance() From 86713abfc755ab000ec906259f92b4aabb3d9977 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 17 Jan 2018 18:25:16 +0900 Subject: [PATCH 086/881] Add "not congested" network capability. Can be used by a network to indicate when it's congested, meaning that apps should defer network traffic that could be done at a later time. Test: bit FrameworksNetTests:android.net.,com.android.server.net.,com.android.server.connectivity.VpnTest,com.android.server.ConnectivityServiceTest Bug: 64133169 Change-Id: I97664d041920c8d6e3f9fb7c9e8638925b15c30e --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 0bbe3b5e3c..2e5d09e2ca 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -429,6 +429,7 @@ class EthernetNetworkFactory { mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); + mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); // We have no useful data on bandwidth. Say 100M up and 100M down. :-( mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000); From fab3fa31106dfe2acdf10e058468fb58cef4a95d Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 13 Dec 2017 17:16:53 -0800 Subject: [PATCH 087/881] Address comments and final cleanup from refcounting integration Added some extra comments on reference counting and moved a few methods around. No significant logical changes made in this CL Bug: 63409385 Test: CTS, Unit tests (both frameworks-base and netd) and binder tests all pass Change-Id: I89f1f4a021db48ae406fefefa6aca7406045736c --- .../java/com/android/server/IpSecService.java | 90 +++++++++++++------ 1 file changed, 63 insertions(+), 27 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 46a35ec800..64eb870352 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -148,7 +148,7 @@ public class IpSecService extends IIpSecService.Stub { * resources. * *

References to the IResource object may be held by other RefcountedResource objects, - * and as such, the kernel resources and quota may not be cleaned up. + * and as such, the underlying resources and quota may not be cleaned up. */ void invalidate() throws RemoteException; @@ -298,7 +298,12 @@ public class IpSecService extends IIpSecService.Stub { } } - /* Very simple counting class that looks much like a counting semaphore */ + /** + * Very simple counting class that looks much like a counting semaphore + * + *

This class is not thread-safe, and expects that that users of this class will ensure + * synchronization and thread safety by holding the IpSecService.this instance lock. + */ @VisibleForTesting static class ResourceTracker { private final int mMax; @@ -341,26 +346,38 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting static final class UserRecord { - /* Type names */ - public static final String TYPENAME_SPI = "SecurityParameterIndex"; - public static final String TYPENAME_TRANSFORM = "IpSecTransform"; - public static final String TYPENAME_ENCAP_SOCKET = "UdpEncapSocket"; - /* Maximum number of each type of resource that a single UID may possess */ public static final int MAX_NUM_ENCAP_SOCKETS = 2; public static final int MAX_NUM_TRANSFORMS = 4; public static final int MAX_NUM_SPIS = 8; + /** + * Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing + * and explicit (user) reference management. + * + *

These are stored in separate arrays to improve debuggability and dump output clarity. + * + *

Resources are removed from this array when the user releases their explicit reference + * by calling one of the releaseResource() methods. + */ final RefcountedResourceArray mSpiRecords = - new RefcountedResourceArray<>(TYPENAME_SPI); - final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS); - + new RefcountedResourceArray<>(SpiRecord.class.getSimpleName()); final RefcountedResourceArray mTransformRecords = - new RefcountedResourceArray<>(TYPENAME_TRANSFORM); - final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS); - + new RefcountedResourceArray<>(TransformRecord.class.getSimpleName()); final RefcountedResourceArray mEncapSocketRecords = - new RefcountedResourceArray<>(TYPENAME_ENCAP_SOCKET); + new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName()); + + /** + * Trackers for quotas for each of the OwnedResource types. + * + *

These trackers are separate from the resource arrays, since they are incremented and + * decremented at different points in time. Specifically, quota is only returned upon final + * resource deallocation (after all explicit and implicit references are released). Note + * that it is possible that calls to releaseResource() will not return the used quota if + * there are other resources that depend on (are parents of) the resource being released. + */ + final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS); + final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS); final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); void removeSpiRecord(int resourceId) { @@ -395,11 +412,15 @@ public class IpSecService extends IIpSecService.Stub { } } + /** + * This class is not thread-safe, and expects that that users of this class will ensure + * synchronization and thread safety by holding the IpSecService.this instance lock. + */ @VisibleForTesting static final class UserResourceTracker { private final SparseArray mUserRecords = new SparseArray<>(); - /** Never-fail getter that populates the list of UIDs as-needed */ + /** Lazy-initialization/getter that populates or retrieves the UserRecord as needed */ public UserRecord getUserRecord(int uid) { checkCallerUid(uid); @@ -428,18 +449,20 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting final UserResourceTracker mUserResourceTracker = new UserResourceTracker(); /** - * The KernelResourceRecord class provides a facility to cleanly and reliably track system + * The OwnedResourceRecord class provides a facility to cleanly and reliably track system * resources. It relies on a provided resourceId that should uniquely identify the kernel * resource. To use this class, the user should implement the invalidate() and * freeUnderlyingResources() methods that are responsible for cleaning up IpSecService resource - * tracking arrays and kernel resources, respectively + * tracking arrays and kernel resources, respectively. + * + *

This class associates kernel resources with the UID that owns and controls them. */ - private abstract class KernelResourceRecord implements IResource { + private abstract class OwnedResourceRecord implements IResource { final int pid; final int uid; protected final int mResourceId; - KernelResourceRecord(int resourceId) { + OwnedResourceRecord(int resourceId) { super(); if (resourceId == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); @@ -479,8 +502,6 @@ public class IpSecService extends IIpSecService.Stub { } }; - // TODO: Move this to right after RefcountedResource. With this here, Gerrit was showing many - // more things as changed. /** * Thin wrapper over SparseArray to ensure resources exist, and simplify generic typing. * @@ -534,7 +555,12 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class TransformRecord extends KernelResourceRecord { + /** + * Tracks an SA in the kernel, and manages cleanup paths. Once a TransformRecord is + * created, the SpiRecord that originally tracked the SAs will reliquish the + * responsibility of freeing the underlying SA to this class via the mOwnedByTransform flag. + */ + private final class TransformRecord extends OwnedResourceRecord { private final IpSecConfig mConfig; private final SpiRecord mSpi; private final EncapSocketRecord mSocket; @@ -603,7 +629,12 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class SpiRecord extends KernelResourceRecord { + /** + * Tracks a single SA in the kernel, and manages cleanup paths. Once used in a Transform, the + * responsibility for cleaning up underlying resources will be passed to the TransformRecord + * object + */ + private final class SpiRecord extends OwnedResourceRecord { private final String mSourceAddress; private final String mDestinationAddress; private int mSpi; @@ -692,7 +723,14 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class EncapSocketRecord extends KernelResourceRecord { + /** + * Tracks a UDP encap socket, and manages cleanup paths + * + *

While this class does not manage non-kernel resources, race conditions around socket + * binding require that the service creates the encap socket, binds it and applies the socket + * policy before handing it to a user. + */ + private final class EncapSocketRecord extends OwnedResourceRecord { private FileDescriptor mSocket; private final int mPort; @@ -1112,9 +1150,7 @@ public class IpSecService extends IIpSecService.Stub { final int resourceId = mNextResourceId++; UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); - - // Avoid resizing by creating a dependency array of min-size 2 (1 UDP encap + 1 SPI) - List dependencies = new ArrayList<>(2); + List dependencies = new ArrayList<>(); if (!userRecord.mTransformQuotaTracker.isAvailable()) { return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); From 3f6d5df0b5a8565e7aa7f328628d26eb84df8cdb Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 17 Jan 2018 16:09:24 -0800 Subject: [PATCH 088/881] Add Tunnel Interface APIs to IpSecManager Add a new interface and a new management object, IpSecTunnelInterface to the IpSecManager surface. This object will be used to control IPsec tunnels. -Add IpSecTunnelInterface object -Add methods to create and use an IpSecTunnelInterface -Update the IpSecTransform builder to create Tunnel mode IpSecTransform objects (usable with an IpSecTunnel) Bug: 36033193 Test: compilation Change-Id: Ib6948b12c15c93674234dc36288058ae44435b90 --- core/java/android/net/IpSecManager.java | 128 ++++++++++++++++++++++ core/java/android/net/IpSecTransform.java | 16 +-- 2 files changed, 129 insertions(+), 15 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 2cda58c99a..f04f03f6b6 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -19,6 +19,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; @@ -624,6 +625,133 @@ public final class IpSecManager { return new UdpEncapsulationSocket(mService, 0); } + /** + * This class represents an IpSecTunnelInterface + * + *

IpSecTunnelInterface objects track tunnel interfaces that serve as + * local endpoints for IPsec tunnels. + * + *

Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be + * applied to provide IPsec security to packets sent through the tunnel. While a tunnel + * cannot be used in standalone mode within Android, the higher layers may use the tunnel + * to create Network objects which are accessible to the Android system. + * @hide + */ + @SystemApi + public static final class IpSecTunnelInterface implements AutoCloseable { + private final IIpSecService mService; + private final InetAddress mRemoteAddress; + private final InetAddress mLocalAddress; + private final Network mUnderlyingNetwork; + private final CloseGuard mCloseGuard = CloseGuard.get(); + private String mInterfaceName; + private int mResourceId = INVALID_RESOURCE_ID; + + /** Get the underlying SPI held by this object. */ + public String getInterfaceName() { + return mInterfaceName; + } + + /** + * Add an address to the IpSecTunnelInterface + * + *

Add an address which may be used as the local inner address for + * tunneled traffic. + * + * @param address the local address for traffic inside the tunnel + * @throws IOException if the address could not be added + * @hide + */ + public void addAddress(LinkAddress address) throws IOException { + } + + /** + * Remove an address from the IpSecTunnelInterface + * + *

Remove an address which was previously added to the IpSecTunnelInterface + * + * @param address to be removed + * @throws IOException if the address could not be removed + * @hide + */ + public void removeAddress(LinkAddress address) throws IOException { + } + + private IpSecTunnelInterface(@NonNull IIpSecService service, + @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, + @NonNull Network underlyingNetwork) + throws ResourceUnavailableException, IOException { + mService = service; + mLocalAddress = localAddress; + mRemoteAddress = remoteAddress; + mUnderlyingNetwork = underlyingNetwork; + // TODO: Call IpSecService + } + + /** + * Delete an IpSecTunnelInterface + * + *

Calling close will deallocate the IpSecTunnelInterface and all of its system + * resources. Any packets bound for this interface either inbound or outbound will + * all be lost. + */ + @Override + public void close() { + // try { + // TODO: Call IpSecService + mResourceId = INVALID_RESOURCE_ID; + // } catch (RemoteException e) { + // throw e.rethrowFromSystemServer(); + // } + mCloseGuard.close(); + } + + /** Check that the Interface was closed properly. */ + @Override + protected void finalize() throws Throwable { + if (mCloseGuard != null) { + mCloseGuard.warnIfOpen(); + } + close(); + } + } + + /** + * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. + * + * @param localAddress The local addres of the tunnel + * @param remoteAddress The local addres of the tunnel + * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. + * This network should almost certainly be a network such as WiFi with an L2 address. + * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties + * @throws IOException indicating that the socket could not be opened or bound + * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open + * @hide + */ + @SystemApi + public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, + @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) + throws ResourceUnavailableException, IOException { + return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork); + } + + /** + * Apply a transform to the IpSecTunnelInterface + * + * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied + * transform. + * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which + * the transform will be used. + * @param transform an {@link IpSecTransform} created in tunnel mode + * @throws IOException indicating that the transform could not be applied due to a lower + * layer failure. + * @hide + */ + @SystemApi + void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction, + IpSecTransform transform) throws IOException { + // TODO: call IpSecService + } /** * Construct an instance of IpSecManager within an application context. * diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 7b9b483092..be6026ff37 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -299,21 +299,6 @@ public final class IpSecTransform implements AutoCloseable { return this; } - /** - * Set the {@link Network} which will carry tunneled traffic. - * - *

Restricts the transformed traffic to a particular {@link Network}. This is required - * for tunnel mode, otherwise tunneled traffic would be sent on the default network. - * - * @hide - */ - @SystemApi - public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) { - Preconditions.checkNotNull(net); - mConfig.setNetwork(net); - return this; - } - /** * Add UDP encapsulation to an IPv4 transform. * @@ -415,6 +400,7 @@ public final class IpSecTransform implements AutoCloseable { * @throws IOException indicating other errors * @hide */ + @SystemApi public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) From 47d108c1913797206356b3fdc377a54fb0efb5ef Mon Sep 17 00:00:00 2001 From: Di Lu Date: Thu, 11 Jan 2018 11:35:25 -0800 Subject: [PATCH 089/881] Add xfrm mark in IpSecConfig Bug: 63589600 Test: runtest frameworks-net Change-Id: I2d38d781b8b31d8bf39fd4e9a7e31509f15a9e16 --- core/java/android/net/IpSecConfig.java | 32 ++++++++++++++++++- .../java/com/android/server/IpSecService.java | 8 +++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 80b0af3373..6a262e2c87 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -65,6 +65,10 @@ public final class IpSecConfig implements Parcelable { // An interval, in seconds between the NattKeepalive packets private int mNattKeepaliveInterval; + // XFRM mark and mask + private int mMarkValue; + private int mMarkMask; + /** Set the mode for this IPsec transform */ public void setMode(int mode) { mMode = mode; @@ -121,6 +125,14 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = interval; } + public void setMarkValue(int mark) { + mMarkValue = mark; + } + + public void setMarkMask(int mask) { + mMarkMask = mask; + } + // Transport or Tunnel public int getMode() { return mMode; @@ -170,6 +182,14 @@ public final class IpSecConfig implements Parcelable { return mNattKeepaliveInterval; } + public int getMarkValue() { + return mMarkValue; + } + + public int getMarkMask() { + return mMarkMask; + } + // Parcelable Methods @Override @@ -191,6 +211,8 @@ public final class IpSecConfig implements Parcelable { out.writeInt(mEncapSocketResourceId); out.writeInt(mEncapRemotePort); out.writeInt(mNattKeepaliveInterval); + out.writeInt(mMarkValue); + out.writeInt(mMarkMask); } @VisibleForTesting @@ -212,6 +234,8 @@ public final class IpSecConfig implements Parcelable { mEncapSocketResourceId = in.readInt(); mEncapRemotePort = in.readInt(); mNattKeepaliveInterval = in.readInt(); + mMarkValue = in.readInt(); + mMarkMask = in.readInt(); } @Override @@ -242,6 +266,10 @@ public final class IpSecConfig implements Parcelable { .append(mAuthentication) .append(", mAuthenticatedEncryption=") .append(mAuthenticatedEncryption) + .append(", mMarkValue=") + .append(mMarkValue) + .append(", mMarkMask=") + .append(mMarkMask) .append("}"); return strBuilder.toString(); @@ -275,6 +303,8 @@ public final class IpSecConfig implements Parcelable { && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) && IpSecAlgorithm.equals( lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) - && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication)); + && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication) + && lhs.mMarkValue == rhs.mMarkValue + && lhs.mMarkMask == rhs.mMarkMask); } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 46a35ec800..09d7d9bc62 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -566,7 +566,9 @@ public class IpSecService extends IIpSecService.Stub { mResourceId, mConfig.getSourceAddress(), mConfig.getDestinationAddress(), - spi); + spi, + mConfig.getMarkValue(), + mConfig.getMarkMask()); } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception } catch (RemoteException e) { @@ -634,7 +636,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - mResourceId, mSourceAddress, mDestinationAddress, mSpi); + mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception } catch (RemoteException e) { @@ -1153,6 +1155,8 @@ public class IpSecService extends IIpSecService.Stub { c.getDestinationAddress(), (c.getNetwork() != null) ? c.getNetwork().netId : 0, spiRecord.getSpi(), + c.getMarkValue(), + c.getMarkMask(), (auth != null) ? auth.getName() : "", (auth != null) ? auth.getKey() : new byte[] {}, (auth != null) ? auth.getTruncationLengthBits() : 0, From bc015bd353f7fa97e1aad2ec721de3cddc7f18f1 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 00:50:48 +0900 Subject: [PATCH 090/881] Pass all default networks to NetworkStatsService This will allow NetworkStatsService to treat traffic on these networks differently from traffic where the app selects a network that is not the default. Bug: 35142602 Test: runtest frameworks-net Change-Id: I5ea9d200d9fb153490c6108bb9390bf152f297da --- .../android/net/INetworkStatsService.aidl | 3 ++- .../server/net/NetworkStatsService.java | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 95e7f6031c..90e3ffd550 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.DataUsageRequest; import android.net.INetworkStatsSession; +import android.net.Network; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; @@ -53,7 +54,7 @@ interface INetworkStatsService { void setUidForeground(int uid, boolean uidForeground); /** Force update of ifaces. */ - void forceUpdateIfaces(); + void forceUpdateIfaces(in Network[] defaultNetworks); /** Force update of statistics. */ void forceUpdate(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index db61ef5cd9..0b25573c30 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -83,6 +83,7 @@ import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.LinkProperties; +import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkInfo; @@ -231,14 +232,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final Object mStatsLock = new Object(); /** Set of currently active ifaces. */ + @GuardedBy("mStatsLock") private final ArrayMap mActiveIfaces = new ArrayMap<>(); + /** Set of currently active ifaces for UID stats. */ + @GuardedBy("mStatsLock") private final ArrayMap mActiveUidIfaces = new ArrayMap<>(); + /** Current default active iface. */ private String mActiveIface; + /** Set of any ifaces associated with mobile networks since boot. */ + @GuardedBy("mStatsLock") private String[] mMobileIfaces = new String[0]; + /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */ + @GuardedBy("mStatsLock") + private Network[] mDefaultNetworks = new Network[0]; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -779,13 +790,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void forceUpdateIfaces() { + public void forceUpdateIfaces(Network[] defaultNetworks) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(); + updateIfaces(defaultNetworks); } finally { Binder.restoreCallingIdentity(token); } @@ -996,11 +1007,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; - private void updateIfaces() { + private void updateIfaces(Network[] defaultNetworks) { synchronized (mStatsLock) { mWakeLock.acquire(); try { - updateIfacesLocked(); + updateIfacesLocked(defaultNetworks); } finally { mWakeLock.release(); } @@ -1013,7 +1024,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * are active on a single {@code iface}, they are combined under a single * {@link NetworkIdentitySet}. */ - private void updateIfacesLocked() { + private void updateIfacesLocked(Network[] defaultNetworks) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1040,6 +1051,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); + if (defaultNetworks != null) { + // Caller is ConnectivityService. Update the list of default networks. + mDefaultNetworks = defaultNetworks; + } final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { @@ -1511,7 +1526,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return true; } case MSG_UPDATE_IFACES: { - mService.updateIfaces(); + mService.updateIfaces(null); return true; } case MSG_REGISTER_GLOBAL_ALERT: { From 6fe513c753074172d255a01aa2be53d0d2f2d416 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 01:05:20 +0900 Subject: [PATCH 091/881] Add the default network to NetworkStats and NetworkStatsCollection. This allows us to maintain NetworkStats entries that track whether the traffic was on the default network. At the moment, the stats collection code always passes in DEFAULT_NETWORK_NO. However, this value is a no-op, since it is not persisted to disk. Only the ident, the uid/set/tag, and the packet/byte/operation counters are persisted. A future change will add defaultNetwork to the ident and start persisting it. Bug: 35142602 Test: runtest frameworks-net Change-Id: Ifa291c62c0fa389b88e5561086a29dcd7cee2253 --- core/java/android/net/NetworkStats.java | 90 +++++++++++++++---- .../internal/net/NetworkStatsFactory.java | 2 +- ...droid_internal_net_NetworkStatsFactory.cpp | 9 +- .../server/net/NetworkStatsCollection.java | 2 + .../server/net/NetworkStatsService.java | 7 +- 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 171adc054b..a85f80e38d 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -82,6 +82,13 @@ public class NetworkStats implements Parcelable { /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; + /** {@link #onDefaultNetwork} value to account for all default network states. */ + public static final int DEFAULT_NETWORK_ALL = -1; + /** {@link #onDefaultNetwork} value to account for usage while not the default network. */ + public static final int DEFAULT_NETWORK_NO = 0; + /** {@link #onDefaultNetwork} value to account for usage while the default network. */ + public static final int DEFAULT_NETWORK_YES = 1; + /** Denotes a request for stats at the interface level. */ public static final int STATS_PER_IFACE = 0; /** Denotes a request for stats at the interface and UID level. */ @@ -102,6 +109,7 @@ public class NetworkStats implements Parcelable { private int[] tag; private int[] metered; private int[] roaming; + private int[] defaultNetwork; private long[] rxBytes; private long[] rxPackets; private long[] txBytes; @@ -125,6 +133,12 @@ public class NetworkStats implements Parcelable { * getSummary(). */ public int roaming; + /** + * Note that this is only populated w/ the default value when read from /proc or written + * to disk. We merge in the correct value when reporting this value to clients of + * getSummary(). + */ + public int defaultNetwork; public long rxBytes; public long rxPackets; public long txBytes; @@ -142,18 +156,27 @@ public class NetworkStats implements Parcelable { public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - this(iface, uid, set, tag, METERED_NO, ROAMING_NO, rxBytes, rxPackets, txBytes, - txPackets, operations); + this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, + rxBytes, rxPackets, txBytes, txPackets, operations); + } + + // TODO: fix the the telephony code to pass DEFAULT_NETWORK_YES and remove this constructor. + public Entry(String iface, int uid, int set, int tag, int metered, int roaming, + long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + this(iface, uid, set, tag, metered, roaming, DEFAULT_NETWORK_YES, rxBytes, rxPackets, + txBytes, txPackets, operations); } public Entry(String iface, int uid, int set, int tag, int metered, int roaming, - long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { this.iface = iface; this.uid = uid; this.set = set; this.tag = tag; this.metered = metered; this.roaming = roaming; + this.defaultNetwork = defaultNetwork; this.rxBytes = rxBytes; this.rxPackets = rxPackets; this.txBytes = txBytes; @@ -187,6 +210,7 @@ public class NetworkStats implements Parcelable { builder.append(" tag=").append(tagToString(tag)); builder.append(" metered=").append(meteredToString(metered)); builder.append(" roaming=").append(roamingToString(roaming)); + builder.append(" defaultNetwork=").append(defaultNetworkToString(defaultNetwork)); builder.append(" rxBytes=").append(rxBytes); builder.append(" rxPackets=").append(rxPackets); builder.append(" txBytes=").append(txBytes); @@ -200,7 +224,8 @@ public class NetworkStats implements Parcelable { if (o instanceof Entry) { final Entry e = (Entry) o; return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered - && roaming == e.roaming && rxBytes == e.rxBytes && rxPackets == e.rxPackets + && roaming == e.roaming && defaultNetwork == e.defaultNetwork + && rxBytes == e.rxBytes && rxPackets == e.rxPackets && txBytes == e.txBytes && txPackets == e.txPackets && operations == e.operations && iface.equals(e.iface); } @@ -209,7 +234,7 @@ public class NetworkStats implements Parcelable { @Override public int hashCode() { - return Objects.hash(uid, set, tag, metered, roaming, iface); + return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface); } } @@ -224,6 +249,7 @@ public class NetworkStats implements Parcelable { this.tag = new int[initialSize]; this.metered = new int[initialSize]; this.roaming = new int[initialSize]; + this.defaultNetwork = new int[initialSize]; this.rxBytes = new long[initialSize]; this.rxPackets = new long[initialSize]; this.txBytes = new long[initialSize]; @@ -238,6 +264,7 @@ public class NetworkStats implements Parcelable { this.tag = EmptyArray.INT; this.metered = EmptyArray.INT; this.roaming = EmptyArray.INT; + this.defaultNetwork = EmptyArray.INT; this.rxBytes = EmptyArray.LONG; this.rxPackets = EmptyArray.LONG; this.txBytes = EmptyArray.LONG; @@ -256,6 +283,7 @@ public class NetworkStats implements Parcelable { tag = parcel.createIntArray(); metered = parcel.createIntArray(); roaming = parcel.createIntArray(); + defaultNetwork = parcel.createIntArray(); rxBytes = parcel.createLongArray(); rxPackets = parcel.createLongArray(); txBytes = parcel.createLongArray(); @@ -274,6 +302,7 @@ public class NetworkStats implements Parcelable { dest.writeIntArray(tag); dest.writeIntArray(metered); dest.writeIntArray(roaming); + dest.writeIntArray(defaultNetwork); dest.writeLongArray(rxBytes); dest.writeLongArray(rxPackets); dest.writeLongArray(txBytes); @@ -308,10 +337,11 @@ public class NetworkStats implements Parcelable { @VisibleForTesting public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming, - long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { return addValues(new Entry( - iface, uid, set, tag, metered, roaming, rxBytes, rxPackets, txBytes, txPackets, - operations)); + iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets, + txBytes, txPackets, operations)); } /** @@ -327,6 +357,7 @@ public class NetworkStats implements Parcelable { tag = Arrays.copyOf(tag, newLength); metered = Arrays.copyOf(metered, newLength); roaming = Arrays.copyOf(roaming, newLength); + defaultNetwork = Arrays.copyOf(defaultNetwork, newLength); rxBytes = Arrays.copyOf(rxBytes, newLength); rxPackets = Arrays.copyOf(rxPackets, newLength); txBytes = Arrays.copyOf(txBytes, newLength); @@ -341,6 +372,7 @@ public class NetworkStats implements Parcelable { tag[size] = entry.tag; metered[size] = entry.metered; roaming[size] = entry.roaming; + defaultNetwork[size] = entry.defaultNetwork; rxBytes[size] = entry.rxBytes; rxPackets[size] = entry.rxPackets; txBytes[size] = entry.txBytes; @@ -362,6 +394,7 @@ public class NetworkStats implements Parcelable { entry.tag = tag[i]; entry.metered = metered[i]; entry.roaming = roaming[i]; + entry.defaultNetwork = defaultNetwork[i]; entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; @@ -416,7 +449,7 @@ public class NetworkStats implements Parcelable { */ public NetworkStats combineValues(Entry entry) { final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, - entry.roaming); + entry.roaming, entry.defaultNetwork); if (i == -1) { // only create new entry when positive contribution addValues(entry); @@ -444,10 +477,12 @@ public class NetworkStats implements Parcelable { /** * Find first stats index that matches the requested parameters. */ - public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming) { + public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming, + int defaultNetwork) { for (int i = 0; i < size; i++) { if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] && metered == this.metered[i] && roaming == this.roaming[i] + && defaultNetwork == this.defaultNetwork[i] && Objects.equals(iface, this.iface[i])) { return i; } @@ -461,7 +496,7 @@ public class NetworkStats implements Parcelable { */ @VisibleForTesting public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming, - int hintIndex) { + int defaultNetwork, int hintIndex) { for (int offset = 0; offset < size; offset++) { final int halfOffset = offset / 2; @@ -475,6 +510,7 @@ public class NetworkStats implements Parcelable { if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] && metered == this.metered[i] && roaming == this.roaming[i] + && defaultNetwork == this.defaultNetwork[i] && Objects.equals(iface, this.iface[i])) { return i; } @@ -489,7 +525,8 @@ public class NetworkStats implements Parcelable { */ public void spliceOperationsFrom(NetworkStats stats) { for (int i = 0; i < size; i++) { - final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i]); + final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i], + defaultNetwork[i]); if (j == -1) { operations[i] = 0; } else { @@ -581,6 +618,7 @@ public class NetworkStats implements Parcelable { entry.tag = TAG_NONE; entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; + entry.defaultNetwork = DEFAULT_NETWORK_ALL; entry.rxBytes = 0; entry.rxPackets = 0; entry.txBytes = 0; @@ -677,6 +715,7 @@ public class NetworkStats implements Parcelable { entry.tag = left.tag[i]; entry.metered = left.metered[i]; entry.roaming = left.roaming[i]; + entry.defaultNetwork = left.defaultNetwork[i]; entry.rxBytes = left.rxBytes[i]; entry.rxPackets = left.rxPackets[i]; entry.txBytes = left.txBytes[i]; @@ -685,7 +724,7 @@ public class NetworkStats implements Parcelable { // find remote row that matches, and subtract final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, - entry.metered, entry.roaming, i); + entry.metered, entry.roaming, entry.defaultNetwork, i); if (j != -1) { // Found matching row, subtract remote value. entry.rxBytes -= right.rxBytes[j]; @@ -725,6 +764,7 @@ public class NetworkStats implements Parcelable { entry.tag = TAG_NONE; entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; + entry.defaultNetwork = DEFAULT_NETWORK_ALL; entry.operations = 0L; for (int i = 0; i < size; i++) { @@ -755,6 +795,7 @@ public class NetworkStats implements Parcelable { entry.tag = TAG_NONE; entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; + entry.defaultNetwork = DEFAULT_NETWORK_ALL; for (int i = 0; i < size; i++) { // skip specific tags, since already counted in TAG_NONE @@ -802,6 +843,7 @@ public class NetworkStats implements Parcelable { pw.print(" tag="); pw.print(tagToString(tag[i])); pw.print(" metered="); pw.print(meteredToString(metered[i])); pw.print(" roaming="); pw.print(roamingToString(roaming[i])); + pw.print(" defaultNetwork="); pw.print(defaultNetworkToString(defaultNetwork[i])); pw.print(" rxBytes="); pw.print(rxBytes[i]); pw.print(" rxPackets="); pw.print(rxPackets[i]); pw.print(" txBytes="); pw.print(txBytes[i]); @@ -900,6 +942,22 @@ public class NetworkStats implements Parcelable { } } + /** + * Return text description of {@link #defaultNetwork} value. + */ + public static String defaultNetworkToString(int defaultNetwork) { + switch (defaultNetwork) { + case DEFAULT_NETWORK_ALL: + return "ALL"; + case DEFAULT_NETWORK_NO: + return "NO"; + case DEFAULT_NETWORK_YES: + return "YES"; + default: + return "UNKNOWN"; + } + } + @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); @@ -1055,6 +1113,7 @@ public class NetworkStats implements Parcelable { tmpEntry.set = set[i]; tmpEntry.metered = metered[i]; tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; combineValues(tmpEntry); if (tag[i] == TAG_NONE) { moved.add(tmpEntry); @@ -1075,6 +1134,7 @@ public class NetworkStats implements Parcelable { moved.iface = underlyingIface; moved.metered = METERED_ALL; moved.roaming = ROAMING_ALL; + moved.defaultNetwork = DEFAULT_NETWORK_ALL; combineValues(moved); // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than @@ -1085,13 +1145,13 @@ public class NetworkStats implements Parcelable { // roaming data after applying these adjustments, by checking the NetworkIdentity of the // underlying iface. int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO); + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnBackground != -1) { tunSubtract(idxVpnBackground, this, moved); } int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO); + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnForeground != -1) { tunSubtract(idxVpnForeground, this, moved); } diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 3d3e148fb3..b576a20db5 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -217,7 +217,7 @@ public class NetworkStatsFactory { } NetworkStats.Entry adjust = - new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); + new NetworkStats.Entry(baseIface, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); // Subtract any 464lat traffic seen for the root UID on the current base interface. adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 0cb6935990..d254de65f7 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -45,6 +45,7 @@ static struct { jfieldID tag; jfieldID metered; jfieldID roaming; + jfieldID defaultNetwork; jfieldID rxBytes; jfieldID rxPackets; jfieldID txBytes; @@ -246,6 +247,9 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, ScopedIntArrayRW roaming(env, get_int_array(env, stats, gNetworkStatsClassInfo.roaming, size, grow)); if (roaming.get() == NULL) return -1; + ScopedIntArrayRW defaultNetwork(env, get_int_array(env, stats, + gNetworkStatsClassInfo.defaultNetwork, size, grow)); + if (defaultNetwork.get() == NULL) return -1; ScopedLongArrayRW rxBytes(env, get_long_array(env, stats, gNetworkStatsClassInfo.rxBytes, size, grow)); if (rxBytes.get() == NULL) return -1; @@ -269,7 +273,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, uid[i] = lines[i].uid; set[i] = lines[i].set; tag[i] = lines[i].tag; - // Metered and Roaming are populated in Java-land by inspecting the iface properties. + // Metered, roaming and defaultNetwork are populated in Java-land. rxBytes[i] = lines[i].rxBytes; rxPackets[i] = lines[i].rxPackets; txBytes[i] = lines[i].txBytes; @@ -285,6 +289,8 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.metered, metered.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray()); + env->SetObjectField(stats, gNetworkStatsClassInfo.defaultNetwork, + defaultNetwork.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray()); @@ -318,6 +324,7 @@ int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I"); gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I"); gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I"); + gNetworkStatsClassInfo.defaultNetwork = GetFieldIDOrDie(env, clazz, "defaultNetwork", "[I"); gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J"); gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J"); gNetworkStatsClassInfo.txBytes = GetFieldIDOrDie(env, clazz, "txBytes", "[J"); diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 4ceb592af0..5f797691be 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.DEFAULT_NETWORK_YES; import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_NO; @@ -364,6 +365,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; + entry.defaultNetwork = DEFAULT_NETWORK_YES; entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO; entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 0b25573c30..84dd05d326 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -25,6 +25,7 @@ import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.METERED_ALL; import static android.net.NetworkStats.ROAMING_ALL; @@ -677,9 +678,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); final NetworkStats stats = new NetworkStats(end - start, 1); - stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, - ROAMING_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, - entry.operations)); + stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets, + entry.txBytes, entry.txPackets, entry.operations)); return stats; } From 502b95fb44f0bc8236cb29137d74267cad2d28ab Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 01:12:04 +0900 Subject: [PATCH 092/881] Track and persist in stats whether traffic is on the default network. This change adds the defaultNetwork to the ident based on current system networking state, and persists that value to flash. Bug: 35142602 Test: runtest frameworks-net Test: downloaded files using default/non-default networks while watching dumpsys netstats Change-Id: Id8776d149b2977548a9eb455ad4926af55e25aba --- core/java/android/net/NetworkIdentity.java | 24 ++++++++++++---- .../server/net/NetworkIdentitySet.java | 28 +++++++++++++++++-- .../server/net/NetworkStatsCollection.java | 4 ++- .../server/net/NetworkStatsService.java | 7 +++-- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index d3b35998be..fd118f3401 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -58,21 +58,24 @@ public class NetworkIdentity implements Comparable { final String mNetworkId; final boolean mRoaming; final boolean mMetered; + final boolean mDefaultNetwork; public NetworkIdentity( int type, int subType, String subscriberId, String networkId, boolean roaming, - boolean metered) { + boolean metered, boolean defaultNetwork) { mType = type; mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType; mSubscriberId = subscriberId; mNetworkId = networkId; mRoaming = roaming; mMetered = metered; + mDefaultNetwork = defaultNetwork; } @Override public int hashCode() { - return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered); + return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered, + mDefaultNetwork); } @Override @@ -82,7 +85,8 @@ public class NetworkIdentity implements Comparable { return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming && Objects.equals(mSubscriberId, ident.mSubscriberId) && Objects.equals(mNetworkId, ident.mNetworkId) - && mMetered == ident.mMetered; + && mMetered == ident.mMetered + && mDefaultNetwork == ident.mDefaultNetwork; } return false; } @@ -109,6 +113,7 @@ public class NetworkIdentity implements Comparable { builder.append(", ROAMING"); } builder.append(", metered=").append(mMetered); + builder.append(", defaultNetwork=").append(mDefaultNetwork); return builder.append("}").toString(); } @@ -153,6 +158,10 @@ public class NetworkIdentity implements Comparable { return mMetered; } + public boolean getDefaultNetwork() { + return mDefaultNetwork; + } + /** * Scrub given IMSI on production builds. */ @@ -183,7 +192,8 @@ public class NetworkIdentity implements Comparable { * Build a {@link NetworkIdentity} from the given {@link NetworkState}, * assuming that any mobile networks are using the current IMSI. */ - public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) { + public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, + boolean defaultNetwork) { final int type = state.networkInfo.getType(); final int subType = state.networkInfo.getSubtype(); @@ -216,7 +226,8 @@ public class NetworkIdentity implements Comparable { } } - return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered); + return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, + defaultNetwork); } @Override @@ -237,6 +248,9 @@ public class NetworkIdentity implements Comparable { if (res == 0) { res = Boolean.compare(mMetered, another.mMetered); } + if (res == 0) { + res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork); + } return res; } } diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index ee00fdc333..68cd5e7aed 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -39,6 +39,7 @@ public class NetworkIdentitySet extends HashSet implements private static final int VERSION_ADD_ROAMING = 2; private static final int VERSION_ADD_NETWORK_ID = 3; private static final int VERSION_ADD_METERED = 4; + private static final int VERSION_ADD_DEFAULT_NETWORK = 5; public NetworkIdentitySet() { } @@ -76,12 +77,20 @@ public class NetworkIdentitySet extends HashSet implements metered = (type == TYPE_MOBILE); } - add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered)); + final boolean defaultNetwork; + if (version >= VERSION_ADD_DEFAULT_NETWORK) { + defaultNetwork = in.readBoolean(); + } else { + defaultNetwork = true; + } + + add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, + defaultNetwork)); } } public void writeToStream(DataOutputStream out) throws IOException { - out.writeInt(VERSION_ADD_METERED); + out.writeInt(VERSION_ADD_DEFAULT_NETWORK); out.writeInt(size()); for (NetworkIdentity ident : this) { out.writeInt(ident.getType()); @@ -90,6 +99,7 @@ public class NetworkIdentitySet extends HashSet implements writeOptionalString(out, ident.getNetworkId()); out.writeBoolean(ident.getRoaming()); out.writeBoolean(ident.getMetered()); + out.writeBoolean(ident.getDefaultNetwork()); } } @@ -119,6 +129,20 @@ public class NetworkIdentitySet extends HashSet implements return false; } + /** @return whether any {@link NetworkIdentity} in this set is considered on the default + network. */ + public boolean areAllMembersOnDefaultNetwork() { + if (isEmpty()) { + return true; + } + for (NetworkIdentity ident : this) { + if (!ident.getDefaultNetwork()) { + return false; + } + } + return true; + } + private static void writeOptionalString(DataOutputStream out, String value) throws IOException { if (value != null) { out.writeByte(1); diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 5f797691be..961a451778 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.METERED_YES; @@ -365,7 +366,8 @@ public class NetworkStatsCollection implements FileRotator.Reader { entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; - entry.defaultNetwork = DEFAULT_NETWORK_YES; + entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() ? + DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO; entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO; entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 84dd05d326..78fd4b4923 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1061,7 +1061,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); - final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); + final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); + final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, + isDefault); // Traffic occurring on the base interface is always counted for // both total usage and UID details. @@ -1081,7 +1083,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Copy the identify from IMS one but mark it as metered. NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), - ident.getRoaming(), true); + ident.getRoaming(), true /* metered */, + true /* onDefaultNetwork */); findOrCreateNetworkIdentitySet(mActiveIfaces, VT_INTERFACE).add(vtIdent); findOrCreateNetworkIdentitySet(mActiveUidIfaces, VT_INTERFACE).add(vtIdent); } From f6311456b2b06485d03bca6cd4c7dd1f634402ab Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 01:12:58 +0900 Subject: [PATCH 093/881] Add getDefaultNetwork to the NetworkStats public API. This allows an app using the public API to know whether the traffic in a particular bucket was on the default network (i.e., the network was selected by the system), or not (i.e., the network was selected by the app). Bug: 35142602 Test: builds, boots Test: added coverage to NetworkUsageStatsTest CTS test, still passes Change-Id: I9f6669908fa119743b9c0aa0c31a03e5ebafa7db --- core/java/android/app/usage/NetworkStats.java | 52 +++++++++++++++++++ .../app/usage/NetworkStatsManager.java | 35 +++++++------ 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 2e44a630b0..da36157d85 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -227,6 +227,30 @@ public final class NetworkStats implements AutoCloseable { */ public static final int ROAMING_YES = 0x2; + /** @hide */ + @IntDef(prefix = { "DEFAULT_NETWORK_" }, value = { + DEFAULT_NETWORK_ALL, + DEFAULT_NETWORK_NO, + DEFAULT_NETWORK_YES + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DefaultNetwork {} + + /** + * Combined usage for this network regardless of whether it was the active default network. + */ + public static final int DEFAULT_NETWORK_ALL = -1; + + /** + * Usage that occurs while this network is not the active default network. + */ + public static final int DEFAULT_NETWORK_NO = 0x1; + + /** + * Usage that occurs while this network is the active default network. + */ + public static final int DEFAULT_NETWORK_YES = 0x2; + /** * Special TAG value for total data across all tags */ @@ -235,6 +259,7 @@ public final class NetworkStats implements AutoCloseable { private int mUid; private int mTag; private int mState; + private int mDefaultNetwork; private int mMetered; private int mRoaming; private long mBeginTimeStamp; @@ -286,6 +311,15 @@ public final class NetworkStats implements AutoCloseable { return 0; } + private static @DefaultNetwork int convertDefaultNetwork(int defaultNetwork) { + switch (defaultNetwork) { + case android.net.NetworkStats.DEFAULT_NETWORK_ALL : return DEFAULT_NETWORK_ALL; + case android.net.NetworkStats.DEFAULT_NETWORK_NO: return DEFAULT_NETWORK_NO; + case android.net.NetworkStats.DEFAULT_NETWORK_YES: return DEFAULT_NETWORK_YES; + } + return 0; + } + public Bucket() { } @@ -350,6 +384,21 @@ public final class NetworkStats implements AutoCloseable { return mRoaming; } + /** + * Default network state. One of the following values:

+ *

    + *
  • {@link #DEFAULT_NETWORK_ALL}
  • + *
  • {@link #DEFAULT_NETWORK_NO}
  • + *
  • {@link #DEFAULT_NETWORK_YES}
  • + *
+ *

Indicates whether the network usage occurred on the system default network for this + * type of traffic, or whether the application chose to send this traffic on a network that + * was not the one selected by the system. + */ + public @DefaultNetwork int getDefaultNetwork() { + return mDefaultNetwork; + } + /** * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. @@ -551,6 +600,8 @@ public final class NetworkStats implements AutoCloseable { bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid); bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag); bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set); + bucketOut.mDefaultNetwork = Bucket.convertDefaultNetwork( + mRecycledSummaryEntry.defaultNetwork); bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered); bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming); bucketOut.mBeginTimeStamp = mStartTimeStamp; @@ -600,6 +651,7 @@ public final class NetworkStats implements AutoCloseable { bucketOut.mUid = Bucket.convertUid(getUid()); bucketOut.mTag = Bucket.convertTag(mTag); bucketOut.mState = Bucket.STATE_ALL; + bucketOut.mDefaultNetwork = Bucket.DEFAULT_NETWORK_ALL; bucketOut.mMetered = Bucket.METERED_ALL; bucketOut.mRoaming = Bucket.ROAMING_ALL; bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart; diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 853b00331a..90b514e272 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -60,10 +60,11 @@ import android.util.Log; * {@link #queryDetailsForUid}

* {@link #queryDetails}

* These queries do not aggregate over time but do aggregate over state, metered and roaming. - * Therefore there can be multiple buckets for a particular key but all Bucket's state is going to - * be {@link NetworkStats.Bucket#STATE_ALL}, all Bucket's metered is going to be - * {@link NetworkStats.Bucket#METERED_ALL}, and all Bucket's roaming is going to be - * {@link NetworkStats.Bucket#ROAMING_ALL}. + * Therefore there can be multiple buckets for a particular key. However, all Buckets will have + * {@code state} {@link NetworkStats.Bucket#STATE_ALL}, + * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * {@code metered } {@link NetworkStats.Bucket#METERED_ALL}, + * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}. *

* NOTE: Calling {@link #querySummaryForDevice} or accessing stats for apps other than the * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, @@ -136,7 +137,9 @@ public class NetworkStatsManager { * roaming. This means the bucket's start and end timestamp are going to be the same as the * 'startTime' and 'endTime' parameters. State is going to be * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL}, - * tag {@link NetworkStats.Bucket#TAG_NONE}, metered {@link NetworkStats.Bucket#METERED_ALL}, + * tag {@link NetworkStats.Bucket#TAG_NONE}, + * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered {@link NetworkStats.Bucket#METERED_ALL}, * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. * * @param networkType As defined in {@link ConnectivityManager}, e.g. @@ -209,10 +212,10 @@ public class NetworkStatsManager { /** * Query network usage statistics summaries. Result filtered to include only uids belonging to * calling user. Result is aggregated over time, hence all buckets will have the same start and - * end timestamps. Not aggregated over state, uid, metered, or roaming. This means buckets' - * start and end timestamps are going to be the same as the 'startTime' and 'endTime' - * parameters. State, uid, metered, and roaming are going to vary, and tag is going to be the - * same. + * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This + * means buckets' start and end timestamps are going to be the same as the 'startTime' and + * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to + * be the same. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -258,9 +261,10 @@ public class NetworkStatsManager { * belonging to calling user. Result is aggregated over state but not aggregated over time. * This means buckets' start and end timestamps are going to be between 'startTime' and * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the - * same as the 'uid' parameter and tag the same as 'tag' parameter. metered is going to be - * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be - * {@link NetworkStats.Bucket#ROAMING_ALL}. + * same as the 'uid' parameter and tag the same as 'tag' parameter. + * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and + * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. @@ -301,9 +305,10 @@ public class NetworkStatsManager { * metered, nor roaming. This means buckets' start and end timestamps are going to be between * 'startTime' and 'endTime' parameters. State is going to be * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary, - * tag {@link NetworkStats.Bucket#TAG_NONE}, metered is going to be - * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be - * {@link NetworkStats.Bucket#ROAMING_ALL}. + * tag {@link NetworkStats.Bucket#TAG_NONE}, + * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, + * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. From 976205c14881269026735bc46bf075dfb87b272b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sat, 20 Jan 2018 02:02:56 +0900 Subject: [PATCH 094/881] Add the defaultNetwork element to the netstats.proto. This is in its own commit because AOSP has diverged from internal master. Bug: 35142602 Test: builds, boots Change-Id: I75fc85b961bc919e3d6c2adce6d6861c6f2c8379 --- core/java/android/net/NetworkIdentity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index fd118f3401..ce2de8554d 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -130,6 +130,7 @@ public class NetworkIdentity implements Comparable { proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId); proto.write(NetworkIdentityProto.ROAMING, mRoaming); proto.write(NetworkIdentityProto.METERED, mMetered); + proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork); proto.end(start); } From 77df1d37eddb3c368c763b766aec9de170fd179a Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 18 Jan 2018 14:38:16 -0800 Subject: [PATCH 095/881] Rename create/delete transform methods CreateTransportModeTransform and DeleteTransportModeTransform are both agnostic as far as which mode of transform it creates/deletes. As such, to facilitate the implementation of tunnel mode, this patch renames them to CreateTransform and DeleteTransform, along with all test names. Bug: 63588681 Test: frameworks/base unit tests and CTS tests run, passed Change-Id: I1f015eb7ad0e85fca966658a9402485ca2b44091 --- core/java/android/net/IIpSecService.aidl | 4 ++-- core/java/android/net/IpSecTransform.java | 5 ++--- services/core/java/com/android/server/IpSecService.java | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 790c80b1d9..eeb30e23d0 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -39,9 +39,9 @@ interface IIpSecService void closeUdpEncapsulationSocket(int resourceId); - IpSecTransformResponse createTransportModeTransform(in IpSecConfig c, in IBinder binder); + IpSecTransformResponse createTransform(in IpSecConfig c, in IBinder binder); - void deleteTransportModeTransform(int transformId); + void deleteTransform(int transformId); void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 7b9b483092..794cafcf36 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -124,8 +124,7 @@ public final class IpSecTransform implements AutoCloseable { synchronized (this) { try { IIpSecService svc = getIpSecService(); - IpSecTransformResponse result = - svc.createTransportModeTransform(mConfig, new Binder()); + IpSecTransformResponse result = svc.createTransform(mConfig, new Binder()); int status = result.status; checkResultStatus(status); mResourceId = result.resourceId; @@ -170,7 +169,7 @@ public final class IpSecTransform implements AutoCloseable { * still want to clear out the transform. */ IIpSecService svc = getIpSecService(); - svc.deleteTransportModeTransform(mResourceId); + svc.deleteTransform(mResourceId); stopKeepalive(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 46a35ec800..af33ab08cb 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1105,10 +1105,10 @@ public class IpSecService extends IIpSecService.Stub { * receive data. */ @Override - public synchronized IpSecTransformResponse createTransportModeTransform( - IpSecConfig c, IBinder binder) throws RemoteException { + public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder) + throws RemoteException { checkIpSecConfig(c); - checkNotNull(binder, "Null Binder passed to createTransportModeTransform"); + checkNotNull(binder, "Null Binder passed to createTransform"); final int resourceId = mNextResourceId++; UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); @@ -1186,7 +1186,7 @@ public class IpSecService extends IIpSecService.Stub { * other reasons. */ @Override - public synchronized void deleteTransportModeTransform(int resourceId) throws RemoteException { + public synchronized void deleteTransform(int resourceId) throws RemoteException { UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); releaseResource(userRecord.mTransformRecords, resourceId); } From e7fdf8ac1a3fe64e26f565f9b4a11cb689fa036d Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sun, 21 Jan 2018 23:00:55 +0900 Subject: [PATCH 096/881] Remove obsolete NetworkStats.Entry constructor. The only caller is telephony code, and it's being fixed in this topic. Bug: 35142602 Test: builds, boots Change-Id: Ia77a1c2c297037f311c2355610c206cd8e3192c4 --- core/java/android/net/NetworkStats.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index a85f80e38d..01b2b39213 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -160,13 +160,6 @@ public class NetworkStats implements Parcelable { rxBytes, rxPackets, txBytes, txPackets, operations); } - // TODO: fix the the telephony code to pass DEFAULT_NETWORK_YES and remove this constructor. - public Entry(String iface, int uid, int set, int tag, int metered, int roaming, - long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - this(iface, uid, set, tag, metered, roaming, DEFAULT_NETWORK_YES, rxBytes, rxPackets, - txBytes, txPackets, operations); - } - public Entry(String iface, int uid, int set, int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { From 1a4a483ed6ba31a9bc57b013db52eda5d1911743 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 22 Jan 2018 11:54:46 +0900 Subject: [PATCH 097/881] Add metered, roaming, and defaultNetwork info to NetworkTemplate. This will allow data usage clients to query for and receive callbacks on data usage matching these conditions. Bug: 35142602 Test: atest FrameworksNetTests Change-Id: I4d985a2734eeab7ee454c09cc2098b6b3c671c23 --- core/java/android/net/NetworkTemplate.java | 69 +++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index b307c5d6fc..8efd39a7a7 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -24,6 +24,15 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; +import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; +import static android.net.NetworkStats.DEFAULT_NETWORK_NO; +import static android.net.NetworkStats.DEFAULT_NETWORK_YES; +import static android.net.NetworkStats.METERED_ALL; +import static android.net.NetworkStats.METERED_NO; +import static android.net.NetworkStats.METERED_YES; +import static android.net.NetworkStats.ROAMING_ALL; +import static android.net.NetworkStats.ROAMING_NO; +import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.removeDoubleQuotes; import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G; @@ -191,16 +200,30 @@ public class NetworkTemplate implements Parcelable { private final String mNetworkId; + // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. + private final int mMetered; + private final int mRoaming; + private final int mDefaultNetwork; + public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); } public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { + this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL); + } + + public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, + String networkId, int metered, int roaming, int defaultNetwork) { mMatchRule = matchRule; mSubscriberId = subscriberId; mMatchSubscriberIds = matchSubscriberIds; mNetworkId = networkId; + mMetered = metered; + mRoaming = roaming; + mDefaultNetwork = defaultNetwork; if (!isKnownMatchRule(matchRule)) { Log.e(TAG, "Unknown network template rule " + matchRule @@ -213,6 +236,9 @@ public class NetworkTemplate implements Parcelable { mSubscriberId = in.readString(); mMatchSubscriberIds = in.createStringArray(); mNetworkId = in.readString(); + mMetered = in.readInt(); + mRoaming = in.readInt(); + mDefaultNetwork = in.readInt(); } @Override @@ -221,6 +247,9 @@ public class NetworkTemplate implements Parcelable { dest.writeString(mSubscriberId); dest.writeStringArray(mMatchSubscriberIds); dest.writeString(mNetworkId); + dest.writeInt(mMetered); + dest.writeInt(mRoaming); + dest.writeInt(mDefaultNetwork); } @Override @@ -243,12 +272,23 @@ public class NetworkTemplate implements Parcelable { if (mNetworkId != null) { builder.append(", networkId=").append(mNetworkId); } + if (mMetered != METERED_ALL) { + builder.append(", metered=").append(NetworkStats.meteredToString(mMetered)); + } + if (mRoaming != ROAMING_ALL) { + builder.append(", roaming=").append(NetworkStats.roamingToString(mRoaming)); + } + if (mDefaultNetwork != DEFAULT_NETWORK_ALL) { + builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( + mDefaultNetwork)); + } return builder.toString(); } @Override public int hashCode() { - return Objects.hash(mMatchRule, mSubscriberId, mNetworkId); + return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, + mDefaultNetwork); } @Override @@ -257,7 +297,10 @@ public class NetworkTemplate implements Parcelable { final NetworkTemplate other = (NetworkTemplate) obj; return mMatchRule == other.mMatchRule && Objects.equals(mSubscriberId, other.mSubscriberId) - && Objects.equals(mNetworkId, other.mNetworkId); + && Objects.equals(mNetworkId, other.mNetworkId) + && mMetered == other.mMetered + && mRoaming == other.mRoaming + && mDefaultNetwork == other.mDefaultNetwork; } return false; } @@ -300,6 +343,10 @@ public class NetworkTemplate implements Parcelable { * Test if given {@link NetworkIdentity} matches this template. */ public boolean matches(NetworkIdentity ident) { + if (!matchesMetered(ident)) return false; + if (!matchesRoaming(ident)) return false; + if (!matchesDefaultNetwork(ident)) return false; + switch (mMatchRule) { case MATCH_MOBILE_ALL: return matchesMobile(ident); @@ -326,6 +373,24 @@ public class NetworkTemplate implements Parcelable { } } + private boolean matchesMetered(NetworkIdentity ident) { + return (mMetered == METERED_ALL) + || (mMetered == METERED_YES && ident.mMetered) + || (mMetered == METERED_NO && !ident.mMetered); + } + + private boolean matchesRoaming(NetworkIdentity ident) { + return (mRoaming == ROAMING_ALL) + || (mRoaming == ROAMING_YES && ident.mRoaming) + || (mRoaming == ROAMING_NO && !ident.mRoaming); + } + + private boolean matchesDefaultNetwork(NetworkIdentity ident) { + return (mDefaultNetwork == DEFAULT_NETWORK_ALL) + || (mDefaultNetwork == DEFAULT_NETWORK_YES && ident.mDefaultNetwork) + || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); + } + public boolean matchesSubscriberId(String subscriberId) { return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); } From 3249e27a21367a2d6f7fcf4131ca9590a47df507 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 22 Jan 2018 21:00:49 +0900 Subject: [PATCH 098/881] Support passing a template to NetworkStatsManager queries. Currently, NetworkStatsManager queries and callbacks only allow selecting network traffic based on network identifiers: networkType, subscriptionId and networkId. The code ends up converting these into a template under the hood. Now that templates can express more fine-grained queries (e.g., select only roaming traffic, or select only traffic that's not on the default network) add a hidden method to pass in a template. This should have no security implications, as all the access controls are performed in NetworkStatsService. Bug: 35142602 Test: android.app.usage.cts.NetworkUsageStatsTest passes Change-Id: Iab4afa26b34544299d2a9c501c1b0feb470e90a9 --- .../app/usage/NetworkStatsManager.java | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 90b514e272..5576e86edd 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -131,6 +131,17 @@ public class NetworkStatsManager { } } + /** @hide */ + public Bucket querySummaryForDevice(NetworkTemplate template, + long startTime, long endTime) throws SecurityException, RemoteException { + Bucket bucket = null; + NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); + bucket = stats.getDeviceSummaryForNetwork(); + + stats.close(); + return bucket; + } + /** * Query network usage statistics summaries. Result is summarised data usage for the whole * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and @@ -163,12 +174,7 @@ public class NetworkStatsManager { return null; } - Bucket bucket = null; - NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); - bucket = stats.getDeviceSummaryForNetwork(); - - stats.close(); - return bucket; + return querySummaryForDevice(template, startTime, endTime); } /** @@ -340,6 +346,37 @@ public class NetworkStatsManager { return result; } + /** @hide */ + public void registerUsageCallback(NetworkTemplate template, int networkType, + long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { + checkNotNull(callback, "UsageCallback cannot be null"); + + final Looper looper; + if (handler == null) { + looper = Looper.myLooper(); + } else { + looper = handler.getLooper(); + } + + DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, + template, thresholdBytes); + try { + CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, + template.getSubscriberId(), callback); + callback.request = mService.registerUsageCallback( + mContext.getOpPackageName(), request, new Messenger(callbackHandler), + new Binder()); + if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); + + if (callback.request == null) { + Log.e(TAG, "Request from callback is null; should not happen"); + } + } catch (RemoteException e) { + if (DBG) Log.d(TAG, "Remote exception when registering callback"); + throw e.rethrowFromSystemServer(); + } + } + /** * Registers to receive notifications about data usage on specified networks. * @@ -368,15 +405,7 @@ public class NetworkStatsManager { */ public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { - checkNotNull(callback, "UsageCallback cannot be null"); - - final Looper looper; - if (handler == null) { - looper = Looper.myLooper(); - } else { - looper = handler.getLooper(); - } - + NetworkTemplate template = createTemplate(networkType, subscriberId); if (DBG) { Log.d(TAG, "registerUsageCallback called with: {" + " networkType=" + networkType @@ -384,25 +413,7 @@ public class NetworkStatsManager { + " thresholdBytes=" + thresholdBytes + " }"); } - - NetworkTemplate template = createTemplate(networkType, subscriberId); - DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, - template, thresholdBytes); - try { - CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, - subscriberId, callback); - callback.request = mService.registerUsageCallback( - mContext.getOpPackageName(), request, new Messenger(callbackHandler), - new Binder()); - if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); - - if (callback.request == null) { - Log.e(TAG, "Request from callback is null; should not happen"); - } - } catch (RemoteException e) { - if (DBG) Log.d(TAG, "Remote exception when registering callback"); - throw e.rethrowFromSystemServer(); - } + registerUsageCallback(template, networkType, thresholdBytes, callback, handler); } /** From d220c1630445ce396b1520cc5644db52d611486f Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 13 Dec 2017 18:26:40 -0800 Subject: [PATCH 099/881] Add checks to ensure SPIs are not reused This change adds an additional check in CheckIpsecConfig to prevent users from using the same SPI twice. This allows for a more granular error message. Bug: 70642141 Test: Tests added in IpSecServiceParameterizedTest Change-Id: I9621fb05c6b162bd8ae8db4ac1e64feaa9d0ac73 --- .../java/com/android/server/IpSecService.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index ef6bc437cb..24d493e301 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -571,6 +571,8 @@ public class IpSecService extends IIpSecService.Stub { mConfig = config; mSpi = spi; mSocket = socket; + + spi.setOwnedByTransform(); } public IpSecConfig getConfig() { @@ -651,16 +653,6 @@ public class IpSecService extends IIpSecService.Stub { /** always guarded by IpSecService#this */ @Override public void freeUnderlyingResources() { - if (mOwnedByTransform) { - Log.d(TAG, "Cannot release Spi " + mSpi + ": Currently locked by a Transform"); - // Because SPIs are "handed off" to transform, objects, they should never be - // freed from the SpiRecord once used in a transform. (They refer to the same SA, - // thus ownership and responsibility for freeing these resources passes to the - // Transform object). Thus, we should let the user free them without penalty once - // they are applied in a Transform object. - return; - } - try { mSrvConfig .getNetdInstance() @@ -694,6 +686,10 @@ public class IpSecService extends IIpSecService.Stub { mOwnedByTransform = true; } + public boolean getOwnedByTransform() { + return mOwnedByTransform; + } + @Override public void invalidate() throws RemoteException { getUserRecord().removeSpiRecord(mResourceId); @@ -1107,6 +1103,11 @@ public class IpSecService extends IIpSecService.Stub { // Retrieve SPI record; will throw IllegalArgumentException if not found SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId()); + // Check to ensure that SPI has not already been used. + if (s.getOwnedByTransform()) { + throw new IllegalStateException("SPI already in use; cannot be used in new Transforms"); + } + // If no remote address is supplied, then use one from the SPI. if (TextUtils.isEmpty(config.getDestinationAddress())) { config.setDestinationAddress(s.getDestinationAddress()); From 37a880e339d6ffa4fc5df11a20c0b719e339e3ee Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Mon, 20 Nov 2017 18:23:46 -0800 Subject: [PATCH 100/881] Add BPF support for NetworkStatsService Add the native implementation for NetworkStatsService to read the uidStatsMap and tagStatsMap to get the network traffic information. Currently the implementation only try to get the data from bpf for a reference but the final value returned is still from old xt_qtaguid module. So the result will not be effected. The bpf implementation is depending on libbpf inside netd. Bug: 30950746 Test: CtsNetTestCases -t android.net.cts.TrafficStatsTest Change-Id: Ia85e4d4d602f6bd536739d89085e6dc37ad82e15 --- .../server/net/NetworkStatsService.java | 16 +++-- ...android_server_net_NetworkStatsService.cpp | 58 ++++++++++++++----- 2 files changed, 53 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 78fd4b4923..bfc150e1a9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -887,17 +887,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getUidStats(int uid, int type) { - return nativeGetUidStat(uid, type); + return nativeGetUidStat(uid, type, checkBpfStatsEnable()); } @Override public long getIfaceStats(String iface, int type) { - return nativeGetIfaceStat(iface, type); + return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); } @Override public long getTotalStats(int type) { - return nativeGetTotalStat(type); + return nativeGetTotalStat(type, checkBpfStatsEnable()); + } + + private boolean checkBpfStatsEnable() { + return new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); } /** @@ -1668,7 +1672,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static int TYPE_TCP_RX_PACKETS; private static int TYPE_TCP_TX_PACKETS; - private static native long nativeGetTotalStat(int type); - private static native long nativeGetIfaceStat(String iface, int type); - private static native long nativeGetUidStat(int uid, int type); + private static native long nativeGetTotalStat(int type, boolean useBpfStats); + private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats); + private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats); } diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 8de24e5565..3302dea535 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -29,6 +29,15 @@ #include #include +#include "android-base/unique_fd.h" +#include "bpf/BpfNetworkStats.h" +#include "bpf/BpfUtils.h" + +using android::bpf::Stats; +using android::bpf::hasBpfSupport; +using android::bpf::bpfGetUidStats; +using android::bpf::bpfGetIfaceStats; + namespace android { static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt"; @@ -46,15 +55,6 @@ enum StatsType { TCP_TX_PACKETS = 5 }; -struct Stats { - uint64_t rxBytes; - uint64_t rxPackets; - uint64_t txBytes; - uint64_t txPackets; - uint64_t tcpRxPackets; - uint64_t tcpTxPackets; -}; - static uint64_t getStatsType(struct Stats* stats, StatsType type) { switch (type) { case RX_BYTES: @@ -150,9 +150,18 @@ static int parseUidStats(const uint32_t uid, struct Stats* stats) { return 0; } -static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) { +static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) { struct Stats stats; memset(&stats, 0, sizeof(Stats)); + + if (useBpfStats) { + if (bpfGetIfaceStats(NULL, &stats) == 0) { + return getStatsType(&stats, (StatsType) type); + } else { + return UNKNOWN; + } + } + if (parseIfaceStats(NULL, &stats) == 0) { return getStatsType(&stats, (StatsType) type); } else { @@ -160,7 +169,8 @@ static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) { } } -static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) { +static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type, + jboolean useBpfStats) { ScopedUtfChars iface8(env, iface); if (iface8.c_str() == NULL) { return UNKNOWN; @@ -168,6 +178,15 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) { struct Stats stats; memset(&stats, 0, sizeof(Stats)); + + if (useBpfStats) { + if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) { + return getStatsType(&stats, (StatsType) type); + } else { + return UNKNOWN; + } + } + if (parseIfaceStats(iface8.c_str(), &stats) == 0) { return getStatsType(&stats, (StatsType) type); } else { @@ -175,9 +194,18 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) { } } -static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) { +static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) { struct Stats stats; memset(&stats, 0, sizeof(Stats)); + + if (useBpfStats) { + if (bpfGetUidStats(uid, &stats) == 0) { + return getStatsType(&stats, (StatsType) type); + } else { + return UNKNOWN; + } + } + if (parseUidStats(uid, &stats) == 0) { return getStatsType(&stats, (StatsType) type); } else { @@ -186,9 +214,9 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) { } static const JNINativeMethod gMethods[] = { - {"nativeGetTotalStat", "(I)J", (void*) getTotalStat}, - {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat}, - {"nativeGetUidStat", "(II)J", (void*) getUidStat}, + {"nativeGetTotalStat", "(IZ)J", (void*) getTotalStat}, + {"nativeGetIfaceStat", "(Ljava/lang/String;IZ)J", (void*) getIfaceStat}, + {"nativeGetUidStat", "(IIZ)J", (void*) getUidStat}, }; int register_android_server_net_NetworkStatsService(JNIEnv* env) { From 155b0b0866aaf41b1a9998f4267cd9a7bf983fae Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Mon, 20 Nov 2017 17:03:59 -0800 Subject: [PATCH 101/881] Add bpf support for NetworkStatsFactory Add the native method used to read the detail information of network stats from bpf maps. The native method of NetworkStatsFactory should choose the correct implementation to get the stats detail depending on the kernel version. Currently the bpf result is printed as a reference and the actual behavior of NetworkStatsFactory should not change. Test: NetworkStatsFactory related cts test should not fail. Bug: 30950746 Change-Id: I4715a23559b5b2306bd556cea0431f0ed172a993 --- .../internal/net/NetworkStatsFactory.java | 13 +-- ...droid_internal_net_NetworkStatsFactory.cpp | 85 +++++++++++-------- 2 files changed, 56 insertions(+), 42 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index b576a20db5..47666b57e8 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -62,6 +62,8 @@ public class NetworkStatsFactory { /** Path to {@code /proc/net/xt_qtaguid/stats}. */ private final File mStatsXtUid; + private boolean mUseBpfStats; + // TODO: to improve testability and avoid global state, do not use a static variable. @GuardedBy("sStackedIfaces") private static final ArrayMap sStackedIfaces = new ArrayMap<>(); @@ -77,14 +79,15 @@ public class NetworkStatsFactory { } public NetworkStatsFactory() { - this(new File("/proc/")); + this(new File("/proc/"), new File("/sys/fs/bpf/traffic_uid_stats_map").exists()); } @VisibleForTesting - public NetworkStatsFactory(File procRoot) { + public NetworkStatsFactory(File procRoot, boolean useBpfStats) { mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); + mUseBpfStats = useBpfStats; } /** @@ -252,7 +255,7 @@ public class NetworkStatsFactory { stats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, - limitIfaces, limitTag) != 0) { + limitIfaces, limitTag, mUseBpfStats) != 0) { throw new IOException("Failed to parse network stats"); } if (SANITY_CHECK_NATIVE) { @@ -346,6 +349,6 @@ public class NetworkStatsFactory { * are expected to monotonically increase since device boot. */ @VisibleForTesting - public static native int nativeReadNetworkStatsDetail( - NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag); + public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path, + int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats); } diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index d254de65f7..99d9839570 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -30,7 +30,14 @@ #include #include -#include + +#include "android-base/unique_fd.h" +#include "bpf/BpfNetworkStats.h" +#include "bpf/BpfUtils.h" + +using android::bpf::hasBpfSupport; +using android::bpf::parseBpfNetworkStatsDetail; +using android::bpf::stats_line; namespace android { @@ -53,17 +60,6 @@ static struct { jfieldID operations; } gNetworkStatsClassInfo; -struct stats_line { - char iface[32]; - int32_t uid; - int32_t set; - int32_t tag; - int64_t rxBytes; - int64_t rxPackets; - int64_t txBytes; - int64_t txPackets; -}; - static jobjectArray get_string_array(JNIEnv* env, jobject obj, jfieldID field, int size, bool grow) { if (!grow) { @@ -97,33 +93,14 @@ static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int s return env->NewLongArray(size); } -static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, - jstring path, jint limitUid, jobjectArray limitIfacesObj, jint limitTag) { - ScopedUtfChars path8(env, path); - if (path8.c_str() == NULL) { - return -1; - } - - FILE *fp = fopen(path8.c_str(), "r"); +static int legacyReadNetworkStatsDetail(std::vector* lines, + const std::vector& limitIfaces, + int limitTag, int limitUid, const char* path) { + FILE* fp = fopen(path, "r"); if (fp == NULL) { return -1; } - Vector limitIfaces; - if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { - int num = env->GetArrayLength(limitIfacesObj); - limitIfaces.setCapacity(num); - for (int i=0; iGetObjectArrayElement(limitIfacesObj, i); - ScopedUtfChars string8(env, string); - if (string8.c_str() != NULL) { - limitIfaces.add(String8(string8.c_str())); - } - } - } - - Vector lines; - int lastIdx = 1; int idx; char buffer[384]; @@ -215,7 +192,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, //ALOGI("skipping due to uid: %s", buffer); continue; } - lines.push_back(s); + lines->push_back(s); } else { //ALOGI("skipping due to bad remaining fields: %s", pos); } @@ -225,8 +202,42 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, ALOGE("Failed to close netstats file"); return -1; } + return 0; +} + +static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path, + jint limitUid, jobjectArray limitIfacesObj, jint limitTag, + jboolean useBpfStats) { + ScopedUtfChars path8(env, path); + if (path8.c_str() == NULL) { + return -1; + } + + std::vector limitIfaces; + if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { + int num = env->GetArrayLength(limitIfacesObj); + for (int i = 0; i < num; i++) { + jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i); + ScopedUtfChars string8(env, string); + if (string8.c_str() != NULL) { + limitIfaces.push_back(std::string(string8.c_str())); + } + } + } + std::vector lines; + + + if (useBpfStats) { + if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0) + return -1; + } else { + if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag, + limitUid, path8.c_str()) < 0) + return -1; + } int size = lines.size(); + bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity); ScopedLocalRef iface(env, get_string_array(env, stats, @@ -303,7 +314,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, static const JNINativeMethod gMethods[] = { { "nativeReadNetworkStatsDetail", - "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;I)I", + "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I", (void*) readNetworkStatsDetail } }; From e2cafb6d71c50b130d5615ebef2f0f211d4a4ddf Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Thu, 18 Jan 2018 19:48:52 -0800 Subject: [PATCH 102/881] Use /proc/net/dev to get stats summary If the qtaguid proc file is no longer exist, the device is running new eBPF module to do traffic accounting. So the NetworkStatsFactory need to use the proc/net/dev interface to get the per interface traffic stats summary. Also, adding a test to verify the helper function work properly Bug: 30950746 Test: run NetworkStatsFactoryTest Change-Id: Ia36808bf02f1637dd41a3e7c50917b91b1a77524 --- .../internal/net/NetworkStatsFactory.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 47666b57e8..902bd120e8 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -31,13 +31,17 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; +import com.google.android.collect.Lists; import libcore.io.IoUtils; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; +import java.io.FileReader; import java.io.IOException; import java.net.ProtocolException; +import java.util.ArrayList; import java.util.Objects; /** @@ -55,6 +59,8 @@ public class NetworkStatsFactory { // Used for correct stats accounting on clatd interfaces. private static final int IPV4V6_HEADER_DELTA = 20; + /** Path to {@code /proc/net/dev}. */ + private final File mStatsIfaceDev; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ private final File mStatsXtIfaceAll; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */ @@ -84,12 +90,51 @@ public class NetworkStatsFactory { @VisibleForTesting public NetworkStatsFactory(File procRoot, boolean useBpfStats) { + mStatsIfaceDev = new File(procRoot, "net/dev"); mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; } + @VisibleForTesting + public NetworkStats readNetworkStatsIfaceDev() throws IOException { + final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); + + final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); + final NetworkStats.Entry entry = new NetworkStats.Entry(); + + BufferedReader reader = null; + try { + reader = new BufferedReader(new FileReader(mStatsIfaceDev)); + + // skip first two header lines + reader.readLine(); + reader.readLine(); + + // parse remaining lines + String line; + while ((line = reader.readLine()) != null) { + String[] values = line.trim().split("\\:?\\s+"); + entry.iface = values[0]; + entry.uid = UID_ALL; + entry.set = SET_ALL; + entry.tag = TAG_NONE; + entry.rxBytes = Long.parseLong(values[1]); + entry.rxPackets = Long.parseLong(values[2]); + entry.txBytes = Long.parseLong(values[9]); + entry.txPackets = Long.parseLong(values[10]); + stats.addValues(entry); + } + } catch (NullPointerException|NumberFormatException e) { + throw new ProtocolException("problem parsing stats", e); + } finally { + IoUtils.closeQuietly(reader); + StrictMode.setThreadPolicy(savedPolicy); + } + return stats; + } + /** * Parse and return interface-level summary {@link NetworkStats} measured * using {@code /proc/net/dev} style hooks, which may include non IP layer @@ -99,6 +144,11 @@ public class NetworkStatsFactory { * @throws IllegalStateException when problem parsing stats. */ public NetworkStats readNetworkStatsSummaryDev() throws IOException { + + // Return the stats get from /proc/net/dev if switched to bpf module. + if (mUseBpfStats) + return readNetworkStatsIfaceDev(); + final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); @@ -150,6 +200,11 @@ public class NetworkStatsFactory { * @throws IllegalStateException when problem parsing stats. */ public NetworkStats readNetworkStatsSummaryXt() throws IOException { + + // Return the stats get from /proc/net/dev if qtaguid module is replaced. + if (mUseBpfStats) + return readNetworkStatsIfaceDev(); + final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); // return null when kernel doesn't support From bbe19ecf9aa240bfd2ecf51c8025992d2751c855 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 01:12:58 +0900 Subject: [PATCH 103/881] Add getDefaultNetwork to the NetworkStats public API. This allows an app using the public API to know whether the traffic in a particular bucket was on the default network (i.e., the network was selected by the system), or not (i.e., the network was selected by the app). Bug: 35142602 Test: builds, boots Test: added coverage to NetworkUsageStatsTest CTS test, still passes Change-Id: I9f6669908fa119743b9c0aa0c31a03e5ebafa7db Merged-In: I9f6669908fa119743b9c0aa0c31a03e5ebafa7db --- core/java/android/app/usage/NetworkStats.java | 52 +++++++++++++++++++ .../app/usage/NetworkStatsManager.java | 35 +++++++------ 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 222e9a0e5e..d33af4faeb 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -215,6 +215,30 @@ public final class NetworkStats implements AutoCloseable { */ public static final int ROAMING_YES = 0x2; + /** @hide */ + @IntDef(prefix = { "DEFAULT_NETWORK_" }, value = { + DEFAULT_NETWORK_ALL, + DEFAULT_NETWORK_NO, + DEFAULT_NETWORK_YES + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DefaultNetwork {} + + /** + * Combined usage for this network regardless of whether it was the active default network. + */ + public static final int DEFAULT_NETWORK_ALL = -1; + + /** + * Usage that occurs while this network is not the active default network. + */ + public static final int DEFAULT_NETWORK_NO = 0x1; + + /** + * Usage that occurs while this network is the active default network. + */ + public static final int DEFAULT_NETWORK_YES = 0x2; + /** * Special TAG value for total data across all tags */ @@ -223,6 +247,7 @@ public final class NetworkStats implements AutoCloseable { private int mUid; private int mTag; private int mState; + private int mDefaultNetwork; private int mMetered; private int mRoaming; private long mBeginTimeStamp; @@ -274,6 +299,15 @@ public final class NetworkStats implements AutoCloseable { return 0; } + private static @DefaultNetwork int convertDefaultNetwork(int defaultNetwork) { + switch (defaultNetwork) { + case android.net.NetworkStats.DEFAULT_NETWORK_ALL : return DEFAULT_NETWORK_ALL; + case android.net.NetworkStats.DEFAULT_NETWORK_NO: return DEFAULT_NETWORK_NO; + case android.net.NetworkStats.DEFAULT_NETWORK_YES: return DEFAULT_NETWORK_YES; + } + return 0; + } + public Bucket() { } @@ -338,6 +372,21 @@ public final class NetworkStats implements AutoCloseable { return mRoaming; } + /** + * Default network state. One of the following values:

+ *

    + *
  • {@link #DEFAULT_NETWORK_ALL}
  • + *
  • {@link #DEFAULT_NETWORK_NO}
  • + *
  • {@link #DEFAULT_NETWORK_YES}
  • + *
+ *

Indicates whether the network usage occurred on the system default network for this + * type of traffic, or whether the application chose to send this traffic on a network that + * was not the one selected by the system. + */ + public @DefaultNetwork int getDefaultNetwork() { + return mDefaultNetwork; + } + /** * Start timestamp of the bucket's time interval. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. @@ -539,6 +588,8 @@ public final class NetworkStats implements AutoCloseable { bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid); bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag); bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set); + bucketOut.mDefaultNetwork = Bucket.convertDefaultNetwork( + mRecycledSummaryEntry.defaultNetwork); bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered); bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming); bucketOut.mBeginTimeStamp = mStartTimeStamp; @@ -588,6 +639,7 @@ public final class NetworkStats implements AutoCloseable { bucketOut.mUid = Bucket.convertUid(getUid()); bucketOut.mTag = Bucket.convertTag(mTag); bucketOut.mState = Bucket.STATE_ALL; + bucketOut.mDefaultNetwork = Bucket.DEFAULT_NETWORK_ALL; bucketOut.mMetered = Bucket.METERED_ALL; bucketOut.mRoaming = Bucket.ROAMING_ALL; bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart; diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 853b00331a..90b514e272 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -60,10 +60,11 @@ import android.util.Log; * {@link #queryDetailsForUid}

* {@link #queryDetails}

* These queries do not aggregate over time but do aggregate over state, metered and roaming. - * Therefore there can be multiple buckets for a particular key but all Bucket's state is going to - * be {@link NetworkStats.Bucket#STATE_ALL}, all Bucket's metered is going to be - * {@link NetworkStats.Bucket#METERED_ALL}, and all Bucket's roaming is going to be - * {@link NetworkStats.Bucket#ROAMING_ALL}. + * Therefore there can be multiple buckets for a particular key. However, all Buckets will have + * {@code state} {@link NetworkStats.Bucket#STATE_ALL}, + * {@code defaultNetwork} {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * {@code metered } {@link NetworkStats.Bucket#METERED_ALL}, + * {@code roaming} {@link NetworkStats.Bucket#ROAMING_ALL}. *

* NOTE: Calling {@link #querySummaryForDevice} or accessing stats for apps other than the * calling app requires the permission {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, @@ -136,7 +137,9 @@ public class NetworkStatsManager { * roaming. This means the bucket's start and end timestamp are going to be the same as the * 'startTime' and 'endTime' parameters. State is going to be * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL}, - * tag {@link NetworkStats.Bucket#TAG_NONE}, metered {@link NetworkStats.Bucket#METERED_ALL}, + * tag {@link NetworkStats.Bucket#TAG_NONE}, + * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered {@link NetworkStats.Bucket#METERED_ALL}, * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. * * @param networkType As defined in {@link ConnectivityManager}, e.g. @@ -209,10 +212,10 @@ public class NetworkStatsManager { /** * Query network usage statistics summaries. Result filtered to include only uids belonging to * calling user. Result is aggregated over time, hence all buckets will have the same start and - * end timestamps. Not aggregated over state, uid, metered, or roaming. This means buckets' - * start and end timestamps are going to be the same as the 'startTime' and 'endTime' - * parameters. State, uid, metered, and roaming are going to vary, and tag is going to be the - * same. + * end timestamps. Not aggregated over state, uid, default network, metered, or roaming. This + * means buckets' start and end timestamps are going to be the same as the 'startTime' and + * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to + * be the same. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -258,9 +261,10 @@ public class NetworkStatsManager { * belonging to calling user. Result is aggregated over state but not aggregated over time. * This means buckets' start and end timestamps are going to be between 'startTime' and * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the - * same as the 'uid' parameter and tag the same as 'tag' parameter. metered is going to be - * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be - * {@link NetworkStats.Bucket#ROAMING_ALL}. + * same as the 'uid' parameter and tag the same as 'tag' parameter. + * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and + * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. @@ -301,9 +305,10 @@ public class NetworkStatsManager { * metered, nor roaming. This means buckets' start and end timestamps are going to be between * 'startTime' and 'endTime' parameters. State is going to be * {@link NetworkStats.Bucket#STATE_ALL}, uid will vary, - * tag {@link NetworkStats.Bucket#TAG_NONE}, metered is going to be - * {@link NetworkStats.Bucket#METERED_ALL}, and roaming is going to be - * {@link NetworkStats.Bucket#ROAMING_ALL}. + * tag {@link NetworkStats.Bucket#TAG_NONE}, + * default network is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, + * and roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. From 3729a8dd4c7bd4b5fca20cf633e2916294c9c05d Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 22 Jan 2018 21:00:49 +0900 Subject: [PATCH 104/881] Support passing a template to NetworkStatsManager queries. Currently, NetworkStatsManager queries and callbacks only allow selecting network traffic based on network identifiers: networkType, subscriptionId and networkId. The code ends up converting these into a template under the hood. Now that templates can express more fine-grained queries (e.g., select only roaming traffic, or select only traffic that's not on the default network) add a hidden method to pass in a template. This should have no security implications, as all the access controls are performed in NetworkStatsService. Bug: 35142602 Test: android.app.usage.cts.NetworkUsageStatsTest passes Change-Id: Iab4afa26b34544299d2a9c501c1b0feb470e90a9 Merged-In: Iab4afa26b34544299d2a9c501c1b0feb470e90a9 --- .../app/usage/NetworkStatsManager.java | 79 +++++++++++-------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 90b514e272..5576e86edd 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -131,6 +131,17 @@ public class NetworkStatsManager { } } + /** @hide */ + public Bucket querySummaryForDevice(NetworkTemplate template, + long startTime, long endTime) throws SecurityException, RemoteException { + Bucket bucket = null; + NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); + bucket = stats.getDeviceSummaryForNetwork(); + + stats.close(); + return bucket; + } + /** * Query network usage statistics summaries. Result is summarised data usage for the whole * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and @@ -163,12 +174,7 @@ public class NetworkStatsManager { return null; } - Bucket bucket = null; - NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); - bucket = stats.getDeviceSummaryForNetwork(); - - stats.close(); - return bucket; + return querySummaryForDevice(template, startTime, endTime); } /** @@ -340,6 +346,37 @@ public class NetworkStatsManager { return result; } + /** @hide */ + public void registerUsageCallback(NetworkTemplate template, int networkType, + long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { + checkNotNull(callback, "UsageCallback cannot be null"); + + final Looper looper; + if (handler == null) { + looper = Looper.myLooper(); + } else { + looper = handler.getLooper(); + } + + DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, + template, thresholdBytes); + try { + CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, + template.getSubscriberId(), callback); + callback.request = mService.registerUsageCallback( + mContext.getOpPackageName(), request, new Messenger(callbackHandler), + new Binder()); + if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); + + if (callback.request == null) { + Log.e(TAG, "Request from callback is null; should not happen"); + } + } catch (RemoteException e) { + if (DBG) Log.d(TAG, "Remote exception when registering callback"); + throw e.rethrowFromSystemServer(); + } + } + /** * Registers to receive notifications about data usage on specified networks. * @@ -368,15 +405,7 @@ public class NetworkStatsManager { */ public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { - checkNotNull(callback, "UsageCallback cannot be null"); - - final Looper looper; - if (handler == null) { - looper = Looper.myLooper(); - } else { - looper = handler.getLooper(); - } - + NetworkTemplate template = createTemplate(networkType, subscriberId); if (DBG) { Log.d(TAG, "registerUsageCallback called with: {" + " networkType=" + networkType @@ -384,25 +413,7 @@ public class NetworkStatsManager { + " thresholdBytes=" + thresholdBytes + " }"); } - - NetworkTemplate template = createTemplate(networkType, subscriberId); - DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, - template, thresholdBytes); - try { - CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, - subscriberId, callback); - callback.request = mService.registerUsageCallback( - mContext.getOpPackageName(), request, new Messenger(callbackHandler), - new Binder()); - if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); - - if (callback.request == null) { - Log.e(TAG, "Request from callback is null; should not happen"); - } - } catch (RemoteException e) { - if (DBG) Log.d(TAG, "Remote exception when registering callback"); - throw e.rethrowFromSystemServer(); - } + registerUsageCallback(template, networkType, thresholdBytes, callback, handler); } /** From 1b0d4fd42b67af6bbb286cd8580f8a8546b99804 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sat, 20 Jan 2018 02:02:56 +0900 Subject: [PATCH 105/881] Add the defaultNetwork element to the netstats.proto. This is in its own commit because AOSP has diverged from internal master. Bug: 35142602 Test: builds, boots Change-Id: I75fc85b961bc919e3d6c2adce6d6861c6f2c8379 Merged-In: I75fc85b961bc919e3d6c2adce6d6861c6f2c8379 --- core/java/android/net/NetworkIdentity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index fd118f3401..ce2de8554d 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -130,6 +130,7 @@ public class NetworkIdentity implements Comparable { proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId); proto.write(NetworkIdentityProto.ROAMING, mRoaming); proto.write(NetworkIdentityProto.METERED, mMetered); + proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork); proto.end(start); } From 8afb8fb55da885a776d9bfcdb1c57823b0dc959b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 22 Jan 2018 11:54:46 +0900 Subject: [PATCH 106/881] Add metered, roaming, and defaultNetwork info to NetworkTemplate. This will allow data usage clients to query for and receive callbacks on data usage matching these conditions. Bug: 35142602 Test: atest FrameworksNetTests Change-Id: I4d985a2734eeab7ee454c09cc2098b6b3c671c23 Merged-In: I4d985a2734eeab7ee454c09cc2098b6b3c671c23 --- core/java/android/net/NetworkTemplate.java | 69 +++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index b307c5d6fc..8efd39a7a7 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -24,6 +24,15 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; +import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; +import static android.net.NetworkStats.DEFAULT_NETWORK_NO; +import static android.net.NetworkStats.DEFAULT_NETWORK_YES; +import static android.net.NetworkStats.METERED_ALL; +import static android.net.NetworkStats.METERED_NO; +import static android.net.NetworkStats.METERED_YES; +import static android.net.NetworkStats.ROAMING_ALL; +import static android.net.NetworkStats.ROAMING_NO; +import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.removeDoubleQuotes; import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G; import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G; @@ -191,16 +200,30 @@ public class NetworkTemplate implements Parcelable { private final String mNetworkId; + // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. + private final int mMetered; + private final int mRoaming; + private final int mDefaultNetwork; + public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); } public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { + this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL); + } + + public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, + String networkId, int metered, int roaming, int defaultNetwork) { mMatchRule = matchRule; mSubscriberId = subscriberId; mMatchSubscriberIds = matchSubscriberIds; mNetworkId = networkId; + mMetered = metered; + mRoaming = roaming; + mDefaultNetwork = defaultNetwork; if (!isKnownMatchRule(matchRule)) { Log.e(TAG, "Unknown network template rule " + matchRule @@ -213,6 +236,9 @@ public class NetworkTemplate implements Parcelable { mSubscriberId = in.readString(); mMatchSubscriberIds = in.createStringArray(); mNetworkId = in.readString(); + mMetered = in.readInt(); + mRoaming = in.readInt(); + mDefaultNetwork = in.readInt(); } @Override @@ -221,6 +247,9 @@ public class NetworkTemplate implements Parcelable { dest.writeString(mSubscriberId); dest.writeStringArray(mMatchSubscriberIds); dest.writeString(mNetworkId); + dest.writeInt(mMetered); + dest.writeInt(mRoaming); + dest.writeInt(mDefaultNetwork); } @Override @@ -243,12 +272,23 @@ public class NetworkTemplate implements Parcelable { if (mNetworkId != null) { builder.append(", networkId=").append(mNetworkId); } + if (mMetered != METERED_ALL) { + builder.append(", metered=").append(NetworkStats.meteredToString(mMetered)); + } + if (mRoaming != ROAMING_ALL) { + builder.append(", roaming=").append(NetworkStats.roamingToString(mRoaming)); + } + if (mDefaultNetwork != DEFAULT_NETWORK_ALL) { + builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( + mDefaultNetwork)); + } return builder.toString(); } @Override public int hashCode() { - return Objects.hash(mMatchRule, mSubscriberId, mNetworkId); + return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, + mDefaultNetwork); } @Override @@ -257,7 +297,10 @@ public class NetworkTemplate implements Parcelable { final NetworkTemplate other = (NetworkTemplate) obj; return mMatchRule == other.mMatchRule && Objects.equals(mSubscriberId, other.mSubscriberId) - && Objects.equals(mNetworkId, other.mNetworkId); + && Objects.equals(mNetworkId, other.mNetworkId) + && mMetered == other.mMetered + && mRoaming == other.mRoaming + && mDefaultNetwork == other.mDefaultNetwork; } return false; } @@ -300,6 +343,10 @@ public class NetworkTemplate implements Parcelable { * Test if given {@link NetworkIdentity} matches this template. */ public boolean matches(NetworkIdentity ident) { + if (!matchesMetered(ident)) return false; + if (!matchesRoaming(ident)) return false; + if (!matchesDefaultNetwork(ident)) return false; + switch (mMatchRule) { case MATCH_MOBILE_ALL: return matchesMobile(ident); @@ -326,6 +373,24 @@ public class NetworkTemplate implements Parcelable { } } + private boolean matchesMetered(NetworkIdentity ident) { + return (mMetered == METERED_ALL) + || (mMetered == METERED_YES && ident.mMetered) + || (mMetered == METERED_NO && !ident.mMetered); + } + + private boolean matchesRoaming(NetworkIdentity ident) { + return (mRoaming == ROAMING_ALL) + || (mRoaming == ROAMING_YES && ident.mRoaming) + || (mRoaming == ROAMING_NO && !ident.mRoaming); + } + + private boolean matchesDefaultNetwork(NetworkIdentity ident) { + return (mDefaultNetwork == DEFAULT_NETWORK_ALL) + || (mDefaultNetwork == DEFAULT_NETWORK_YES && ident.mDefaultNetwork) + || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); + } + public boolean matchesSubscriberId(String subscriberId) { return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); } From 7377b3cac71d0da75c5ee965f4c9b7d7d2df3b1a Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 23 Jan 2018 11:01:28 -0800 Subject: [PATCH 107/881] Expose applyTunnelModeTransform as a system API Simple change to expose systemAPI for applyTunnelModeTransform Bug: 36033193 Test: All CTS, unit tests passing Change-Id: I2d857c048bc0dc80c3949387f946b1f5adf0527e --- core/java/android/net/IpSecManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index f04f03f6b6..6125394ab5 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -748,7 +748,7 @@ public final class IpSecManager { * @hide */ @SystemApi - void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction, + public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction, IpSecTransform transform) throws IOException { // TODO: call IpSecService } From 79d011823be02a063f3181deb819e24ce53ff458 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 18 Jan 2018 18:31:45 -0800 Subject: [PATCH 108/881] Add TunnelInterface API and KernelResourceRecords This change adds one KernelResourceRecord type (TunnelInterfaceRecord), and adds methods for the creation of TunnelInterfaces, as well as the application of Transforms to the given TunnelInterfaces As part of the generation of ikeys/okeys, a ReserveKeyTracker manages a java bitset to avoid collisions and reserve/release keys. Bug: 63588681 Test: Compiles, CTS, unit tests all pass on AOSP_marlin Change-Id: I9e9b6455e27073acd4491eae666aa966b3b10e0f --- core/java/android/net/IIpSecService.aidl | 19 ++ core/java/android/net/IpSecManager.java | 53 +++- .../net/IpSecTunnelInterfaceResponse.aidl | 20 ++ .../net/IpSecTunnelInterfaceResponse.java | 78 +++++ .../java/com/android/server/IpSecService.java | 284 ++++++++++++++++++ 5 files changed, 446 insertions(+), 8 deletions(-) create mode 100644 core/java/android/net/IpSecTunnelInterfaceResponse.aidl create mode 100644 core/java/android/net/IpSecTunnelInterfaceResponse.java diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index eeb30e23d0..3ce0283d7f 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -21,6 +21,7 @@ import android.net.IpSecConfig; import android.net.IpSecUdpEncapResponse; import android.net.IpSecSpiResponse; import android.net.IpSecTransformResponse; +import android.net.IpSecTunnelInterfaceResponse; import android.os.Bundle; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -39,11 +40,29 @@ interface IIpSecService void closeUdpEncapsulationSocket(int resourceId); + IpSecTunnelInterfaceResponse createTunnelInterface( + in String localAddr, + in String remoteAddr, + in Network underlyingNetwork, + in IBinder binder); + + void addAddressToTunnelInterface( + int tunnelResourceId, + String localAddr); + + void removeAddressFromTunnelInterface( + int tunnelResourceId, + String localAddr); + + void deleteTunnelInterface(int resourceId); + IpSecTransformResponse createTransform(in IpSecConfig c, in IBinder binder); void deleteTransform(int transformId); void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); + void applyTunnelModeTransform(int tunnelResourceId, int direction, int transformResourceId); + void removeTransportModeTransforms(in ParcelFileDescriptor socket); } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 6125394ab5..24a078fccc 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -685,7 +685,30 @@ public final class IpSecManager { mLocalAddress = localAddress; mRemoteAddress = remoteAddress; mUnderlyingNetwork = underlyingNetwork; - // TODO: Call IpSecService + + try { + IpSecTunnelInterfaceResponse result = + mService.createTunnelInterface( + localAddress.getHostAddress(), + remoteAddress.getHostAddress(), + underlyingNetwork, + new Binder()); + switch (result.status) { + case Status.OK: + break; + case Status.RESOURCE_UNAVAILABLE: + throw new ResourceUnavailableException( + "No more tunnel interfaces may be allocated by this requester."); + default: + throw new RuntimeException( + "Unknown status returned by IpSecService: " + result.status); + } + mResourceId = result.resourceId; + mInterfaceName = result.interfaceName; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + mCloseGuard.open("constructor"); } /** @@ -697,12 +720,12 @@ public final class IpSecManager { */ @Override public void close() { - // try { - // TODO: Call IpSecService - mResourceId = INVALID_RESOURCE_ID; - // } catch (RemoteException e) { - // throw e.rethrowFromSystemServer(); - // } + try { + mService.deleteTunnelInterface(mResourceId); + mResourceId = INVALID_RESOURCE_ID; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } mCloseGuard.close(); } @@ -714,11 +737,20 @@ public final class IpSecManager { } close(); } + + /** @hide */ + @VisibleForTesting + public int getResourceId() { + return mResourceId; + } } /** * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. * + *

An application that creates tunnels is responsible for cleaning up the tunnel when the + * underlying network goes away, and the onLost() callback is received. + * * @param localAddress The local addres of the tunnel * @param remoteAddress The local addres of the tunnel * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. @@ -750,7 +782,12 @@ public final class IpSecManager { @SystemApi public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction, IpSecTransform transform) throws IOException { - // TODO: call IpSecService + try { + mService.applyTunnelModeTransform( + tunnel.getResourceId(), direction, transform.getResourceId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** * Construct an instance of IpSecManager within an application context. diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.aidl b/core/java/android/net/IpSecTunnelInterfaceResponse.aidl new file mode 100644 index 0000000000..7239221415 --- /dev/null +++ b/core/java/android/net/IpSecTunnelInterfaceResponse.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +parcelable IpSecTunnelInterfaceResponse; diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/core/java/android/net/IpSecTunnelInterfaceResponse.java new file mode 100644 index 0000000000..c23d831a44 --- /dev/null +++ b/core/java/android/net/IpSecTunnelInterfaceResponse.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.net; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * This class is used to return an IpSecTunnelInterface resource Id and and corresponding status + * from the IpSecService to an IpSecTunnelInterface object. + * + * @hide + */ +public final class IpSecTunnelInterfaceResponse implements Parcelable { + private static final String TAG = "IpSecTunnelInterfaceResponse"; + + public final int resourceId; + public final String interfaceName; + public final int status; + // Parcelable Methods + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(status); + out.writeInt(resourceId); + out.writeString(interfaceName); + } + + public IpSecTunnelInterfaceResponse(int inStatus) { + if (inStatus == IpSecManager.Status.OK) { + throw new IllegalArgumentException("Valid status implies other args must be provided"); + } + status = inStatus; + resourceId = IpSecManager.INVALID_RESOURCE_ID; + interfaceName = ""; + } + + public IpSecTunnelInterfaceResponse(int inStatus, int inResourceId, String inInterfaceName) { + status = inStatus; + resourceId = inResourceId; + interfaceName = inInterfaceName; + } + + private IpSecTunnelInterfaceResponse(Parcel in) { + status = in.readInt(); + resourceId = in.readInt(); + interfaceName = in.readString(); + } + + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) { + return new IpSecTunnelInterfaceResponse(in); + } + + public IpSecTunnelInterfaceResponse[] newArray(int size) { + return new IpSecTunnelInterfaceResponse[size]; + } + }; +} diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index a9a81089fc..c2adbfaeb7 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -34,7 +34,9 @@ import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecTransform; import android.net.IpSecTransformResponse; +import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; +import android.net.Network; import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; @@ -50,6 +52,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -62,6 +65,7 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; import libcore.io.IoUtils; @@ -99,6 +103,7 @@ public class IpSecService extends IIpSecService.Stub { static final int FREE_PORT_MIN = 1024; // ports 1-1023 are reserved static final int PORT_MAX = 0xFFFF; // ports are an unsigned 16-bit integer + static final String TUNNEL_INTERFACE_PREFIX = "ipsec"; /* Binder context for this service */ private final Context mContext; @@ -347,6 +352,7 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting static final class UserRecord { /* Maximum number of each type of resource that a single UID may possess */ + public static final int MAX_NUM_TUNNEL_INTERFACES = 2; public static final int MAX_NUM_ENCAP_SOCKETS = 2; public static final int MAX_NUM_TRANSFORMS = 4; public static final int MAX_NUM_SPIS = 8; @@ -366,6 +372,8 @@ public class IpSecService extends IIpSecService.Stub { new RefcountedResourceArray<>(TransformRecord.class.getSimpleName()); final RefcountedResourceArray mEncapSocketRecords = new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName()); + final RefcountedResourceArray mTunnelInterfaceRecords = + new RefcountedResourceArray<>(TunnelInterfaceRecord.class.getSimpleName()); /** * Trackers for quotas for each of the OwnedResource types. @@ -379,6 +387,7 @@ public class IpSecService extends IIpSecService.Stub { final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS); final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS); final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); + final ResourceTracker mTunnelQuotaTracker = new ResourceTracker(MAX_NUM_TUNNEL_INTERFACES); void removeSpiRecord(int resourceId) { mSpiRecords.remove(resourceId); @@ -388,6 +397,10 @@ public class IpSecService extends IIpSecService.Stub { mTransformRecords.remove(resourceId); } + void removeTunnelInterfaceRecord(int resourceId) { + mTunnelInterfaceRecords.remove(resourceId); + } + void removeEncapSocketRecord(int resourceId) { mEncapSocketRecords.remove(resourceId); } @@ -721,6 +734,145 @@ public class IpSecService extends IIpSecService.Stub { } } + // These values have been reserved in ConnectivityService + @VisibleForTesting static final int TUN_INTF_NETID_START = 0xFC00; + + @VisibleForTesting static final int TUN_INTF_NETID_RANGE = 0x0400; + + private final SparseBooleanArray mTunnelNetIds = new SparseBooleanArray(); + private int mNextTunnelNetIdIndex = 0; + + /** + * Reserves a netId within the range of netIds allocated for IPsec tunnel interfaces + * + *

This method should only be called from Binder threads. Do not call this from within the + * system server as it will crash the system on failure. + * + * @return an integer key within the netId range, if successful + * @throws IllegalStateException if unsuccessful (all netId are currently reserved) + */ + @VisibleForTesting + int reserveNetId() { + synchronized (mTunnelNetIds) { + for (int i = 0; i < TUN_INTF_NETID_RANGE; i++) { + int index = mNextTunnelNetIdIndex; + int netId = index + TUN_INTF_NETID_START; + if (++mNextTunnelNetIdIndex >= TUN_INTF_NETID_RANGE) mNextTunnelNetIdIndex = 0; + if (!mTunnelNetIds.get(netId)) { + mTunnelNetIds.put(netId, true); + return netId; + } + } + } + throw new IllegalStateException("No free netIds to allocate"); + } + + @VisibleForTesting + void releaseNetId(int netId) { + synchronized (mTunnelNetIds) { + mTunnelNetIds.delete(netId); + } + } + + private final class TunnelInterfaceRecord extends OwnedResourceRecord { + private final String mInterfaceName; + private final Network mUnderlyingNetwork; + + // outer addresses + private final String mLocalAddress; + private final String mRemoteAddress; + + private final int mIkey; + private final int mOkey; + + TunnelInterfaceRecord( + int resourceId, + String interfaceName, + Network underlyingNetwork, + String localAddr, + String remoteAddr, + int ikey, + int okey) { + super(resourceId); + + mInterfaceName = interfaceName; + mUnderlyingNetwork = underlyingNetwork; + mLocalAddress = localAddr; + mRemoteAddress = remoteAddr; + mIkey = ikey; + mOkey = okey; + } + + /** always guarded by IpSecService#this */ + @Override + public void freeUnderlyingResources() { + // TODO: Add calls to netd + // Teardown VTI + // Delete global policies + + getResourceTracker().give(); + releaseNetId(mIkey); + releaseNetId(mOkey); + } + + public String getInterfaceName() { + return mInterfaceName; + } + + public Network getUnderlyingNetwork() { + return mUnderlyingNetwork; + } + + /** Returns the local, outer address for the tunnelInterface */ + public String getLocalAddress() { + return mLocalAddress; + } + + /** Returns the remote, outer address for the tunnelInterface */ + public String getRemoteAddress() { + return mRemoteAddress; + } + + public int getIkey() { + return mIkey; + } + + public int getOkey() { + return mOkey; + } + + @Override + protected ResourceTracker getResourceTracker() { + return getUserRecord().mTunnelQuotaTracker; + } + + @Override + public void invalidate() { + getUserRecord().removeTunnelInterfaceRecord(mResourceId); + } + + @Override + public String toString() { + return new StringBuilder() + .append("{super=") + .append(super.toString()) + .append(", mInterfaceName=") + .append(mInterfaceName) + .append(", mUnderlyingNetwork=") + .append(mUnderlyingNetwork) + .append(", mLocalAddress=") + .append(mLocalAddress) + .append(", mRemoteAddress=") + .append(mRemoteAddress) + .append(", mIkey=") + .append(mIkey) + .append(", mOkey=") + .append(mOkey) + .append("}") + .toString(); + } + } + /** * Tracks a UDP encap socket, and manages cleanup paths * @@ -1051,6 +1203,97 @@ public class IpSecService extends IIpSecService.Stub { releaseResource(userRecord.mEncapSocketRecords, resourceId); } + /** + * Create a tunnel interface for use in IPSec tunnel mode. The system server will cache the + * tunnel interface and a record of its owner so that it can and must be freed when no longer + * needed. + */ + @Override + public synchronized IpSecTunnelInterfaceResponse createTunnelInterface( + String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder) { + checkNotNull(binder, "Null Binder passed to createTunnelInterface"); + checkNotNull(underlyingNetwork, "No underlying network was specified"); + checkInetAddress(localAddr); + checkInetAddress(remoteAddr); + + // TODO: Check that underlying network exists, and IP addresses not assigned to a different + // network (b/72316676). + + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + if (!userRecord.mTunnelQuotaTracker.isAvailable()) { + return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); + } + + final int resourceId = mNextResourceId++; + final int ikey = reserveNetId(); + final int okey = reserveNetId(); + String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId); + + // TODO: Add calls to netd: + // Create VTI + // Add inbound/outbound global policies + // (use reqid = 0) + + userRecord.mTunnelInterfaceRecords.put( + resourceId, + new RefcountedResource( + new TunnelInterfaceRecord( + resourceId, + intfName, + underlyingNetwork, + localAddr, + remoteAddr, + ikey, + okey), + binder)); + return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); + } + + /** + * Adds a new local address to the tunnel interface. This allows packets to be sent and received + * from multiple local IP addresses over the same tunnel. + */ + @Override + public synchronized void addAddressToTunnelInterface(int tunnelResourceId, String localAddr) { + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + + // Get tunnelInterface record; if no such interface is found, will throw + // IllegalArgumentException + TunnelInterfaceRecord tunnelInterfaceInfo = + userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); + + // TODO: Add calls to netd: + // Add address to TunnelInterface + } + + /** + * Remove a new local address from the tunnel interface. After removal, the address will no + * longer be available to send from, or receive on. + */ + @Override + public synchronized void removeAddressFromTunnelInterface( + int tunnelResourceId, String localAddr) { + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + + // Get tunnelInterface record; if no such interface is found, will throw + // IllegalArgumentException + TunnelInterfaceRecord tunnelInterfaceInfo = + userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); + + // TODO: Add calls to netd: + // Remove address from TunnelInterface + } + + /** + * Delete a TunnelInterface that has been been allocated by and registered with the system + * server + */ + @Override + public synchronized void deleteTunnelInterface(int resourceId) throws RemoteException { + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + releaseResource(userRecord.mTunnelInterfaceRecords, resourceId); + } + @VisibleForTesting void validateAlgorithms(IpSecConfig config) throws IllegalArgumentException { IpSecAlgorithm auth = config.getAuthentication(); @@ -1249,7 +1492,12 @@ public class IpSecService extends IIpSecService.Stub { throw new SecurityException("Only the owner of an IpSec Transform may apply it!"); } + // Get config and check that to-be-applied transform has the correct mode IpSecConfig c = info.getConfig(); + Preconditions.checkArgument( + c.getMode() == IpSecTransform.MODE_TRANSPORT, + "Transform mode was not Transport mode; cannot be applied to a socket"); + try { mSrvConfig .getNetdInstance() @@ -1287,6 +1535,42 @@ public class IpSecService extends IIpSecService.Stub { } } + /** + * Apply an active tunnel mode transform to a TunnelInterface, which will apply the IPsec + * security association as a correspondent policy to the provided interface + */ + @Override + public synchronized void applyTunnelModeTransform( + int tunnelResourceId, int direction, int transformResourceId) throws RemoteException { + checkDirection(direction); + + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + + // Get transform record; if no transform is found, will throw IllegalArgumentException + TransformRecord transformInfo = + userRecord.mTransformRecords.getResourceOrThrow(transformResourceId); + + // Get tunnelInterface record; if no such interface is found, will throw + // IllegalArgumentException + TunnelInterfaceRecord tunnelInterfaceInfo = + userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); + + // Get config and check that to-be-applied transform has the correct mode + IpSecConfig c = transformInfo.getConfig(); + Preconditions.checkArgument( + c.getMode() == IpSecTransform.MODE_TUNNEL, + "Transform mode was not Tunnel mode; cannot be applied to a tunnel interface"); + + int mark = + (direction == IpSecManager.DIRECTION_IN) + ? tunnelInterfaceInfo.getIkey() + : tunnelInterfaceInfo.getOkey(); + + // TODO: Add calls to netd: + // Update SA with tunnel mark (ikey or okey based on direction) + // If outbound, add SPI to policy + } + @Override protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); From 779eedf6e0bb0ba18c50adc8a9b6edf37da03f1b Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Fri, 19 Jan 2018 17:36:02 -0800 Subject: [PATCH 109/881] Add tunnel-mode calls to netd in IpSecService Adds calls to relevant netd methods in IpSecService, enabling Tunnel mode functionality. Bug: 63588681 Test: Compiles, passing CTS + unit tests Change-Id: I6deb68584cddb03f21bd76370d4ef69cadc1bf16 --- .../java/com/android/server/IpSecService.java | 220 +++++++++++++----- 1 file changed, 159 insertions(+), 61 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index c2adbfaeb7..fe4ac6d771 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -65,7 +65,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.BitSet; import java.util.List; import libcore.io.IoUtils; @@ -596,6 +595,10 @@ public class IpSecService extends IIpSecService.Stub { return mSpi; } + public EncapSocketRecord getSocketRecord() { + return mSocket; + } + /** always guarded by IpSecService#this */ @Override public void freeUnderlyingResources() { @@ -806,9 +809,29 @@ public class IpSecService extends IIpSecService.Stub { /** always guarded by IpSecService#this */ @Override public void freeUnderlyingResources() { - // TODO: Add calls to netd + // Calls to netd // Teardown VTI // Delete global policies + try { + mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName); + + for (int direction : DIRECTIONS) { + int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey; + mSrvConfig + .getNetdInstance() + .ipSecDeleteSecurityPolicy( + 0, direction, mLocalAddress, mRemoteAddress, mark, 0xffffffff); + } + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (RemoteException e) { + Log.e( + TAG, + "Failed to delete VTI with interface name: " + + mInterfaceName + + " and id: " + + mResourceId); + } getResourceTracker().give(); releaseNetId(mIkey); @@ -1229,24 +1252,57 @@ public class IpSecService extends IIpSecService.Stub { final int okey = reserveNetId(); String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId); - // TODO: Add calls to netd: - // Create VTI - // Add inbound/outbound global policies - // (use reqid = 0) + try { + // Calls to netd: + // Create VTI + // Add inbound/outbound global policies + // (use reqid = 0) + mSrvConfig + .getNetdInstance() + .addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey); - userRecord.mTunnelInterfaceRecords.put( - resourceId, - new RefcountedResource( - new TunnelInterfaceRecord( - resourceId, - intfName, - underlyingNetwork, - localAddr, - remoteAddr, - ikey, - okey), - binder)); - return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); + for (int direction : DIRECTIONS) { + int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey; + + mSrvConfig + .getNetdInstance() + .ipSecAddSecurityPolicy( + 0, // Use 0 for reqId + direction, + "", + "", + 0, + mark, + 0xffffffff); + } + + userRecord.mTunnelInterfaceRecords.put( + resourceId, + new RefcountedResource( + new TunnelInterfaceRecord( + resourceId, + intfName, + underlyingNetwork, + localAddr, + remoteAddr, + ikey, + okey), + binder)); + return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); + } catch (RemoteException e) { + // Release keys if we got an error. + releaseNetId(ikey); + releaseNetId(okey); + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + // FIXME: get the error code and throw is at an IOException from Errno Exception + } + + // If we make it to here, then something has gone wrong and we couldn't create a VTI. + // Release the keys that we reserved, and return an error status. + releaseNetId(ikey); + releaseNetId(okey); + return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } /** @@ -1381,12 +1437,50 @@ public class IpSecService extends IIpSecService.Stub { } } + private void createOrUpdateTransform( + IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord) + throws RemoteException { + + int encapType = c.getEncapType(), encapLocalPort = 0, encapRemotePort = 0; + if (encapType != IpSecTransform.ENCAP_NONE) { + encapLocalPort = socketRecord.getPort(); + encapRemotePort = c.getEncapRemotePort(); + } + + IpSecAlgorithm auth = c.getAuthentication(); + IpSecAlgorithm crypt = c.getEncryption(); + IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(); + + mSrvConfig + .getNetdInstance() + .ipSecAddSecurityAssociation( + resourceId, + c.getMode(), + c.getSourceAddress(), + c.getDestinationAddress(), + (c.getNetwork() != null) ? c.getNetwork().netId : 0, + spiRecord.getSpi(), + c.getMarkValue(), + c.getMarkMask(), + (auth != null) ? auth.getName() : "", + (auth != null) ? auth.getKey() : new byte[] {}, + (auth != null) ? auth.getTruncationLengthBits() : 0, + (crypt != null) ? crypt.getName() : "", + (crypt != null) ? crypt.getKey() : new byte[] {}, + (crypt != null) ? crypt.getTruncationLengthBits() : 0, + (authCrypt != null) ? authCrypt.getName() : "", + (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, + (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, + encapType, + encapLocalPort, + encapRemotePort); + } + /** - * Create a transport mode transform, which represent two security associations (one in each - * direction) in the kernel. The transform will be cached by the system server and must be freed - * when no longer needed. It is possible to free one, deleting the SA from underneath sockets - * that are using it, which will result in all of those sockets becoming unable to send or - * receive data. + * Create a IPsec transform, which represents a single security association in the kernel. The + * transform will be cached by the system server and must be freed when no longer needed. It is + * possible to free one, deleting the SA from underneath sockets that are using it, which will + * result in all of those sockets becoming unable to send or receive data. */ @Override public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder) @@ -1402,58 +1496,28 @@ public class IpSecService extends IIpSecService.Stub { return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } - int encapType, encapLocalPort = 0, encapRemotePort = 0; EncapSocketRecord socketRecord = null; - encapType = c.getEncapType(); - if (encapType != IpSecTransform.ENCAP_NONE) { + if (c.getEncapType() != IpSecTransform.ENCAP_NONE) { RefcountedResource refcountedSocketRecord = userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow( c.getEncapSocketResourceId()); dependencies.add(refcountedSocketRecord); - socketRecord = refcountedSocketRecord.getResource(); - encapLocalPort = socketRecord.getPort(); - encapRemotePort = c.getEncapRemotePort(); } - IpSecAlgorithm auth = c.getAuthentication(); - IpSecAlgorithm crypt = c.getEncryption(); - IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(); - RefcountedResource refcountedSpiRecord = userRecord.mSpiRecords.getRefcountedResourceOrThrow(c.getSpiResourceId()); dependencies.add(refcountedSpiRecord); SpiRecord spiRecord = refcountedSpiRecord.getResource(); try { - mSrvConfig - .getNetdInstance() - .ipSecAddSecurityAssociation( - resourceId, - c.getMode(), - c.getSourceAddress(), - c.getDestinationAddress(), - (c.getNetwork() != null) ? c.getNetwork().netId : 0, - spiRecord.getSpi(), - c.getMarkValue(), - c.getMarkMask(), - (auth != null) ? auth.getName() : "", - (auth != null) ? auth.getKey() : new byte[] {}, - (auth != null) ? auth.getTruncationLengthBits() : 0, - (crypt != null) ? crypt.getName() : "", - (crypt != null) ? crypt.getKey() : new byte[] {}, - (crypt != null) ? crypt.getTruncationLengthBits() : 0, - (authCrypt != null) ? authCrypt.getName() : "", - (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, - (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, - encapType, - encapLocalPort, - encapRemotePort); + createOrUpdateTransform(c, resourceId, spiRecord, socketRecord); } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } - // Both SAs were created successfully, time to construct a record and lock it away + + // SA was created successfully, time to construct a record and lock it away userRecord.mTransformRecords.put( resourceId, new RefcountedResource( @@ -1561,14 +1625,48 @@ public class IpSecService extends IIpSecService.Stub { c.getMode() == IpSecTransform.MODE_TUNNEL, "Transform mode was not Tunnel mode; cannot be applied to a tunnel interface"); + EncapSocketRecord socketRecord = null; + if (c.getEncapType() != IpSecTransform.ENCAP_NONE) { + socketRecord = + userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId()); + } + SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId()); + int mark = (direction == IpSecManager.DIRECTION_IN) ? tunnelInterfaceInfo.getIkey() : tunnelInterfaceInfo.getOkey(); - // TODO: Add calls to netd: - // Update SA with tunnel mark (ikey or okey based on direction) - // If outbound, add SPI to policy + try { + c.setMarkValue(mark); + c.setMarkMask(0xffffffff); + + if (direction == IpSecManager.DIRECTION_OUT) { + // Set output mark via underlying network (output only) + c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork()); + + // If outbound, also add SPI to the policy. + mSrvConfig + .getNetdInstance() + .ipSecUpdateSecurityPolicy( + 0, // Use 0 for reqId + direction, + "", + "", + transformInfo.getSpiRecord().getSpi(), + mark, + 0xffffffff); + } + + // Update SA with tunnel mark (ikey or okey based on direction) + createOrUpdateTransform(c, transformResourceId, spiRecord, socketRecord); + } catch (ServiceSpecificException e) { + if (e.errorCode == EINVAL) { + throw new IllegalArgumentException(e.toString()); + } else { + throw e; + } + } } @Override From dbfdb4a16086f6d21080519ef5a1c6008d60b92d Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 6 Dec 2017 19:12:28 -0800 Subject: [PATCH 110/881] Move Keepalive out of IpSecTransform.Builder The lifecycle of Keepalive offloading is, unfortunately different from that of an IpSecTransform. Because starting a keepalive is fundamentally asynchronous, and isn't valid until after a transform exists, it will now be a separate optional procedure that may succeed or fail. It remains linked with a Transform by the need for a Transform to exist in order to initiate a Keepalive. Bug: 38350389 Test: compilation Change-Id: Ia76fccee41f86d694dff436043293d0c0762c041 --- core/java/android/net/IpSecTransform.java | 155 ++++++++++++++-------- 1 file changed, 102 insertions(+), 53 deletions(-) diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 37e2c4fbf0..9ccdbe2b1b 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -17,11 +17,14 @@ package android.net; import static android.net.IpSecManager.INVALID_RESOURCE_ID; +import static com.android.internal.util.Preconditions.checkNotNull; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.Context; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -128,13 +131,6 @@ public final class IpSecTransform implements AutoCloseable { int status = result.status; checkResultStatus(status); mResourceId = result.resourceId; - - /* Keepalive will silently fail if not needed by the config; but, if needed and - * it fails to start, we need to bail because a transform will not be reliable - * to use if keepalive is expected to offload and fails. - */ - // FIXME: if keepalive fails, we need to fail spectacularly - startKeepalive(mContext); Log.d(TAG, "Added Transform with Id " + mResourceId); mCloseGuard.open("build"); } catch (RemoteException e) { @@ -164,13 +160,9 @@ public final class IpSecTransform implements AutoCloseable { return; } try { - /* Order matters here because the keepalive is best-effort but could fail in some - * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we - * still want to clear out the transform. - */ IIpSecService svc = getIpSecService(); svc.deleteTransform(mResourceId); - stopKeepalive(); + stopNattKeepalive(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { @@ -198,42 +190,35 @@ public final class IpSecTransform implements AutoCloseable { private final Context mContext; private final CloseGuard mCloseGuard = CloseGuard.get(); private ConnectivityManager.PacketKeepalive mKeepalive; - private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; - private Object mKeepaliveSyncLock = new Object(); - private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback = + private Handler mCallbackHandler; + private final ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback = new ConnectivityManager.PacketKeepaliveCallback() { @Override public void onStarted() { - synchronized (mKeepaliveSyncLock) { - mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS; - mKeepaliveSyncLock.notifyAll(); + synchronized (this) { + mCallbackHandler.post(() -> mUserKeepaliveCallback.onStarted()); } } @Override public void onStopped() { - synchronized (mKeepaliveSyncLock) { - mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE; - mKeepaliveSyncLock.notifyAll(); + synchronized (this) { + mKeepalive = null; + mCallbackHandler.post(() -> mUserKeepaliveCallback.onStopped()); } } @Override public void onError(int error) { - synchronized (mKeepaliveSyncLock) { - mKeepaliveStatus = error; - mKeepaliveSyncLock.notifyAll(); + synchronized (this) { + mKeepalive = null; + mCallbackHandler.post(() -> mUserKeepaliveCallback.onError(error)); } } }; - /* Package */ - void startKeepalive(Context c) { - if (mConfig.getNattKeepaliveInterval() != 0) { - Log.wtf(TAG, "Keepalive not yet supported."); - } - } + private NattKeepaliveCallback mUserKeepaliveCallback; /** @hide */ @VisibleForTesting @@ -241,9 +226,93 @@ public final class IpSecTransform implements AutoCloseable { return mResourceId; } - /* Package */ - void stopKeepalive() { - return; + /** + * A callback class to provide status information regarding a NAT-T keepalive session + * + *

Use this callback to receive status information regarding a NAT-T keepalive session + * by registering it when calling {@link #startNattKeepalive}. + * + * @hide + */ + @SystemApi + public static class NattKeepaliveCallback { + /** The specified {@code Network} is not connected. */ + public static final int ERROR_INVALID_NETWORK = 1; + /** The hardware does not support this request. */ + public static final int ERROR_HARDWARE_UNSUPPORTED = 2; + /** The hardware returned an error. */ + public static final int ERROR_HARDWARE_ERROR = 3; + + /** The requested keepalive was successfully started. */ + public void onStarted() {} + /** The keepalive was successfully stopped. */ + public void onStopped() {} + /** An error occurred. */ + public void onError(int error) {} + } + + /** + * Start a NAT-T keepalive session for the current transform. + * + * For a transform that is using UDP encapsulated IPv4, NAT-T offloading provides + * a power efficient mechanism of sending NAT-T packets at a specified interval. + * + * @param userCallback a {@link #NattKeepaliveCallback} to receive asynchronous status + * information about the requested NAT-T keepalive session. + * @param intervalSeconds the interval between NAT-T keepalives being sent. The + * the allowed range is between 20 and 3600 seconds. + * @param handler a handler on which to post callbacks when received. + * + * @hide + */ + @SystemApi + public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback, + int intervalSeconds, @NonNull Handler handler) throws IOException { + checkNotNull(userCallback); + if (intervalSeconds < 20 || intervalSeconds > 3600) { + throw new IllegalArgumentException("Invalid NAT-T keepalive interval"); + } + checkNotNull(handler); + if (mResourceId == INVALID_RESOURCE_ID) { + throw new IllegalStateException( + "Packet keepalive cannot be started for an inactive transform"); + } + + synchronized (mKeepaliveCallback) { + if (mKeepaliveCallback != null) { + throw new IllegalStateException("Keepalive already active"); + } + + mUserKeepaliveCallback = userCallback; + ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + mKeepalive = cm.startNattKeepalive( + mConfig.getNetwork(), intervalSeconds, mKeepaliveCallback, + NetworkUtils.numericToInetAddress(mConfig.getSourceAddress()), + 4500, // FIXME urgently, we need to get the port number from the Encap socket + NetworkUtils.numericToInetAddress(mConfig.getDestinationAddress())); + mCallbackHandler = handler; + } + } + + /** + * Stop an ongoing NAT-T keepalive session. + * + * Calling this API will request that an ongoing NAT-T keepalive session be terminated. + * If this API is not called when a Transform is closed, the underlying NAT-T session will + * be terminated automatically. + * + * @hide + */ + @SystemApi + public void stopNattKeepalive() { + synchronized (mKeepaliveCallback) { + if (mKeepalive == null) { + Log.e(TAG, "No active keepalive to stop"); + return; + } + mKeepalive.stop(); + } } /** This class is used to build {@link IpSecTransform} objects. */ @@ -323,26 +392,6 @@ public final class IpSecTransform implements AutoCloseable { return this; } - // TODO: Decrease the minimum keepalive to maybe 10? - // TODO: Probably a better exception to throw for NATTKeepalive failure - // TODO: Specify the needed NATT keepalive permission. - /** - * Set NAT-T keepalives to be sent with a given interval. - * - *

This will set power-efficient keepalive packets to be sent by the system. If NAT-T - * keepalive is requested but cannot be activated, then creation of an {@link - * IpSecTransform} will fail when calling the build method. - * - * @param intervalSeconds the maximum number of seconds between keepalive packets. Must be - * between 20s and 3600s. - * @hide - */ - @SystemApi - public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) { - mConfig.setNattKeepaliveInterval(intervalSeconds); - return this; - } - /** * Build a transport mode {@link IpSecTransform}. * From d5135d4b8397f2e1ffb9108edd276d72233bd5db Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Tue, 31 Oct 2017 15:42:16 -0700 Subject: [PATCH 111/881] Enable multiple active Ethernet interfaces - reworked EthernetNetworkFactory to support multiple active Ethernet interfaces - allow vendors to specify network capabilities + ip config through XML config overlay Test: manual using hikey960 + multiple usb->eth adapters Change-Id: Ie39bcb0d2a3f960f497222159c7bd5797accaa68 --- .../server/ethernet/EthernetConfigStore.java | 69 +- .../ethernet/EthernetNetworkFactory.java | 741 ++++++++---------- .../server/ethernet/EthernetServiceImpl.java | 89 +-- .../server/ethernet/EthernetTracker.java | 383 +++++++++ 4 files changed, 809 insertions(+), 473 deletions(-) create mode 100644 service-t/src/com/android/server/ethernet/EthernetTracker.java diff --git a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java index 676bc99d8a..6445603b96 100644 --- a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java +++ b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java @@ -17,11 +17,8 @@ package com.android.server.ethernet; import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; import android.os.Environment; -import android.util.Log; -import android.util.SparseArray; +import android.util.ArrayMap; import com.android.server.net.IpConfigStore; @@ -29,34 +26,60 @@ import com.android.server.net.IpConfigStore; /** * This class provides an API to store and manage Ethernet network configuration. */ -public class EthernetConfigStore extends IpConfigStore { - private static final String TAG = "EthernetConfigStore"; - +public class EthernetConfigStore { private static final String ipConfigFile = Environment.getDataDirectory() + "/misc/ethernet/ipconfig.txt"; + private IpConfigStore mStore = new IpConfigStore(); + private ArrayMap mIpConfigurations; + private IpConfiguration mIpConfigurationForDefaultInterface; + private final Object mSync = new Object(); + public EthernetConfigStore() { + mIpConfigurations = new ArrayMap<>(0); } - public IpConfiguration readIpAndProxyConfigurations() { - SparseArray networks = readIpAndProxyConfigurations(ipConfigFile); + public void read() { + synchronized (mSync) { + ArrayMap configs = + IpConfigStore.readIpConfigurations(ipConfigFile); - if (networks.size() == 0) { - Log.w(TAG, "No Ethernet configuration found. Using default."); - return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); + // This configuration may exist in old file versions when there was only a single active + // Ethernet interface. + if (configs.containsKey("0")) { + mIpConfigurationForDefaultInterface = configs.remove("0"); + } + + mIpConfigurations = configs; } - - if (networks.size() > 1) { - // Currently we only support a single Ethernet interface. - Log.w(TAG, "Multiple Ethernet configurations detected. Only reading first one."); - } - - return networks.valueAt(0); } - public void writeIpAndProxyConfigurations(IpConfiguration config) { - SparseArray networks = new SparseArray(); - networks.put(0, config); - writeIpAndProxyConfigurations(ipConfigFile, networks); + public void write(String iface, IpConfiguration config) { + boolean modified; + + synchronized (mSync) { + if (config == null) { + modified = mIpConfigurations.remove(iface) != null; + } else { + IpConfiguration oldConfig = mIpConfigurations.put(iface, config); + modified = !config.equals(oldConfig); + } + + if (modified) { + mStore.writeIpConfigurations(ipConfigFile, mIpConfigurations); + } + } + } + + public ArrayMap getIpConfigurations() { + synchronized (mSync) { + return new ArrayMap<>(mIpConfigurations); + } + } + + public IpConfiguration getIpConfigurationForDefaultInterface() { + synchronized (mSync) { + return new IpConfiguration(mIpConfigurationForDefaultInterface); + } } } diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 2e5d09e2ca..29464b78ce 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,12 +16,9 @@ package com.android.server.ethernet; +import static android.net.ConnectivityManager.TYPE_ETHERNET; + import android.content.Context; -import android.net.ConnectivityManager; -import android.net.DhcpResults; -import android.net.EthernetManager; -import android.net.IEthernetServiceListener; -import android.net.InterfaceConfiguration; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -31,292 +28,215 @@ import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; -import android.net.StaticIpConfiguration; -import android.net.ip.IpManager; -import android.net.ip.IpManager.ProvisioningConfiguration; +import android.net.NetworkRequest; +import android.net.NetworkSpecifier; +import android.net.StringNetworkSpecifier; +import android.net.ip.IpClient; +import android.net.ip.IpClient.ProvisioningConfiguration; import android.os.Handler; -import android.os.IBinder; -import android.os.INetworkManagementService; -import android.os.Looper; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.ServiceManager; import android.text.TextUtils; import android.util.Log; import com.android.internal.util.IndentingPrintWriter; -import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.concurrent.CountDownLatch; - +import java.util.concurrent.ConcurrentHashMap; /** - * Manages connectivity for an Ethernet interface. + * {@link NetworkFactory} that represents Ethernet networks. * - * Ethernet Interfaces may be present at boot time or appear after boot (e.g., - * for Ethernet adapters connected over USB). This class currently supports - * only one interface. When an interface appears on the system (or is present - * at boot time) this class will start tracking it and bring it up, and will - * attempt to connect when requested. Any other interfaces that subsequently - * appear will be ignored until the tracked interface disappears. Only - * interfaces whose names match the config_ethernet_iface_regex - * regular expression are tracked. - * - * This class reports a static network score of 70 when it is tracking an - * interface and that interface's link is up, and a score of 0 otherwise. - * - * @hide + * This class reports a static network score of 70 when it is tracking an interface and that + * interface's link is up, and a score of 0 otherwise. */ -class EthernetNetworkFactory { +public class EthernetNetworkFactory extends NetworkFactory { + private final static String TAG = EthernetNetworkFactory.class.getSimpleName(); + final static boolean DBG = true; + + private final static int NETWORK_SCORE = 70; private static final String NETWORK_TYPE = "Ethernet"; - private static final String TAG = "EthernetNetworkFactory"; - private static final int NETWORK_SCORE = 70; - private static final boolean DBG = true; - /** Tracks interface changes. Called from NetworkManagementService. */ - private InterfaceObserver mInterfaceObserver; + private final ConcurrentHashMap mTrackingInterfaces = + new ConcurrentHashMap<>(); + private final Handler mHandler; + private final Context mContext; - /** For static IP configuration */ - private EthernetManager mEthernetManager; + public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) { + super(handler.getLooper(), context, NETWORK_TYPE, filter); - /** To set link state and configure IP addresses. */ - private INetworkManagementService mNMService; + mHandler = handler; + mContext = context; - /** All code runs here, including start(). */ - private Handler mHandler; - - /* To communicate with ConnectivityManager */ - private NetworkCapabilities mNetworkCapabilities; - private NetworkAgent mNetworkAgent; - private LocalNetworkFactory mFactory; - private Context mContext; - - /** Product-dependent regular expression of interface names we track. */ - private static String mIfaceMatch = ""; - - /** To notify Ethernet status. */ - private final RemoteCallbackList mListeners; - - /** Data members. All accesses to these must be on the handler thread. */ - private String mIface = ""; - private String mHwAddr; - private boolean mLinkUp; - private NetworkInfo mNetworkInfo; - private LinkProperties mLinkProperties; - private IpManager mIpManager; - private boolean mNetworkRequested = false; - - EthernetNetworkFactory(RemoteCallbackList listeners) { - initNetworkCapabilities(); - clearInfo(); - mListeners = listeners; + setScoreFilter(NETWORK_SCORE); } - private class LocalNetworkFactory extends NetworkFactory { - LocalNetworkFactory(String name, Context context, Looper looper) { - super(looper, context, name, new NetworkCapabilities()); + @Override + public boolean acceptRequest(NetworkRequest request, int score) { + if (DBG) { + Log.d(TAG, "acceptRequest, request: " + request + ", score: " + score); } - protected void startNetwork() { - if (!mNetworkRequested) { - mNetworkRequested = true; - maybeStartIpManager(); - } + return networkForRequest(request) != null; + } + + @Override + protected void needNetworkFor(NetworkRequest networkRequest, int score) { + NetworkInterfaceState network = networkForRequest(networkRequest); + + if (network == null) { + Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest); + return; } - protected void stopNetwork() { - mNetworkRequested = false; - stopIpManager(); + if (++network.refCount == 1) { + network.start(); } } - private void clearInfo() { - mLinkProperties = new LinkProperties(); - mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORK_TYPE, ""); - mNetworkInfo.setExtraInfo(mHwAddr); - mNetworkInfo.setIsAvailable(isTrackingInterface()); - } + @Override + protected void releaseNetworkFor(NetworkRequest networkRequest) { + NetworkInterfaceState network = networkForRequest(networkRequest); + if (network == null) { + Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest); + return; + } - private void stopIpManager() { - if (mIpManager != null) { - mIpManager.shutdown(); - mIpManager = null; + if (--network.refCount == 1) { + network.stop(); } - // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object - // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: - // that sets the state to IDLE, and ConnectivityService will still think we're connected. - // - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddr); - if (mNetworkAgent != null) { - updateAgent(); - mNetworkAgent = null; - } - clearInfo(); } /** - * Updates interface state variables. - * Called on link state changes or on startup. + * Returns an array of available interface names. The array is sorted: unrestricted interfaces + * goes first, then sorted by name. */ - private void updateInterfaceState(String iface, boolean up) { - if (!mIface.equals(iface)) { + String[] getAvailableInterfaces(boolean includeRestricted) { + return mTrackingInterfaces.values() + .stream() + .filter(iface -> !iface.isRestricted() || includeRestricted) + .sorted((iface1, iface2) -> { + int r = Boolean.compare(iface1.isRestricted(), iface2.isRestricted()); + return r == 0 ? iface1.name.compareTo(iface2.name) : r; + }) + .map(iface -> iface.name) + .toArray(String[]::new); + } + + void addInterface(String ifaceName, String hwAddress, NetworkCapabilities capabilities, + IpConfiguration ipConfiguration) { + if (mTrackingInterfaces.containsKey(ifaceName)) { + Log.e(TAG, "Interface with name " + ifaceName + " already exists."); return; } - Log.d(TAG, "updateInterface: " + iface + " link " + (up ? "up" : "down")); - mLinkUp = up; - if (up) { - maybeStartIpManager(); + if (DBG) { + Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities); + } + + NetworkInterfaceState iface = new NetworkInterfaceState( + ifaceName, hwAddress, mHandler, mContext, capabilities); + iface.setIpConfig(ipConfiguration); + mTrackingInterfaces.put(ifaceName, iface); + + updateCapabilityFilter(); + } + + private void updateCapabilityFilter() { + NetworkCapabilities capabilitiesFilter = new NetworkCapabilities(); + capabilitiesFilter.clearAll(); + + for (NetworkInterfaceState iface: mTrackingInterfaces.values()) { + capabilitiesFilter.combineCapabilities(iface.mCapabilities); + } + + if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter); + setCapabilityFilter(capabilitiesFilter); + } + + void removeInterface(String interfaceName) { + NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName); + if (iface != null) { + iface.stop(); + } + + updateCapabilityFilter(); + } + + /** Returns true if state has been modified */ + boolean updateInterfaceLinkState(String ifaceName, boolean up) { + if (!mTrackingInterfaces.containsKey(ifaceName)) { + return false; + } + + if (DBG) { + Log.d(TAG, "updateInterfaceLinkState, iface: " + ifaceName + ", up: " + up); + } + + NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName); + return iface.updateLinkState(up); + } + + boolean hasInterface(String interfacName) { + return mTrackingInterfaces.containsKey(interfacName); + } + + void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) { + NetworkInterfaceState network = mTrackingInterfaces.get(iface); + if (network != null) { + network.setIpConfig(ipConfiguration); + } + } + + private NetworkInterfaceState networkForRequest(NetworkRequest request) { + String requestedIface = null; + + NetworkSpecifier specifier = request.networkCapabilities.getNetworkSpecifier(); + if (specifier instanceof StringNetworkSpecifier) { + requestedIface = ((StringNetworkSpecifier) specifier).specifier; + } + + NetworkInterfaceState network = null; + if (!TextUtils.isEmpty(requestedIface)) { + NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface); + if (n != null && n.statisified(request.networkCapabilities)) { + network = n; + } } else { - stopIpManager(); - } - } - - private class InterfaceObserver extends BaseNetworkObserver { - @Override - public void interfaceLinkStateChanged(String iface, boolean up) { - mHandler.post(() -> { - updateInterfaceState(iface, up); - }); - } - - @Override - public void interfaceAdded(String iface) { - mHandler.post(() -> { - maybeTrackInterface(iface); - }); - } - - @Override - public void interfaceRemoved(String iface) { - mHandler.post(() -> { - if (stopTrackingInterface(iface)) { - trackFirstAvailableInterface(); + for (NetworkInterfaceState n : mTrackingInterfaces.values()) { + if (n.statisified(request.networkCapabilities)) { + network = n; + break; } - }); - } - } - - private void setInterfaceUp(String iface) { - // Bring up the interface so we get link status indications. - try { - mNMService.setInterfaceUp(iface); - String hwAddr = null; - InterfaceConfiguration config = mNMService.getInterfaceConfig(iface); - - if (config == null) { - Log.e(TAG, "Null interface config for " + iface + ". Bailing out."); - return; } - - if (!isTrackingInterface()) { - setInterfaceInfo(iface, config.getHardwareAddress()); - mNetworkInfo.setIsAvailable(true); - mNetworkInfo.setExtraInfo(mHwAddr); - } else { - Log.e(TAG, "Interface unexpectedly changed from " + iface + " to " + mIface); - mNMService.setInterfaceDown(iface); - } - } catch (RemoteException | IllegalStateException e) { - // Either the system is crashing or the interface has disappeared. Just ignore the - // error; we haven't modified any state because we only do that if our calls succeed. - Log.e(TAG, "Error upping interface " + mIface + ": " + e); } - } - private boolean maybeTrackInterface(String iface) { - // If we don't already have an interface, and if this interface matches - // our regex, start tracking it. - if (!iface.matches(mIfaceMatch) || isTrackingInterface()) - return false; - - Log.d(TAG, "Started tracking interface " + iface); - setInterfaceUp(iface); - return true; - } - - private boolean stopTrackingInterface(String iface) { - if (!iface.equals(mIface)) - return false; - - Log.d(TAG, "Stopped tracking interface " + iface); - setInterfaceInfo("", null); - stopIpManager(); - return true; - } - - public void updateAgent() { - if (mNetworkAgent == null) return; if (DBG) { - Log.i(TAG, "Updating mNetworkAgent with: " + - mNetworkCapabilities + ", " + - mNetworkInfo + ", " + - mLinkProperties); - } - mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); - mNetworkAgent.sendLinkProperties(mLinkProperties); - // never set the network score below 0. - mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); - } - - void onIpLayerStarted(LinkProperties linkProperties) { - if (mNetworkAgent != null) { - Log.e(TAG, "Already have a NetworkAgent - aborting new request"); - stopIpManager(); - return; - } - mLinkProperties = linkProperties; - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr); - - // Create our NetworkAgent. - mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, - NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties, - NETWORK_SCORE) { - public void unwanted() { - if (this == mNetworkAgent) { - stopIpManager(); - } else if (mNetworkAgent != null) { - Log.d(TAG, "Ignoring unwanted as we have a more modern " + - "instance"); - } // Otherwise, we've already called stopIpManager. - } - }; - } - - void onIpLayerStopped(LinkProperties linkProperties) { - // This cannot happen due to provisioning timeout, because our timeout is 0. It can only - // happen if we're provisioned and we lose provisioning. - stopIpManager(); - maybeStartIpManager(); - } - - void updateLinkProperties(LinkProperties linkProperties) { - mLinkProperties = linkProperties; - if (mNetworkAgent != null) { - mNetworkAgent.sendLinkProperties(linkProperties); - } - } - - public void maybeStartIpManager() { - if (mNetworkRequested && mIpManager == null && isTrackingInterface()) { - startIpManager(); - } - } - - public void startIpManager() { - if (DBG) { - Log.d(TAG, String.format("starting IpManager(%s): mNetworkInfo=%s", mIface, - mNetworkInfo)); + Log.i(TAG, "networkForRequest, request: " + request + ", network: " + network); } - IpConfiguration config = mEthernetManager.getConfiguration(); + return network; + } - mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr); - IpManager.Callback ipmCallback = new IpManager.Callback() { + private static class NetworkInterfaceState { + final String name; + + private final String mHwAddress; + private final NetworkCapabilities mCapabilities; + private final Handler mHandler; + private final Context mContext; + private final NetworkInfo mNetworkInfo; + + private static String sTcpBufferSizes = null; // Lazy initialized. + + private boolean mLinkUp; + private LinkProperties mLinkProperties = new LinkProperties(); + + private IpClient mIpClient; + private NetworkAgent mNetworkAgent; + private IpConfiguration mIpConfig; + + long refCount = 0; + + private final IpClient.Callback mIpClientCallback = new IpClient.Callback() { @Override public void onProvisioningSuccess(LinkProperties newLp) { mHandler.post(() -> onIpLayerStarted(newLp)); @@ -333,178 +253,191 @@ class EthernetNetworkFactory { } }; - stopIpManager(); - mIpManager = new IpManager(mContext, mIface, ipmCallback); + NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, + NetworkCapabilities capabilities) { + name = ifaceName; + mCapabilities = capabilities; + mHandler = handler; + mContext = context; - if (config.getProxySettings() == ProxySettings.STATIC || - config.getProxySettings() == ProxySettings.PAC) { - mIpManager.setHttpProxy(config.getHttpProxy()); + mHwAddress = hwAddress; + mNetworkInfo = new NetworkInfo(TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + mNetworkInfo.setExtraInfo(mHwAddress); + mNetworkInfo.setIsAvailable(true); } - final String tcpBufferSizes = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_tcp_buffers); - if (!TextUtils.isEmpty(tcpBufferSizes)) { - mIpManager.setTcpBufferSizes(tcpBufferSizes); + void setIpConfig(IpConfiguration ipConfig) { + + this.mIpConfig = ipConfig; } - final ProvisioningConfiguration provisioningConfiguration; - if (config.getIpAssignment() == IpAssignment.STATIC) { - provisioningConfiguration = IpManager.buildProvisioningConfiguration() - .withStaticConfiguration(config.getStaticIpConfiguration()) - .build(); - } else { - provisioningConfiguration = mIpManager.buildProvisioningConfiguration() - .withProvisioningTimeoutMs(0) - .build(); + boolean statisified(NetworkCapabilities requestedCapabilities) { + return requestedCapabilities.satisfiedByNetworkCapabilities(mCapabilities); } - mIpManager.startProvisioning(provisioningConfiguration); - } - - /** - * Begin monitoring connectivity - */ - public void start(Context context, Handler handler) { - mHandler = handler; - - // The services we use. - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNMService = INetworkManagementService.Stub.asInterface(b); - mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE); - - // Interface match regex. - mIfaceMatch = context.getResources().getString( - com.android.internal.R.string.config_ethernet_iface_regex); - - // Create and register our NetworkFactory. - mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, mHandler.getLooper()); - mFactory.setCapabilityFilter(mNetworkCapabilities); - mFactory.setScoreFilter(NETWORK_SCORE); - mFactory.register(); - - mContext = context; - - // Start tracking interface change events. - mInterfaceObserver = new InterfaceObserver(); - try { - mNMService.registerObserver(mInterfaceObserver); - } catch (RemoteException e) { - Log.e(TAG, "Could not register InterfaceObserver " + e); + boolean isRestricted() { + return mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } - // If an Ethernet interface is already connected, start tracking that. - // Otherwise, the first Ethernet interface to appear will be tracked. - mHandler.post(() -> trackFirstAvailableInterface()); - } + private void start() { + if (DBG) { + Log.d(TAG, String.format("starting IpClient(%s): mNetworkInfo=%s", name, + mNetworkInfo)); + } + if (mIpClient != null) stop(); - public void trackFirstAvailableInterface() { - try { - final String[] ifaces = mNMService.listInterfaces(); - for (String iface : ifaces) { - if (maybeTrackInterface(iface)) { - // We have our interface. Track it. - // Note: if the interface already has link (e.g., if we crashed and got - // restarted while it was running), we need to fake a link up notification so we - // start configuring it. - if (mNMService.getInterfaceConfig(iface).hasFlag("running")) { - updateInterfaceState(iface, true); - } - break; + mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress); + + mIpClient = new IpClient(mContext, name, mIpClientCallback); + + if (sTcpBufferSizes == null) { + sTcpBufferSizes = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_tcp_buffers); + } + provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes); + } + + void onIpLayerStarted(LinkProperties linkProperties) { + if (mNetworkAgent != null) { + Log.e(TAG, "Already have a NetworkAgent - aborting new request"); + stop(); + return; + } + mLinkProperties = linkProperties; + mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddress); + mNetworkInfo.setIsAvailable(true); + + // Create our NetworkAgent. + mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, + NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties, + NETWORK_SCORE) { + public void unwanted() { + if (this == mNetworkAgent) { + stop(); + } else if (mNetworkAgent != null) { + Log.d(TAG, "Ignoring unwanted as we have a more modern " + + "instance"); + } // Otherwise, we've already called stop. } + }; + } + + void onIpLayerStopped(LinkProperties linkProperties) { + // This cannot happen due to provisioning timeout, because our timeout is 0. It can only + // happen if we're provisioned and we lose provisioning. + start(); + } + + void updateLinkProperties(LinkProperties linkProperties) { + mLinkProperties = linkProperties; + if (mNetworkAgent != null) { + mNetworkAgent.sendLinkProperties(linkProperties); } - } catch (RemoteException|IllegalStateException e) { - Log.e(TAG, "Could not get list of interfaces " + e); + } + + /** Returns true if state has been modified */ + boolean updateLinkState(boolean up) { + if (mLinkUp == up) return false; + + mLinkUp = up; + if (up) { + start(); + } else { + stop(); + } + + return true; + } + + void stop() { + if (mIpClient != null) { + mIpClient.shutdown(); + mIpClient = null; + } + // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object + // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: + // that sets the state to IDLE, and ConnectivityService will still think we're connected. + // + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddress); + if (mNetworkAgent != null) { + updateAgent(); + mNetworkAgent = null; + } + clear(); + } + + private void updateAgent() { + if (mNetworkAgent == null) return; + if (DBG) { + Log.i(TAG, "Updating mNetworkAgent with: " + + mCapabilities + ", " + + mNetworkInfo + ", " + + mLinkProperties); + } + mNetworkAgent.sendNetworkCapabilities(mCapabilities); + mNetworkAgent.sendNetworkInfo(mNetworkInfo); + mNetworkAgent.sendLinkProperties(mLinkProperties); + // never set the network score below 0. + mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); + } + + private void clear() { + mLinkProperties.clear(); + mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null); + mNetworkInfo.setIsAvailable(false); + } + + private static void provisionIpClient(IpClient ipClient, IpConfiguration config, + String tcpBufferSizes) { + if (config.getProxySettings() == ProxySettings.STATIC || + config.getProxySettings() == ProxySettings.PAC) { + ipClient.setHttpProxy(config.getHttpProxy()); + } + + if (!TextUtils.isEmpty(tcpBufferSizes)) { + ipClient.setTcpBufferSizes(tcpBufferSizes); + } + + final ProvisioningConfiguration provisioningConfiguration; + if (config.getIpAssignment() == IpAssignment.STATIC) { + provisioningConfiguration = IpClient.buildProvisioningConfiguration() + .withStaticConfiguration(config.getStaticIpConfiguration()) + .build(); + } else { + provisioningConfiguration = IpClient.buildProvisioningConfiguration() + .withProvisioningTimeoutMs(0) + .build(); + } + + ipClient.startProvisioning(provisioningConfiguration); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "{ " + + "iface: " + name + ", " + + "up: " + mLinkUp + ", " + + "hwAddress: " + mHwAddress + ", " + + "networkInfo: " + mNetworkInfo + ", " + + "networkAgent: " + mNetworkAgent + ", " + + "ipClient: " + mIpClient + "," + + "linkProperties: " + mLinkProperties + + "}"; } } - public void stop() { - stopIpManager(); - setInterfaceInfo("", null); - mFactory.unregister(); - } - - private void initNetworkCapabilities() { - mNetworkCapabilities = new NetworkCapabilities(); - mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); - mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); - mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - // We have no useful data on bandwidth. Say 100M up and 100M down. :-( - mNetworkCapabilities.setLinkUpstreamBandwidthKbps(100 * 1000); - mNetworkCapabilities.setLinkDownstreamBandwidthKbps(100 * 1000); - } - - public boolean isTrackingInterface() { - return !TextUtils.isEmpty(mIface); - } - - /** - * Set interface information and notify listeners if availability is changed. - */ - private void setInterfaceInfo(String iface, String hwAddr) { - boolean oldAvailable = isTrackingInterface(); - mIface = iface; - mHwAddr = hwAddr; - boolean available = isTrackingInterface(); - - mNetworkInfo.setExtraInfo(mHwAddr); - mNetworkInfo.setIsAvailable(available); - - if (oldAvailable != available) { - int n = mListeners.beginBroadcast(); - for (int i = 0; i < n; i++) { - try { - mListeners.getBroadcastItem(i).onAvailabilityChanged(available); - } catch (RemoteException e) { - // Do nothing here. - } - } - mListeners.finishBroadcast(); - } - } - - private void postAndWaitForRunnable(Runnable r) throws InterruptedException { - CountDownLatch latch = new CountDownLatch(1); - mHandler.post(() -> { - try { - r.run(); - } finally { - latch.countDown(); - } - }); - latch.await(); - } - - void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { - try { - postAndWaitForRunnable(() -> { - pw.println("Network Requested: " + mNetworkRequested); - if (isTrackingInterface()) { - pw.println("Tracking interface: " + mIface); - pw.increaseIndent(); - pw.println("MAC address: " + mHwAddr); - pw.println("Link state: " + (mLinkUp ? "up" : "down")); - pw.decreaseIndent(); - } else { - pw.println("Not tracking any interface"); - } - - pw.println(); - pw.println("NetworkInfo: " + mNetworkInfo); - pw.println("LinkProperties: " + mLinkProperties); - pw.println("NetworkAgent: " + mNetworkAgent); - if (mIpManager != null) { - pw.println("IpManager:"); - pw.increaseIndent(); - mIpManager.dump(fd, pw, args); - pw.decreaseIndent(); - } - }); - } catch (InterruptedException e) { - throw new IllegalStateException("dump() interrupted"); + super.dump(fd, pw, args); + pw.println(getClass().getSimpleName()); + pw.println("Tracking interfaces:"); + pw.increaseIndent(); + for (String iface: mTrackingInterfaces.keySet()) { + NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface); + pw.println(iface + ":" + ifaceState); + pw.increaseIndent(); + ifaceState.mIpClient.dump(fd, pw, args); + pw.decreaseIndent(); } + pw.decreaseIndent(); } } diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 42996d6826..d5beec1cb4 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -21,14 +21,10 @@ import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; import android.net.IpConfiguration; -import android.net.IpConfiguration.IpAssignment; -import android.net.IpConfiguration.ProxySettings; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; -import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.provider.Settings; import android.util.Log; import android.util.PrintWriterPrinter; @@ -41,31 +37,18 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * EthernetServiceImpl handles remote Ethernet operation requests by implementing * the IEthernetManager interface. - * - * @hide */ public class EthernetServiceImpl extends IEthernetManager.Stub { private static final String TAG = "EthernetServiceImpl"; private final Context mContext; - private final EthernetConfigStore mEthernetConfigStore; private final AtomicBoolean mStarted = new AtomicBoolean(false); - private IpConfiguration mIpConfiguration; private Handler mHandler; - private final EthernetNetworkFactory mTracker; - private final RemoteCallbackList mListeners = - new RemoteCallbackList(); + private EthernetTracker mTracker; public EthernetServiceImpl(Context context) { mContext = context; - Log.i(TAG, "Creating EthernetConfigStore"); - mEthernetConfigStore = new EthernetConfigStore(); - mIpConfiguration = mEthernetConfigStore.readIpAndProxyConfigurations(); - - Log.i(TAG, "Read stored IP configuration: " + mIpConfiguration); - - mTracker = new EthernetNetworkFactory(mListeners); } private void enforceAccessPermission() { @@ -80,6 +63,18 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { "ConnectivityService"); } + private void enforceUseRestrictedNetworksPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS, + "ConnectivityService"); + } + + private boolean checkUseRestrictedNetworksPermission() { + return mContext.checkCallingOrSelfPermission( + android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS) + == PackageManager.PERMISSION_GRANTED; + } + public void start() { Log.i(TAG, "Starting Ethernet service"); @@ -87,60 +82,68 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); - mTracker.start(mContext, mHandler); + mTracker = new EthernetTracker(mContext, mHandler); + mTracker.start(); mStarted.set(true); } + @Override + public String[] getAvailableInterfaces() throws RemoteException { + return mTracker.getInterfaces(checkUseRestrictedNetworksPermission()); + } + /** * Get Ethernet configuration * @return the Ethernet Configuration, contained in {@link IpConfiguration}. */ @Override - public IpConfiguration getConfiguration() { + public IpConfiguration getConfiguration(String iface) { enforceAccessPermission(); - synchronized (mIpConfiguration) { - return new IpConfiguration(mIpConfiguration); + if (mTracker.isRestrictedInterface(iface)) { + enforceUseRestrictedNetworksPermission(); } + + return new IpConfiguration(mTracker.getIpConfiguration(iface)); } /** * Set Ethernet configuration */ @Override - public void setConfiguration(IpConfiguration config) { + public void setConfiguration(String iface, IpConfiguration config) { if (!mStarted.get()) { Log.w(TAG, "System isn't ready enough to change ethernet configuration"); } enforceConnectivityInternalPermission(); - synchronized (mIpConfiguration) { - mEthernetConfigStore.writeIpAndProxyConfigurations(config); - - // TODO: this does not check proxy settings, gateways, etc. - // Fix this by making IpConfiguration a complete representation of static configuration. - if (!config.equals(mIpConfiguration)) { - mIpConfiguration = new IpConfiguration(config); - mTracker.stop(); - mTracker.start(mContext, mHandler); - } + if (mTracker.isRestrictedInterface(iface)) { + enforceUseRestrictedNetworksPermission(); } + + // TODO: this does not check proxy settings, gateways, etc. + // Fix this by making IpConfiguration a complete representation of static configuration. + mTracker.updateIpConfiguration(iface, new IpConfiguration(config)); } /** - * Indicates whether the system currently has one or more - * Ethernet interfaces. + * Indicates whether given interface is available. */ @Override - public boolean isAvailable() { + public boolean isAvailable(String iface) { enforceAccessPermission(); - return mTracker.isTrackingInterface(); + + if (mTracker.isRestrictedInterface(iface)) { + enforceUseRestrictedNetworksPermission(); + } + + return mTracker.isTrackingInterface(iface); } /** - * Addes a listener. + * Adds a listener. * @param listener A {@link IEthernetServiceListener} to add. */ public void addListener(IEthernetServiceListener listener) { @@ -148,7 +151,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { throw new IllegalArgumentException("listener must not be null"); } enforceAccessPermission(); - mListeners.register(listener); + mTracker.addListener(listener, checkUseRestrictedNetworksPermission()); } /** @@ -160,7 +163,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { throw new IllegalArgumentException("listener must not be null"); } enforceAccessPermission(); - mListeners.unregister(listener); + mTracker.removeListener(listener); } @Override @@ -179,12 +182,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker.dump(fd, pw, args); pw.decreaseIndent(); - pw.println(); - pw.println("Stored Ethernet configuration: "); - pw.increaseIndent(); - pw.println(mIpConfiguration); - pw.decreaseIndent(); - pw.println("Handler:"); pw.increaseIndent(); mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl"); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java new file mode 100644 index 0000000000..7f893e0339 --- /dev/null +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.ethernet; + +import android.annotation.Nullable; +import android.content.Context; +import android.net.IEthernetServiceListener; +import android.net.InterfaceConfiguration; +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.NetworkCapabilities; +import android.net.StaticIpConfiguration; +import android.os.Handler; +import android.os.IBinder; +import android.os.INetworkManagementService; +import android.os.RemoteCallbackList; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.Log; + +import com.android.internal.util.IndentingPrintWriter; +import com.android.server.net.BaseNetworkObserver; + +import java.io.FileDescriptor; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Tracks Ethernet interfaces and manages interface configurations. + * + *

Interfaces may have different {@link android.net.NetworkCapabilities}. This mapping is defined + * in {@code config_ethernet_interfaces}. Notably, some interfaces could be marked as restricted by + * not specifying {@link android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED} flag. + * Interfaces could have associated {@link android.net.IpConfiguration}. + * Ethernet Interfaces may be present at boot time or appear after boot (e.g., for Ethernet adapters + * connected over USB). This class supports multiple interfaces. When an interface appears on the + * system (or is present at boot time) this class will start tracking it and bring it up. Only + * interfaces whose names match the {@code config_ethernet_iface_regex} regular expression are + * tracked. + * + *

All public or package private methods must be thread-safe unless stated otherwise. + */ +final class EthernetTracker { + private final static String TAG = EthernetTracker.class.getSimpleName(); + private final static boolean DBG = EthernetNetworkFactory.DBG; + + /** Product-dependent regular expression of interface names we track. */ + private final String mIfaceMatch; + + /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */ + private final ConcurrentHashMap mNetworkCapabilities = + new ConcurrentHashMap<>(); + private final ConcurrentHashMap mIpConfigurations = + new ConcurrentHashMap<>(); + + private final INetworkManagementService mNMService; + private final Handler mHandler; + private final EthernetNetworkFactory mFactory; + private final EthernetConfigStore mConfigStore; + + private final RemoteCallbackList mListeners = + new RemoteCallbackList<>(); + + private volatile IpConfiguration mIpConfigForDefaultInterface; + + EthernetTracker(Context context, Handler handler) { + mHandler = handler; + + // The services we use. + IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); + mNMService = INetworkManagementService.Stub.asInterface(b); + + // Interface match regex. + mIfaceMatch = context.getResources().getString( + com.android.internal.R.string.config_ethernet_iface_regex); + + // Read default Ethernet interface configuration from resources + final String[] interfaceConfigs = context.getResources().getStringArray( + com.android.internal.R.array.config_ethernet_interfaces); + for (String strConfig : interfaceConfigs) { + parseEthernetConfig(strConfig); + } + + mConfigStore = new EthernetConfigStore(); + + NetworkCapabilities nc = createNetworkCapabilities(true /* clear default capabilities */); + mFactory = new EthernetNetworkFactory(handler, context, nc); + mFactory.register(); + } + + void start() { + mConfigStore.read(); + + // Default interface is just the first one we want to track. + mIpConfigForDefaultInterface = mConfigStore.getIpConfigurationForDefaultInterface(); + final ArrayMap configs = mConfigStore.getIpConfigurations(); + for (int i = 0; i < configs.size(); i++) { + mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i)); + } + + try { + mNMService.registerObserver(new InterfaceObserver()); + } catch (RemoteException e) { + Log.e(TAG, "Could not register InterfaceObserver " + e); + } + + mHandler.post(this::trackAvailableInterfaces); + } + + void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) { + if (DBG) { + Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration); + } + + mConfigStore.write(iface, ipConfiguration); + mIpConfigurations.put(iface, ipConfiguration); + + mHandler.post(() -> mFactory.updateIpConfiguration(iface, ipConfiguration)); + } + + IpConfiguration getIpConfiguration(String iface) { + return mIpConfigurations.get(iface); + } + + boolean isTrackingInterface(String iface) { + return mFactory.hasInterface(iface); + } + + String[] getInterfaces(boolean includeRestricted) { + return mFactory.getAvailableInterfaces(includeRestricted); + } + + /** + * Returns true if given interface was configured as restricted (doesn't have + * NET_CAPABILITY_NOT_RESTRICTED) capability. Otherwise, returns false. + */ + boolean isRestrictedInterface(String iface) { + final NetworkCapabilities nc = mNetworkCapabilities.get(iface); + return nc != null && !nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + } + + void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) { + mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks)); + } + + void removeListener(IEthernetServiceListener listener) { + mListeners.unregister(listener); + } + + private void removeInterface(String iface) { + mFactory.removeInterface(iface); + } + + private void addInterface(String iface) { + InterfaceConfiguration config = null; + // Bring up the interface so we get link status indications. + try { + mNMService.setInterfaceUp(iface); + config = mNMService.getInterfaceConfig(iface); + } catch (RemoteException | IllegalStateException e) { + // Either the system is crashing or the interface has disappeared. Just ignore the + // error; we haven't modified any state because we only do that if our calls succeed. + Log.e(TAG, "Error upping interface " + iface, e); + } + + if (config == null) { + Log.e(TAG, "Null interface config for " + iface + ". Bailing out."); + return; + } + + final String hwAddress = config.getHardwareAddress(); + + NetworkCapabilities nc = mNetworkCapabilities.get(iface); + if (nc == null) { + // Try to resolve using mac address + nc = mNetworkCapabilities.get(hwAddress); + if (nc == null) { + nc = createDefaultNetworkCapabilities(); + } + } + IpConfiguration ipConfiguration = mIpConfigurations.get(iface); + if (ipConfiguration == null) { + ipConfiguration = createDefaultIpConfiguration(); + } + + Log.d(TAG, "Started tracking interface " + iface); + mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + + // Note: if the interface already has link (e.g., if we crashed and got + // restarted while it was running), we need to fake a link up notification so we + // start configuring it. + if (config.hasFlag("running")) { + updateInterfaceState(iface, true); + } + } + + private void updateInterfaceState(String iface, boolean up) { + boolean modified = mFactory.updateInterfaceLinkState(iface, up); + if (modified) { + boolean restricted = isRestrictedInterface(iface); + int n = mListeners.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + if (restricted) { + ListenerInfo listenerInfo = (ListenerInfo) mListeners.getBroadcastCookie(i); + if (!listenerInfo.canUseRestrictedNetworks) { + continue; + } + } + mListeners.getBroadcastItem(i).onAvailabilityChanged(iface, up); + } catch (RemoteException e) { + // Do nothing here. + } + } + mListeners.finishBroadcast(); + } + } + + private void maybeTrackInterface(String iface) { + if (DBG) Log.i(TAG, "maybeTrackInterface " + iface); + // If we don't already track this interface, and if this interface matches + // our regex, start tracking it. + if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface)) { + return; + } + + if (mIpConfigForDefaultInterface != null) { + updateIpConfiguration(iface, mIpConfigForDefaultInterface); + mIpConfigForDefaultInterface = null; + } + + addInterface(iface); + } + + private void trackAvailableInterfaces() { + try { + final String[] ifaces = mNMService.listInterfaces(); + for (String iface : ifaces) { + maybeTrackInterface(iface); + } + } catch (RemoteException | IllegalStateException e) { + Log.e(TAG, "Could not get list of interfaces " + e); + } + } + + + private class InterfaceObserver extends BaseNetworkObserver { + + @Override + public void interfaceLinkStateChanged(String iface, boolean up) { + if (DBG) { + Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up); + } + mHandler.post(() -> updateInterfaceState(iface, up)); + } + + @Override + public void interfaceAdded(String iface) { + mHandler.post(() -> maybeTrackInterface(iface)); + } + + @Override + public void interfaceRemoved(String iface) { + mHandler.post(() -> removeInterface(iface)); + } + } + + private static class ListenerInfo { + + boolean canUseRestrictedNetworks = false; + + ListenerInfo(boolean canUseRestrictedNetworks) { + this.canUseRestrictedNetworks = canUseRestrictedNetworks; + } + } + + private void parseEthernetConfig(String configString) { + String[] tokens = configString.split(";"); + String name = tokens[0]; + String capabilities = tokens.length > 1 ? tokens[1] : null; + NetworkCapabilities nc = createNetworkCapabilities( + !TextUtils.isEmpty(capabilities) /* clear default capabilities */, capabilities); + mNetworkCapabilities.put(name, nc); + + if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) { + IpConfiguration ipConfig = createStaticIpConfiguration(tokens[2]); + mIpConfigurations.put(name, ipConfig); + } + } + + private static NetworkCapabilities createDefaultNetworkCapabilities() { + NetworkCapabilities nc = createNetworkCapabilities(false /* clear default capabilities */); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); + + return nc; + } + + private static NetworkCapabilities createNetworkCapabilities(boolean clearDefaultCapabilities) { + return createNetworkCapabilities(clearDefaultCapabilities, null); + } + + private static NetworkCapabilities createNetworkCapabilities( + boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities) { + + NetworkCapabilities nc = new NetworkCapabilities(); + if (clearDefaultCapabilities) { + nc.clearAll(); // Remove default capabilities. + } + nc.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); + nc.setLinkUpstreamBandwidthKbps(100 * 1000); + nc.setLinkDownstreamBandwidthKbps(100 * 1000); + + if (!TextUtils.isEmpty(commaSeparatedCapabilities)) { + for (String strNetworkCapability : commaSeparatedCapabilities.split(",")) { + if (!TextUtils.isEmpty(strNetworkCapability)) { + nc.addCapability(Integer.valueOf(strNetworkCapability)); + } + } + } + + return nc; + } + + private static IpConfiguration createStaticIpConfiguration(String strIpAddress) { + StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); + staticIpConfiguration.ipAddress = new LinkAddress(strIpAddress); + return new IpConfiguration( + IpAssignment.STATIC, ProxySettings.NONE, staticIpConfiguration, null); + } + + private static IpConfiguration createDefaultIpConfiguration() { + return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); + } + + private void postAndWaitForRunnable(Runnable r) { + mHandler.runWithScissors(r, 2000L /* timeout */); + } + + void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { + postAndWaitForRunnable(() -> { + pw.println(getClass().getSimpleName()); + pw.println("Ethernet interface name filter: " + mIfaceMatch); + pw.println("Listeners: " + mListeners.getRegisteredCallbackCount()); + pw.println("IP Configurations:"); + pw.increaseIndent(); + for (String iface : mIpConfigurations.keySet()) { + pw.println(iface + ": " + mIpConfigurations.get(iface)); + } + pw.decreaseIndent(); + pw.println(); + + pw.println("Network Capabilities:"); + pw.increaseIndent(); + for (String iface : mNetworkCapabilities.keySet()) { + pw.println(iface + ": " + mNetworkCapabilities.get(iface)); + } + pw.decreaseIndent(); + pw.println(); + + mFactory.dump(fd, pw, args); + }); + } +} From 51b4917dd30455cb4fe3d9bd5a302b29fb5ab0a4 Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Tue, 31 Oct 2017 15:34:16 -0700 Subject: [PATCH 112/881] Enable multiple active Ethernet interfaces - add Ethernet interface configurations to config.xml; no vendors can specify network capabilities (in particular they can mark network as restricted which make sense for embedded applications + static IP configuration) - extend EthernetManager to support multiple interfaces, use interface name as an identificator - extend IpConfigStore to store IP configuration based on string identifier (e.g. ethernet name) Test: runtest -x frameworks/base/services/tests/servicestests/ -c com.android.server.net.IpConfigStoreTest Change-Id: Ic1e70003f2380ca8edb4469d6b34e27c5e8cf059 --- core/java/android/net/EthernetManager.java | 49 ++++-- core/java/android/net/IEthernetManager.aidl | 7 +- .../android/net/IEthernetServiceListener.aidl | 2 +- .../com/android/server/net/IpConfigStore.java | 100 ++++++++++--- .../android/server/net/IpConfigStoreTest.java | 140 ++++++++++++++++++ 5 files changed, 259 insertions(+), 39 deletions(-) create mode 100644 services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 31a30968cb..ecccda588a 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -18,9 +18,6 @@ package android.net; import android.annotation.SystemService; import android.content.Context; -import android.net.IEthernetManager; -import android.net.IEthernetServiceListener; -import android.net.IpConfiguration; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -45,18 +42,18 @@ public class EthernetManager { if (msg.what == MSG_AVAILABILITY_CHANGED) { boolean isAvailable = (msg.arg1 == 1); for (Listener listener : mListeners) { - listener.onAvailabilityChanged(isAvailable); + listener.onAvailabilityChanged((String) msg.obj, isAvailable); } } } }; - private final ArrayList mListeners = new ArrayList(); + private final ArrayList mListeners = new ArrayList<>(); private final IEthernetServiceListener.Stub mServiceListener = new IEthernetServiceListener.Stub() { @Override - public void onAvailabilityChanged(boolean isAvailable) { + public void onAvailabilityChanged(String iface, boolean isAvailable) { mHandler.obtainMessage( - MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, null).sendToTarget(); + MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, iface).sendToTarget(); } }; @@ -66,9 +63,10 @@ public class EthernetManager { public interface Listener { /** * Called when Ethernet port's availability is changed. - * @param isAvailable {@code true} if one or more Ethernet port exists. + * @param iface Ethernet interface name + * @param isAvailable {@code true} if Ethernet port exists. */ - public void onAvailabilityChanged(boolean isAvailable); + void onAvailabilityChanged(String iface, boolean isAvailable); } /** @@ -86,9 +84,9 @@ public class EthernetManager { * Get Ethernet configuration. * @return the Ethernet Configuration, contained in {@link IpConfiguration}. */ - public IpConfiguration getConfiguration() { + public IpConfiguration getConfiguration(String iface) { try { - return mService.getConfiguration(); + return mService.getConfiguration(iface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -97,21 +95,29 @@ public class EthernetManager { /** * Set Ethernet configuration. */ - public void setConfiguration(IpConfiguration config) { + public void setConfiguration(String iface, IpConfiguration config) { try { - mService.setConfiguration(config); + mService.setConfiguration(iface, config); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Indicates whether the system currently has one or more - * Ethernet interfaces. + * Indicates whether the system currently has one or more Ethernet interfaces. */ public boolean isAvailable() { + return getAvailableInterfaces().length > 0; + } + + /** + * Indicates whether the system has given interface. + * + * @param iface Ethernet interface name + */ + public boolean isAvailable(String iface) { try { - return mService.isAvailable(); + return mService.isAvailable(iface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -136,6 +142,17 @@ public class EthernetManager { } } + /** + * Returns an array of available Ethernet interface names. + */ + public String[] getAvailableInterfaces() { + try { + return mService.getAvailableInterfaces(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + /** * Removes a listener. * @param listener A {@link Listener} to remove. diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl index 7a92eb955a..94960b51d3 100644 --- a/core/java/android/net/IEthernetManager.aidl +++ b/core/java/android/net/IEthernetManager.aidl @@ -26,9 +26,10 @@ import android.net.IEthernetServiceListener; /** {@hide} */ interface IEthernetManager { - IpConfiguration getConfiguration(); - void setConfiguration(in IpConfiguration config); - boolean isAvailable(); + String[] getAvailableInterfaces(); + IpConfiguration getConfiguration(String iface); + void setConfiguration(String iface, in IpConfiguration config); + boolean isAvailable(String iface); void addListener(in IEthernetServiceListener listener); void removeListener(in IEthernetServiceListener listener); } diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/core/java/android/net/IEthernetServiceListener.aidl index 356690e8f7..782fa19d9d 100644 --- a/core/java/android/net/IEthernetServiceListener.aidl +++ b/core/java/android/net/IEthernetServiceListener.aidl @@ -19,5 +19,5 @@ package android.net; /** @hide */ oneway interface IEthernetServiceListener { - void onAvailabilityChanged(boolean isAvailable); + void onAvailabilityChanged(String iface, boolean isAvailable); } diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index 4d56468f2f..e3e02e32ad 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -24,11 +24,11 @@ import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.StaticIpConfiguration; +import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.net.DelayedDiskWrite; import java.io.BufferedInputStream; import java.io.DataInputStream; @@ -38,8 +38,8 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.net.InetAddress; import java.net.Inet4Address; +import java.net.InetAddress; public class IpConfigStore { private static final String TAG = "IpConfigStore"; @@ -60,7 +60,7 @@ public class IpConfigStore { protected static final String EXCLUSION_LIST_KEY = "exclusionList"; protected static final String EOS = "eos"; - protected static final int IPCONFIG_FILE_VERSION = 2; + protected static final int IPCONFIG_FILE_VERSION = 3; public IpConfigStore(DelayedDiskWrite writer) { mWriter = writer; @@ -70,9 +70,14 @@ public class IpConfigStore { this(new DelayedDiskWrite()); } + private static boolean writeConfig(DataOutputStream out, String configKey, + IpConfiguration config) throws IOException { + return writeConfig(out, configKey, config, IPCONFIG_FILE_VERSION); + } + @VisibleForTesting - public static boolean writeConfig(DataOutputStream out, int configKey, - IpConfiguration config) throws IOException { + public static boolean writeConfig(DataOutputStream out, String configKey, + IpConfiguration config, int version) throws IOException { boolean written = false; try { @@ -153,7 +158,11 @@ public class IpConfigStore { if (written) { out.writeUTF(ID_KEY); - out.writeInt(configKey); + if (version < 3) { + out.writeInt(Integer.valueOf(configKey)); + } else { + out.writeUTF(configKey); + } } } catch (NullPointerException e) { loge("Failure in writing " + config + e); @@ -163,18 +172,47 @@ public class IpConfigStore { return written; } - public void writeIpAndProxyConfigurations(String filePath, + /** + * @Deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead. + * New method uses string as network identifier which could be interface name or MAC address or + * other token. + */ + @Deprecated + public void writeIpAndProxyConfigurationsToFile(String filePath, final SparseArray networks) { - mWriter.write(filePath, new DelayedDiskWrite.Writer() { - public void onWriteCalled(DataOutputStream out) throws IOException{ - out.writeInt(IPCONFIG_FILE_VERSION); - for(int i = 0; i < networks.size(); i++) { - writeConfig(out, networks.keyAt(i), networks.valueAt(i)); - } + mWriter.write(filePath, out -> { + out.writeInt(IPCONFIG_FILE_VERSION); + for(int i = 0; i < networks.size(); i++) { + writeConfig(out, String.valueOf(networks.keyAt(i)), networks.valueAt(i)); } }); } + public void writeIpConfigurations(String filePath, + ArrayMap networks) { + mWriter.write(filePath, out -> { + out.writeInt(IPCONFIG_FILE_VERSION); + for(int i = 0; i < networks.size(); i++) { + writeConfig(out, networks.keyAt(i), networks.valueAt(i)); + } + }); + } + + public static ArrayMap readIpConfigurations(String filePath) { + BufferedInputStream bufferedInputStream; + try { + bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath)); + } catch (FileNotFoundException e) { + // Return an empty array here because callers expect an empty array when the file is + // not present. + loge("Error opening configuration file: " + e); + return new ArrayMap<>(0); + } + return readIpConfigurations(bufferedInputStream); + } + + /** @Deprecated use {@link #readIpConfigurations(String)} */ + @Deprecated public static SparseArray readIpAndProxyConfigurations(String filePath) { BufferedInputStream bufferedInputStream; try { @@ -188,21 +226,40 @@ public class IpConfigStore { return readIpAndProxyConfigurations(bufferedInputStream); } + /** @Deprecated use {@link #readIpConfigurations(InputStream)} */ + @Deprecated public static SparseArray readIpAndProxyConfigurations( InputStream inputStream) { - SparseArray networks = new SparseArray(); + ArrayMap networks = readIpConfigurations(inputStream); + if (networks == null) { + return null; + } + + SparseArray networksById = new SparseArray<>(); + for (int i = 0; i < networks.size(); i++) { + int id = Integer.valueOf(networks.keyAt(i)); + networksById.put(id, networks.valueAt(i)); + } + + return networksById; + } + + /** Returns a map of network identity token and {@link IpConfiguration}. */ + public static ArrayMap readIpConfigurations( + InputStream inputStream) { + ArrayMap networks = new ArrayMap<>(); DataInputStream in = null; try { in = new DataInputStream(inputStream); int version = in.readInt(); - if (version != 2 && version != 1) { + if (version != 3 && version != 2 && version != 1) { loge("Bad version on IP configuration file, ignore read"); return null; } while (true) { - int id = -1; + String uniqueToken = null; // Default is DHCP with no proxy IpAssignment ipAssignment = IpAssignment.DHCP; ProxySettings proxySettings = ProxySettings.NONE; @@ -217,7 +274,12 @@ public class IpConfigStore { key = in.readUTF(); try { if (key.equals(ID_KEY)) { - id = in.readInt(); + if (version < 3) { + int id = in.readInt(); + uniqueToken = String.valueOf(id); + } else { + uniqueToken = in.readUTF(); + } } else if (key.equals(IP_ASSIGNMENT_KEY)) { ipAssignment = IpAssignment.valueOf(in.readUTF()); } else if (key.equals(LINK_ADDRESS_KEY)) { @@ -280,9 +342,9 @@ public class IpConfigStore { } } while (true); - if (id != -1) { + if (uniqueToken != null) { IpConfiguration config = new IpConfiguration(); - networks.put(id, config); + networks.put(uniqueToken, config); switch (ipAssignment) { case STATIC: diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java new file mode 100644 index 0000000000..9f4b754621 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.NetworkUtils; +import android.net.ProxyInfo; +import android.net.StaticIpConfiguration; +import android.support.test.runner.AndroidJUnit4; +import android.util.ArrayMap; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Unit tests for {@link IpConfigStore} + */ +@RunWith(AndroidJUnit4.class) +public class IpConfigStoreTest { + + @Test + public void backwardCompatibility2to3() throws IOException { + final int KEY_CONFIG = 17; + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + DataOutputStream outputStream = new DataOutputStream(byteStream); + + IpConfiguration expectedConfig = new IpConfiguration(IpAssignment.DHCP, + ProxySettings.NONE, null, null); + + // Emulate writing to old format. + writeDhcpConfigV2(outputStream, KEY_CONFIG, expectedConfig); + + InputStream in = new ByteArrayInputStream(byteStream.toByteArray()); + ArrayMap configurations = IpConfigStore.readIpConfigurations(in); + + assertNotNull(configurations); + assertEquals(1, configurations.size()); + IpConfiguration actualConfig = configurations.get(String.valueOf(KEY_CONFIG)); + assertNotNull(actualConfig); + assertEquals(expectedConfig, actualConfig); + } + + @Test + public void staticIpMultiNetworks() throws Exception { + final String IFACE_1 = "eth0"; + final String IFACE_2 = "eth1"; + final String IP_ADDR_1 = "192.168.1.10/24"; + final String IP_ADDR_2 = "192.168.1.20/24"; + final String DNS_IP_ADDR_1 = "1.2.3.4"; + final String DNS_IP_ADDR_2 = "5.6.7.8"; + + StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); + staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1); + staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1)); + staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2)); + + ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2"); + + IpConfiguration expectedConfig1 = new IpConfiguration(IpAssignment.STATIC, + ProxySettings.STATIC, staticIpConfiguration, proxyInfo); + IpConfiguration expectedConfig2 = new IpConfiguration(expectedConfig1); + expectedConfig2.getStaticIpConfiguration().ipAddress = new LinkAddress(IP_ADDR_2); + + ArrayMap expectedNetworks = new ArrayMap<>(); + expectedNetworks.put(IFACE_1, expectedConfig1); + expectedNetworks.put(IFACE_2, expectedConfig2); + + MockedDelayedDiskWrite writer = new MockedDelayedDiskWrite(); + IpConfigStore store = new IpConfigStore(writer); + store.writeIpConfigurations("file/path/not/used/", expectedNetworks); + + InputStream in = new ByteArrayInputStream(writer.byteStream.toByteArray()); + ArrayMap actualNetworks = IpConfigStore.readIpConfigurations(in); + assertNotNull(actualNetworks); + assertEquals(2, actualNetworks.size()); + assertEquals(expectedNetworks.get(IFACE_1), actualNetworks.get(IFACE_1)); + assertEquals(expectedNetworks.get(IFACE_2), actualNetworks.get(IFACE_2)); + } + + // This is simplified snapshot of code that was used to store values in V2 format (key as int). + private static void writeDhcpConfigV2(DataOutputStream out, int configKey, + IpConfiguration config) throws IOException { + out.writeInt(2); // VERSION 2 + switch (config.ipAssignment) { + case DHCP: + out.writeUTF("ipAssignment"); + out.writeUTF(config.ipAssignment.toString()); + break; + default: + fail("Not supported in test environment"); + } + + out.writeUTF("id"); + out.writeInt(configKey); + out.writeUTF("eos"); + } + + /** Synchronously writes into given byte steam */ + private static class MockedDelayedDiskWrite extends DelayedDiskWrite { + final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + + @Override + public void write(String filePath, Writer w) { + DataOutputStream outputStream = new DataOutputStream(byteStream); + + try { + w.onWriteCalled(outputStream); + } catch (IOException e) { + fail(); + } + } + } +} From 7f880c99407d4233e4e32328d89e40e676832164 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Thu, 25 Jan 2018 11:43:52 -0800 Subject: [PATCH 113/881] Return non-negetive value in getMobileStats method The current implementation of getMobileRxBytes and all the similiar method adds up the return values for multiple calls to getRxBytes so if all of them return UNSUPPORTED for any reason, getMobileRxBytes() would return a value such as -3. This behavior is not compliance with the cts TrafficStatsTest which always assume getMobileRxBytes to return a non-negetive value. The method now will check tha stats get from getRxBytes method and add them up only if the stats is valid. Bug: 72473294 Test: run cts -m CtsNetTestCases -t android.net.cts.TrafficStatsTest Change-Id: I656970ebc8f6506cf17c4353ad46c0178bb65cfd --- core/java/android/net/TrafficStats.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 196a3bc9c8..fa4624ef56 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -433,6 +433,10 @@ public class TrafficStats { } } + private static long addIfSupported(long stat) { + return (stat == UNSUPPORTED) ? 0 : stat; + } + /** * Return number of packets transmitted across mobile networks since device * boot. Counts packets across all mobile network interfaces, and always @@ -445,7 +449,7 @@ public class TrafficStats { public static long getMobileTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - total += getTxPackets(iface); + total += addIfSupported(getTxPackets(iface)); } return total; } @@ -462,7 +466,7 @@ public class TrafficStats { public static long getMobileRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { - total += getRxPackets(iface); + total += addIfSupported(getRxPackets(iface)); } return total; } @@ -479,7 +483,7 @@ public class TrafficStats { public static long getMobileTxBytes() { long total = 0; for (String iface : getMobileIfaces()) { - total += getTxBytes(iface); + total += addIfSupported(getTxBytes(iface)); } return total; } @@ -496,7 +500,7 @@ public class TrafficStats { public static long getMobileRxBytes() { long total = 0; for (String iface : getMobileIfaces()) { - total += getRxBytes(iface); + total += addIfSupported(getRxBytes(iface)); } return total; } @@ -511,9 +515,7 @@ public class TrafficStats { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (stat != UNSUPPORTED) { - total += stat; - } + total += addIfSupported(stat); } return total; } @@ -528,9 +530,7 @@ public class TrafficStats { } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (stat != UNSUPPORTED) { - total += stat; - } + total += addIfSupported(stat); } return total; } From 72a82a752a4b5f25bfc75057409e1ee01ae44b02 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 24 Jan 2018 15:31:39 -0800 Subject: [PATCH 114/881] Fix minor bugs with tunnel mode implementation This change makes sure tunnel mode transforms are properly activated upon construction, and corrects bugs with how policy selectors were being generated for tunnel mode policies. Specifically, the source/destination could not be empty strings, even for cases where an empty selector was desired. Bug: 72457770 Test: GTS tests run Change-Id: I9a9f64c34b07883a02a5c996614f958486d214fc --- core/java/android/net/IpSecTransform.java | 2 +- .../java/com/android/server/IpSecService.java | 57 +++++++++++-------- 2 files changed, 35 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 9ccdbe2b1b..0829b4a3e9 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -462,7 +462,7 @@ public final class IpSecTransform implements AutoCloseable { mConfig.setMode(MODE_TUNNEL); mConfig.setSourceAddress(sourceAddress.getHostAddress()); mConfig.setSpiResourceId(spi.getResourceId()); - return new IpSecTransform(mContext, mConfig); + return new IpSecTransform(mContext, mConfig).activate(); } /** diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index fe4ac6d771..a07a982abc 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -87,6 +87,7 @@ public class IpSecService extends IIpSecService.Stub { private static final String NETD_SERVICE_NAME = "netd"; private static final int[] DIRECTIONS = new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN}; + private static final String[] WILDCARD_ADDRESSES = new String[]{"0.0.0.0", "::"}; private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms private static final int MAX_PORT_BIND_ATTEMPTS = 10; @@ -413,12 +414,16 @@ public class IpSecService extends IIpSecService.Stub { .append(mTransformQuotaTracker) .append(", mSocketQuotaTracker=") .append(mSocketQuotaTracker) + .append(", mTunnelQuotaTracker=") + .append(mTunnelQuotaTracker) .append(", mSpiRecords=") .append(mSpiRecords) .append(", mTransformRecords=") .append(mTransformRecords) .append(", mEncapSocketRecords=") .append(mEncapSocketRecords) + .append(", mTunnelInterfaceRecords=") + .append(mTunnelInterfaceRecords) .append("}") .toString(); } @@ -815,12 +820,14 @@ public class IpSecService extends IIpSecService.Stub { try { mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName); - for (int direction : DIRECTIONS) { - int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey; - mSrvConfig - .getNetdInstance() - .ipSecDeleteSecurityPolicy( - 0, direction, mLocalAddress, mRemoteAddress, mark, 0xffffffff); + for(String wildcardAddr : WILDCARD_ADDRESSES) { + for (int direction : DIRECTIONS) { + int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey; + mSrvConfig + .getNetdInstance() + .ipSecDeleteSecurityPolicy( + 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff); + } } } catch (ServiceSpecificException e) { // FIXME: get the error code and throw is at an IOException from Errno Exception @@ -1261,19 +1268,21 @@ public class IpSecService extends IIpSecService.Stub { .getNetdInstance() .addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey); - for (int direction : DIRECTIONS) { - int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey; + for(String wildcardAddr : WILDCARD_ADDRESSES) { + for (int direction : DIRECTIONS) { + int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey; - mSrvConfig - .getNetdInstance() - .ipSecAddSecurityPolicy( + mSrvConfig + .getNetdInstance() + .ipSecAddSecurityPolicy( 0, // Use 0 for reqId direction, - "", - "", + wildcardAddr, + wildcardAddr, 0, mark, 0xffffffff); + } } userRecord.mTunnelInterfaceRecords.put( @@ -1646,16 +1655,18 @@ public class IpSecService extends IIpSecService.Stub { c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork()); // If outbound, also add SPI to the policy. - mSrvConfig - .getNetdInstance() - .ipSecUpdateSecurityPolicy( - 0, // Use 0 for reqId - direction, - "", - "", - transformInfo.getSpiRecord().getSpi(), - mark, - 0xffffffff); + for(String wildcardAddr : WILDCARD_ADDRESSES) { + mSrvConfig + .getNetdInstance() + .ipSecUpdateSecurityPolicy( + 0, // Use 0 for reqId + direction, + wildcardAddr, + wildcardAddr, + transformInfo.getSpiRecord().getSpi(), + mark, + 0xffffffff); + } } // Update SA with tunnel mark (ikey or okey based on direction) From 14b84ea14ac4639a1b51111b8fcaedbd7b1e3146 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 5 Feb 2018 17:19:22 -0800 Subject: [PATCH 115/881] Frameworks: Annotate trivial @GuardedBy in services/core Add @GuardedBy for simple functions that require a single lock and are named XYZLocked. Derived by errorprone. Bug: 73000847 Test: m Test: m javac-check-framework RUN_ERROR_PRONE=true Change-Id: I6993325b11c71a4ec27c21935fb54a954d95455f --- .../com/android/server/net/NetworkStatsService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index bfc150e1a9..76c4db1340 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -405,6 +405,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags); } + @GuardedBy("mStatsLock") private void shutdownLocked() { mContext.unregisterReceiver(mTetherReceiver); mContext.unregisterReceiver(mPollReceiver); @@ -431,6 +432,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSystemReady = false; } + @GuardedBy("mStatsLock") private void maybeUpgradeLegacyStatsLocked() { File file; try { @@ -909,6 +911,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * reflect current {@link #mPersistThreshold} value. Always defers to * {@link Global} values when defined. */ + @GuardedBy("mStatsLock") private void updatePersistThresholdsLocked() { mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold)); mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold)); @@ -1029,6 +1032,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * are active on a single {@code iface}, they are combined under a single * {@link NetworkIdentitySet}. */ + @GuardedBy("mStatsLock") private void updateIfacesLocked(Network[] defaultNetworks) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1128,6 +1132,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return ident; } + @GuardedBy("mStatsLock") private void recordSnapshotLocked(long currentTime) throws RemoteException { // snapshot and record current counters; read UID stats first to // avoid over counting dev stats. @@ -1163,6 +1168,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Bootstrap initial stats snapshot, usually during {@link #systemReady()} * so we have baseline values without double-counting. */ + @GuardedBy("mStatsLock") private void bootstrapStatsLocked() { final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); @@ -1197,6 +1203,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Periodic poll operation, reading current statistics and recording into * {@link NetworkStatsHistory}. */ + @GuardedBy("mStatsLock") private void performPollLocked(int flags) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); @@ -1258,6 +1265,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Sample recent statistics summary into {@link EventLog}. */ + @GuardedBy("mStatsLock") private void performSampleLocked() { // TODO: migrate trustedtime fixes to separate binary log events final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1; @@ -1295,6 +1303,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Clean up {@link #mUidRecorder} after UID is removed. */ + @GuardedBy("mStatsLock") private void removeUidsLocked(int... uids) { if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids)); @@ -1313,6 +1322,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Clean up {@link #mUidRecorder} after user is removed. */ + @GuardedBy("mStatsLock") private void removeUserLocked(int userId) { if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId); @@ -1434,6 +1444,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + @GuardedBy("mStatsLock") private void dumpProtoLocked(FileDescriptor fd) { final ProtoOutputStream proto = new ProtoOutputStream(fd); From 1b33ea09492c0606a2ee56d41fecd2acb7ee6ff0 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Fri, 2 Feb 2018 18:34:25 -0800 Subject: [PATCH 116/881] Require NETWORK_STACK Permission for IpSec Tunnel Mode At least until further permissions are agreed upon, the NETWORK_STACK permission is sufficient to ensure that access to the tunnel mode APIs is secure, and this permission will always be a sufficient condition. Thus, adding NETWORK_STACK. Bug: 66955045 Test: compilation Change-Id: I2dc36896a52d2e71fad55041507d68ca91191ffc --- core/java/android/net/IpSecManager.java | 3 +++ core/java/android/net/IpSecTransform.java | 10 ++++++++++ .../core/java/com/android/server/IpSecService.java | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 24a078fccc..b60984771a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -19,6 +19,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; @@ -761,6 +762,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { @@ -780,6 +782,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction, IpSecTransform transform) throws IOException { try { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 0829b4a3e9..38759a9183 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; import android.os.Binder; @@ -266,6 +267,10 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD + }) public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback, int intervalSeconds, @NonNull Handler handler) throws IOException { checkNotNull(userCallback); @@ -305,6 +310,10 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD + }) public void stopNattKeepalive() { synchronized (mKeepaliveCallback) { if (mKeepalive == null) { @@ -449,6 +458,7 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index a07a982abc..45a4dfb91b 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1438,7 +1438,9 @@ public class IpSecService extends IIpSecService.Stub { switch (config.getMode()) { case IpSecTransform.MODE_TRANSPORT: + break; case IpSecTransform.MODE_TUNNEL: + enforceNetworkStackPermission(); break; default: throw new IllegalArgumentException( @@ -1446,6 +1448,11 @@ public class IpSecService extends IIpSecService.Stub { } } + private void enforceNetworkStackPermission() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK, + "IpSecService"); + } + private void createOrUpdateTransform( IpSecConfig c, int resourceId, SpiRecord spiRecord, EncapSocketRecord socketRecord) throws RemoteException { @@ -1615,6 +1622,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void applyTunnelModeTransform( int tunnelResourceId, int direction, int transformResourceId) throws RemoteException { + enforceNetworkStackPermission(); checkDirection(direction); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); From 3a637c7a5572febe683de4d90578d684202b9905 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 9 Feb 2018 10:06:59 -0700 Subject: [PATCH 117/881] Shore up dividing by zero protections. We're already trying to protect against zero elsewhere in this file, but we've seen evidence of it still happening, so add last-ditch protections. Test: builds, boots Bug: 73060623 Change-Id: I0549ed08f906521a8dbd9ff6162f80fa9b388434 --- .../core/java/com/android/server/net/NetworkStatsCollection.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 961a451778..3cc4d83267 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -187,6 +187,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { */ @VisibleForTesting public static long multiplySafe(long value, long num, long den) { + if (den == 0) den = 1; long x = value; long y = num; From 1df43871a02aa5c7ff7361435909548da17e9c10 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 9 Feb 2018 10:06:59 -0700 Subject: [PATCH 118/881] Shore up dividing by zero protections. We're already trying to protect against zero elsewhere in this file, but we've seen evidence of it still happening, so add last-ditch protections. Test: builds, boots Bug: 73060623 Change-Id: I0549ed08f906521a8dbd9ff6162f80fa9b388434 (cherry picked from commit a7be8da9adefaf6d55f7c90b95d0c6f9e66fca63) --- .../core/java/com/android/server/net/NetworkStatsCollection.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 961a451778..3cc4d83267 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -187,6 +187,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { */ @VisibleForTesting public static long multiplySafe(long value, long num, long den) { + if (den == 0) den = 1; long x = value; long y = num; From 3899300c2978fc8c609fe30e7f0666dc010c455c Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 6 Feb 2018 20:43:21 -0800 Subject: [PATCH 119/881] Copy IpSecConfig when IpSecTransforms are created This change prevents IpSecTransforms from being inadvertently modified by changes to the IpSecConfig. Specifically, once the transform is created, it takes a copy of the config, rather than a reference. Bug: 69385347 Test: New tests added, and all test passing Change-Id: I89b8660c175ca20aa70352dcda893434ff7fd42b --- core/java/android/net/IpSecConfig.java | 19 +++++++++++++++++++ core/java/android/net/IpSecTransform.java | 18 ++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 6a262e2c87..8599f47c62 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -218,6 +218,25 @@ public final class IpSecConfig implements Parcelable { @VisibleForTesting public IpSecConfig() {} + /** Copy constructor */ + @VisibleForTesting + public IpSecConfig(IpSecConfig c) { + mMode = c.mMode; + mSourceAddress = c.mSourceAddress; + mDestinationAddress = c.mDestinationAddress; + mNetwork = c.mNetwork; + mSpiResourceId = c.mSpiResourceId; + mEncryption = c.mEncryption; + mAuthentication = c.mAuthentication; + mAuthenticatedEncryption = c.mAuthenticatedEncryption; + mEncapType = c.mEncapType; + mEncapSocketResourceId = c.mEncapSocketResourceId; + mEncapRemotePort = c.mEncapRemotePort; + mNattKeepaliveInterval = c.mNattKeepaliveInterval; + mMarkValue = c.mMarkValue; + mMarkMask = c.mMarkMask; + } + private IpSecConfig(Parcel in) { mMode = in.readInt(); mSourceAddress = in.readString(); diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 38759a9183..60e96f9434 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -84,9 +84,11 @@ public final class IpSecTransform implements AutoCloseable { @Retention(RetentionPolicy.SOURCE) public @interface EncapType {} - private IpSecTransform(Context context, IpSecConfig config) { + /** @hide */ + @VisibleForTesting + public IpSecTransform(Context context, IpSecConfig config) { mContext = context; - mConfig = config; + mConfig = new IpSecConfig(config); mResourceId = INVALID_RESOURCE_ID; } @@ -142,6 +144,18 @@ public final class IpSecTransform implements AutoCloseable { return this; } + /** + * Equals method used for testing + * + * @hide + */ + @VisibleForTesting + public static boolean equals(IpSecTransform lhs, IpSecTransform rhs) { + if (lhs == null || rhs == null) return (lhs == rhs); + return IpSecConfig.equals(lhs.getConfig(), rhs.getConfig()) + && lhs.mResourceId == rhs.mResourceId; + } + /** * Deactivate this {@code IpSecTransform} and free allocated resources. * From 8b0e926d8e127c6cdb0f40e5c1985056868aa723 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 14 Feb 2018 22:29:11 -0700 Subject: [PATCH 120/881] Better handling of NTP-based clocks. Now that we have a nice Clock abstraction, we can use it to represent a clock backed by an NTP fix. (This makes testing logic much easier to write.) We now rely completely on NetworkTimeUpdateService to keep our NTP fix up to date, instead of trying to refresh in the middle of critical paths which could trigger random ANRs. Add internal FallbackClock to make it easier to handle missing NTP fixes. Add internal SimpleClock to let implementers focus on single millis() method. Test: bit FrameworksNetTests:com.android.server.net.NetworkStatsServiceTest Test: bit FrameworksServicesTests:com.android.server.NetworkPolicyManagerServiceTest Bug: 69714690, 72320957 Change-Id: Ic32cdcbe093d08b73b0e4b23d6910b23ea8e1968 Exempt-From-Owner-Approval: approved in previous PS --- .../server/net/NetworkStatsService.java | 51 ++++++++----------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 76c4db1340..d1aa21276b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -68,6 +68,7 @@ import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; +import android.annotation.NonNull; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.usage.NetworkStatsManager; @@ -97,6 +98,7 @@ import android.net.TrafficStats; import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; +import android.os.BestClock; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -120,10 +122,8 @@ import android.util.ArraySet; import android.util.EventLog; import android.util.Log; import android.util.MathUtils; -import android.util.NtpTrustedTime; import android.util.Slog; import android.util.SparseIntArray; -import android.util.TrustedTime; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; @@ -140,6 +140,8 @@ import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.time.Clock; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -167,7 +169,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final Context mContext; private final INetworkManagementService mNetworkManager; private final AlarmManager mAlarmManager; - private final TrustedTime mTime; + private final Clock mClock; private final TelephonyManager mTeleManager; private final NetworkStatsSettings mSettings; private final NetworkStatsObservers mStatsObservers; @@ -202,7 +204,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ public interface NetworkStatsSettings { public long getPollInterval(); - public long getTimeCacheMaxAge(); public boolean getSampleEnabled(); public boolean getAugmentEnabled(); @@ -281,16 +282,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private long mPersistThreshold = 2 * MB_IN_BYTES; private long mGlobalAlertBytes; - private static File getDefaultSystemDir() { + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } - private static File getDefaultBaseDir() { + private static @NonNull File getDefaultBaseDir() { File baseDir = new File(getDefaultSystemDir(), "netstats"); baseDir.mkdirs(); return baseDir; } + private static @NonNull Clock getDefaultClock() { + return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(), + Clock.systemUTC()); + } + public static NetworkStatsService create(Context context, INetworkManagementService networkManager) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); @@ -299,7 +305,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, NtpTrustedTime.getInstance(context), TelephonyManager.getDefault(), + wakeLock, getDefaultClock(), TelephonyManager.getDefault(), new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); @@ -313,13 +319,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, - AlarmManager alarmManager, PowerManager.WakeLock wakeLock, TrustedTime time, + AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, TelephonyManager teleManager, NetworkStatsSettings settings, NetworkStatsObservers statsObservers, File systemDir, File baseDir) { mContext = checkNotNull(context, "missing Context"); mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService"); mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager"); - mTime = checkNotNull(time, "missing TrustedTime"); + mClock = checkNotNull(clock, "missing Clock"); mSettings = checkNotNull(settings, "missing NetworkStatsSettings"); mTeleManager = checkNotNull(teleManager, "missing TelephonyManager"); mWakeLock = checkNotNull(wakeLock, "missing WakeLock"); @@ -413,8 +419,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); + final long currentTime = mClock.millis(); // persist any pending stats mDevRecorder.forcePersistLocked(currentTime); @@ -831,8 +836,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // update and persist if beyond new thresholds - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); + final long currentTime = mClock.millis(); synchronized (mStatsLock) { if (!mSystemReady) return; @@ -1170,8 +1174,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ @GuardedBy("mStatsLock") private void bootstrapStatsLocked() { - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); + final long currentTime = mClock.millis(); try { recordSnapshotLocked(currentTime); @@ -1183,11 +1186,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private void performPoll(int flags) { - // try refreshing time source when stale - if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) { - mTime.forceRefresh(); - } - synchronized (mStatsLock) { mWakeLock.acquire(); @@ -1215,8 +1213,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; // TODO: consider marking "untrusted" times in historical stats - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); + final long currentTime = mClock.millis(); try { recordSnapshotLocked(currentTime); @@ -1268,7 +1265,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private void performSampleLocked() { // TODO: migrate trustedtime fixes to separate binary log events - final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1; + final long currentTime = mClock.millis(); NetworkTemplate template; NetworkStats.Entry devTotal; @@ -1285,7 +1282,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, - trustedTime); + currentTime); // collect wifi sample template = buildTemplateWifiWildcard(); @@ -1297,7 +1294,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, - trustedTime); + currentTime); } /** @@ -1621,10 +1618,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); } @Override - public long getTimeCacheMaxAge() { - return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS); - } - @Override public long getGlobalAlertBytes(long def) { return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def); } From d0cd0bf0b273116ec1fd70acda85f34e5fc9d975 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 16 Feb 2018 16:28:25 -0700 Subject: [PATCH 121/881] Leave NetworkStatsService around during shutdown. We've seen system code continue to ask about network statistics during a shutdown, so keep our objects around to avoid crashing with NPEs. Test: builds, boots Bug: 73323432 Change-Id: I2654d37a59eb830ff32a2151ae6ad6a999a41677 --- .../java/com/android/server/net/NetworkStatsService.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 76c4db1340..02c3210b6b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -422,13 +422,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mUidRecorder.forcePersistLocked(currentTime); mUidTagRecorder.forcePersistLocked(currentTime); - mDevRecorder = null; - mXtRecorder = null; - mUidRecorder = null; - mUidTagRecorder = null; - - mXtStatsCached = null; - mSystemReady = false; } From 4757d55288c9f7e82dfae03b3785b8269fca5fa5 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 20 Feb 2018 13:36:14 -0700 Subject: [PATCH 122/881] Only emit debug logging when requested. Test: builds, boots Bug: 72556865 Change-Id: I69d5d760221ef907eeea38490f56243f0a3b9dcb --- .../java/com/android/server/net/NetworkStatsService.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4b80e98f85..32e15c9d9c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -152,7 +152,8 @@ import java.util.List; */ public class NetworkStatsService extends INetworkStatsService.Stub { static final String TAG = "NetworkStats"; - static final boolean LOGV = false; + static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); + static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE); private static final int MSG_PERFORM_POLL = 1; private static final int MSG_UPDATE_IFACES = 2; @@ -641,14 +642,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0 && (template.getMatchRule() == NetworkTemplate.MATCH_MOBILE_ALL) && mSettings.getAugmentEnabled()) { - Slog.d(TAG, "Resolving plan for " + template); + if (LOGD) Slog.d(TAG, "Resolving plan for " + template); final long token = Binder.clearCallingIdentity(); try { final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class); final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); for (int subId : sm.getActiveSubscriptionIdList()) { if (template.matchesSubscriberId(tm.getSubscriberId(subId))) { - Slog.d(TAG, "Found active matching subId " + subId); + if (LOGD) Slog.d(TAG, "Found active matching subId " + subId); final List plans = sm.getSubscriptionPlans(subId); if (!plans.isEmpty()) { plan = plans.get(0); @@ -658,7 +659,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } finally { Binder.restoreCallingIdentity(token); } - Slog.d(TAG, "Resolved to plan " + plan); + if (LOGD) Slog.d(TAG, "Resolved to plan " + plan); } return plan; } From 292624aac6bba3fc10ac9db618a2324e4e9b75d8 Mon Sep 17 00:00:00 2001 From: Luis Hector Chavez Date: Fri, 16 Feb 2018 14:59:53 -0800 Subject: [PATCH 123/881] Avoid re-creating an IpClient if the network has already started This change avoids calling start() on needNetworkFor() if an IpClient object has already been created. This is the case when the interface is connected from boot, as is the case in Chrome OS. Bug: 73396557 Test: Networking is 100% stable in Chrome OS Change-Id: Iaa073d6477aadca2e4e5233b333d717ad82c1f3d --- .../server/ethernet/EthernetNetworkFactory.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 29464b78ce..d4648795c6 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -280,11 +280,14 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void start() { + if (mIpClient != null) { + if (DBG) Log.d(TAG, "IpClient already started"); + return; + } if (DBG) { Log.d(TAG, String.format("starting IpClient(%s): mNetworkInfo=%s", name, mNetworkInfo)); } - if (mIpClient != null) stop(); mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress); @@ -325,6 +328,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void onIpLayerStopped(LinkProperties linkProperties) { // This cannot happen due to provisioning timeout, because our timeout is 0. It can only // happen if we're provisioned and we lose provisioning. + stop(); start(); } @@ -338,12 +342,11 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ boolean updateLinkState(boolean up) { if (mLinkUp == up) return false; - mLinkUp = up; + + stop(); if (up) { start(); - } else { - stop(); } return true; From 6cb094e96732a1f3df3403b13dd80083f2236e65 Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Wed, 21 Feb 2018 14:54:04 -0800 Subject: [PATCH 124/881] Wait for IpClient to shutdown This makes sure that we never accidentally have two IpClients vying for control of the same interface. Test: as follows - built - flashed - booted Bug: 62476366 Change-Id: Iab4ca7c2445e70b6f8beaf5dc6921cb0c6cd56ed --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index d4648795c6..f95500e6e8 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -355,8 +355,10 @@ public class EthernetNetworkFactory extends NetworkFactory { void stop() { if (mIpClient != null) { mIpClient.shutdown(); + mIpClient.awaitShutdown(); mIpClient = null; } + // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: // that sets the state to IDLE, and ConnectivityService will still think we're connected. From 82ffcf567c07d18129812ec6423d40c520cb7864 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 20 Feb 2018 17:24:55 -0700 Subject: [PATCH 125/881] Name specific app for rapid data usage. When a single app is responsible for more than half of the data usage that caused us to trigger a "rapid usage" alert, name that app in the notification. Tests to verify. Move NPMS->NSS direct calls to "Internal" pattern, following best-practices to avoid unnecessary AIDL exposure. Remove 3G/4G split mobile plan support, which has been deprecated for years and was never supported in a shipping product. Move MultipathPolicyTracker in tree to reflect its package name. Test: bit FrameworksNetTests:* Test: bit FrameworksServicesTests:com.android.server.NetworkPolicyManagerServiceTest Bug: 69263587, 64221505, 73431080, 72746951 Exempt-From-Owner-Approval: approved in previous PS Change-Id: I3e4ec1ae2222d51b232f76f32faca93d4f8cd272 --- .../android/net/INetworkStatsService.aidl | 9 -- core/java/android/net/NetworkStats.java | 35 +++--- .../java/android/net/NetworkStatsHistory.java | 17 +++ core/java/android/net/NetworkTemplate.java | 104 ++---------------- .../server/net/NetworkStatsCollection.java | 4 + .../server/net/NetworkStatsService.java | 72 +++++++++--- 6 files changed, 107 insertions(+), 134 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 90e3ffd550..381cfb61de 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -39,9 +39,6 @@ interface INetworkStatsService { */ INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); - /** Return network layer usage total for traffic that matches template. */ - long getNetworkTotalBytes(in NetworkTemplate template, long start, long end); - /** Return data layer snapshot of UID network usage. */ NetworkStats getDataLayerSnapshotForUid(int uid); /** Return set of any ifaces associated with mobile networks since boot. */ @@ -50,17 +47,11 @@ interface INetworkStatsService { /** Increment data layer count of operations performed for UID and tag. */ void incrementOperationCount(int uid, int tag, int operationCount); - /** Mark given UID as being in foreground for stats purposes. */ - void setUidForeground(int uid, boolean uidForeground); - /** Force update of ifaces. */ void forceUpdateIfaces(in Network[] defaultNetworks); /** Force update of statistics. */ void forceUpdate(); - /** Advise persistance threshold; may be overridden internally. */ - void advisePersistThreshold(long thresholdBytes); - /** Registers a callback on data usage. */ DataUsageRequest registerUsageCallback(String callingPackage, in DataUsageRequest request, in Messenger messenger, in IBinder binder); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 01b2b39213..16fb858a58 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -234,7 +234,7 @@ public class NetworkStats implements Parcelable { public NetworkStats(long elapsedRealtime, int initialSize) { this.elapsedRealtime = elapsedRealtime; this.size = 0; - if (initialSize >= 0) { + if (initialSize > 0) { this.capacity = initialSize; this.iface = new String[initialSize]; this.uid = new int[initialSize]; @@ -250,19 +250,7 @@ public class NetworkStats implements Parcelable { this.operations = new long[initialSize]; } else { // Special case for use by NetworkStatsFactory to start out *really* empty. - this.capacity = 0; - this.iface = EmptyArray.STRING; - this.uid = EmptyArray.INT; - this.set = EmptyArray.INT; - this.tag = EmptyArray.INT; - this.metered = EmptyArray.INT; - this.roaming = EmptyArray.INT; - this.defaultNetwork = EmptyArray.INT; - this.rxBytes = EmptyArray.LONG; - this.rxPackets = EmptyArray.LONG; - this.txBytes = EmptyArray.LONG; - this.txPackets = EmptyArray.LONG; - this.operations = EmptyArray.LONG; + clear(); } } @@ -314,6 +302,25 @@ public class NetworkStats implements Parcelable { return clone; } + /** + * Clear all data stored in this object. + */ + public void clear() { + this.capacity = 0; + this.iface = EmptyArray.STRING; + this.uid = EmptyArray.INT; + this.set = EmptyArray.INT; + this.tag = EmptyArray.INT; + this.metered = EmptyArray.INT; + this.roaming = EmptyArray.INT; + this.defaultNetwork = EmptyArray.INT; + this.rxBytes = EmptyArray.LONG; + this.rxPackets = EmptyArray.LONG; + this.txBytes = EmptyArray.LONG; + this.txPackets = EmptyArray.LONG; + this.operations = EmptyArray.LONG; + } + @VisibleForTesting public NetworkStats addIfaceValues( String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) { diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 433f9410cc..a13ad659e7 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -39,6 +39,8 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.util.IndentingPrintWriter; +import libcore.util.EmptyArray; + import java.io.CharArrayWriter; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -458,6 +460,21 @@ public class NetworkStatsHistory implements Parcelable { bucketCount++; } + /** + * Clear all data stored in this object. + */ + public void clear() { + bucketStart = EmptyArray.LONG; + if (activeTime != null) activeTime = EmptyArray.LONG; + if (rxBytes != null) rxBytes = EmptyArray.LONG; + if (rxPackets != null) rxPackets = EmptyArray.LONG; + if (txBytes != null) txBytes = EmptyArray.LONG; + if (txPackets != null) txPackets = EmptyArray.LONG; + if (operations != null) operations = EmptyArray.LONG; + bucketCount = 0; + totalBytes = 0; + } + /** * Remove buckets older than requested cutoff. */ diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 8efd39a7a7..74233fd990 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -23,7 +23,6 @@ import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIMAX; -import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; @@ -34,11 +33,6 @@ import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.removeDoubleQuotes; -import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G; -import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G; -import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G; -import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN; -import static android.telephony.TelephonyManager.getNetworkClass; import android.os.Parcel; import android.os.Parcelable; @@ -55,8 +49,8 @@ import java.util.Arrays; import java.util.Objects; /** - * Template definition used to generically match {@link NetworkIdentity}, - * usually when collecting statistics. + * Predicate used to match {@link NetworkIdentity}, usually when collecting + * statistics. (It should probably have been named {@code NetworkPredicate}.) * * @hide */ @@ -68,13 +62,7 @@ public class NetworkTemplate implements Parcelable { */ private static final int BACKUP_VERSION = 1; - public static final int MATCH_MOBILE_ALL = 1; - /** @deprecated don't use this any more */ - @Deprecated - public static final int MATCH_MOBILE_3G_LOWER = 2; - /** @deprecated don't use this any more */ - @Deprecated - public static final int MATCH_MOBILE_4G = 3; + public static final int MATCH_MOBILE = 1; public static final int MATCH_WIFI = 4; public static final int MATCH_ETHERNET = 5; public static final int MATCH_MOBILE_WILDCARD = 6; @@ -84,9 +72,7 @@ public class NetworkTemplate implements Parcelable { private static boolean isKnownMatchRule(final int rule) { switch (rule) { - case MATCH_MOBILE_ALL: - case MATCH_MOBILE_3G_LOWER: - case MATCH_MOBILE_4G: + case MATCH_MOBILE: case MATCH_WIFI: case MATCH_ETHERNET: case MATCH_MOBILE_WILDCARD: @@ -111,25 +97,7 @@ public class NetworkTemplate implements Parcelable { * the given IMSI. */ public static NetworkTemplate buildTemplateMobileAll(String subscriberId) { - return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId, null); - } - - /** - * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with - * the given IMSI that roughly meet a "3G" definition, or lower. - */ - @Deprecated - public static NetworkTemplate buildTemplateMobile3gLower(String subscriberId) { - return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId, null); - } - - /** - * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with - * the given IMSI that roughly meet a "4G" definition. - */ - @Deprecated - public static NetworkTemplate buildTemplateMobile4g(String subscriberId) { - return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null); + return new NetworkTemplate(MATCH_MOBILE, subscriberId, null); } /** @@ -307,9 +275,7 @@ public class NetworkTemplate implements Parcelable { public boolean isMatchRuleMobile() { switch (mMatchRule) { - case MATCH_MOBILE_3G_LOWER: - case MATCH_MOBILE_4G: - case MATCH_MOBILE_ALL: + case MATCH_MOBILE: case MATCH_MOBILE_WILDCARD: return true; default: @@ -348,12 +314,8 @@ public class NetworkTemplate implements Parcelable { if (!matchesDefaultNetwork(ident)) return false; switch (mMatchRule) { - case MATCH_MOBILE_ALL: + case MATCH_MOBILE: return matchesMobile(ident); - case MATCH_MOBILE_3G_LOWER: - return matchesMobile3gLower(ident); - case MATCH_MOBILE_4G: - return matchesMobile4g(ident); case MATCH_WIFI: return matchesWifi(ident); case MATCH_ETHERNET: @@ -409,43 +371,6 @@ public class NetworkTemplate implements Parcelable { } } - /** - * Check if mobile network classified 3G or lower with matching IMSI. - */ - @Deprecated - private boolean matchesMobile3gLower(NetworkIdentity ident) { - ensureSubtypeAvailable(); - if (ident.mType == TYPE_WIMAX) { - return false; - } else if (matchesMobile(ident)) { - switch (getNetworkClass(ident.mSubType)) { - case NETWORK_CLASS_UNKNOWN: - case NETWORK_CLASS_2_G: - case NETWORK_CLASS_3_G: - return true; - } - } - return false; - } - - /** - * Check if mobile network classified 4G with matching IMSI. - */ - @Deprecated - private boolean matchesMobile4g(NetworkIdentity ident) { - ensureSubtypeAvailable(); - if (ident.mType == TYPE_WIMAX) { - // TODO: consider matching against WiMAX subscriber identity - return true; - } else if (matchesMobile(ident)) { - switch (getNetworkClass(ident.mSubType)) { - case NETWORK_CLASS_4_G: - return true; - } - } - return false; - } - /** * Check if matches Wi-Fi network template. */ @@ -506,12 +431,8 @@ public class NetworkTemplate implements Parcelable { private static String getMatchRuleName(int matchRule) { switch (matchRule) { - case MATCH_MOBILE_3G_LOWER: - return "MOBILE_3G_LOWER"; - case MATCH_MOBILE_4G: - return "MOBILE_4G"; - case MATCH_MOBILE_ALL: - return "MOBILE_ALL"; + case MATCH_MOBILE: + return "MOBILE"; case MATCH_WIFI: return "WIFI"; case MATCH_ETHERNET: @@ -529,13 +450,6 @@ public class NetworkTemplate implements Parcelable { } } - private static void ensureSubtypeAvailable() { - if (COMBINE_SUBTYPE_ENABLED) { - throw new IllegalArgumentException( - "Unable to enforce 3G_LOWER template on combined data."); - } - } - /** * Examine the given template and normalize if it refers to a "merged" * mobile subscriber. We pick the "lowest" merged subscriber as the primary diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 3cc4d83267..a5f8dc72d8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -106,6 +106,10 @@ public class NetworkStatsCollection implements FileRotator.Reader { reset(); } + public void clear() { + reset(); + } + public void reset() { mStats.clear(); mStartMillis = Long.MAX_VALUE; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 32e15c9d9c..93c04fe206 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -49,7 +49,6 @@ import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE; import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES; import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL; import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED; -import static android.provider.Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE; import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES; @@ -95,10 +94,10 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.os.BestClock; import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; -import android.os.BestClock; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -134,6 +133,7 @@ import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; import com.android.server.EventLogTags; +import com.android.server.LocalServices; import com.android.server.connectivity.Tethering; import java.io.File; @@ -333,6 +333,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers"); mSystemDir = checkNotNull(systemDir, "missing systemDir"); mBaseDir = checkNotNull(baseDir, "missing baseDir"); + + LocalServices.addService(NetworkStatsManagerInternal.class, + new NetworkStatsManagerInternalImpl()); } @VisibleForTesting @@ -640,7 +643,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) { SubscriptionPlan plan = null; if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0 - && (template.getMatchRule() == NetworkTemplate.MATCH_MOBILE_ALL) + && (template.getMatchRule() == NetworkTemplate.MATCH_MOBILE) && mSettings.getAugmentEnabled()) { if (LOGD) Slog.d(TAG, "Resolving plan for " + template); final long token = Binder.clearCallingIdentity(); @@ -701,12 +704,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - @Override - public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { - // Special case - since this is for internal use only, don't worry about - // a full access level check and just require the signature/privileged - // permission. - mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); + private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { + assertSystemReady(); assertBandwidthControlEnabled(); // NOTE: if callers want to get non-augmented data, they should go @@ -716,6 +715,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes(); } + private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { + assertSystemReady(); + assertBandwidthControlEnabled(); + + final NetworkStatsCollection uidComplete; + synchronized (mStatsLock) { + uidComplete = mUidRecorder.getOrLoadCompleteLocked(); + } + return uidComplete.getSummary(template, start, end, NetworkStatsAccess.Level.DEVICE, + android.os.Process.SYSTEM_UID); + } + @Override public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException { if (Binder.getCallingUid() != uid) { @@ -777,10 +788,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - @Override - public void setUidForeground(int uid, boolean uidForeground) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - + @VisibleForTesting + void setUidForeground(int uid, boolean uidForeground) { synchronized (mStatsLock) { final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT; final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT); @@ -817,9 +826,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - @Override - public void advisePersistThreshold(long thresholdBytes) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + private void advisePersistThreshold(long thresholdBytes) { assertBandwidthControlEnabled(); // clamp threshold into safe range @@ -1330,6 +1337,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub { removeUidsLocked(uids); } + private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal { + @Override + public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { + return NetworkStatsService.this.getNetworkTotalBytes(template, start, end); + } + + @Override + public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { + return NetworkStatsService.this.getNetworkUidBytes(template, start, end); + } + + @Override + public void setUidForeground(int uid, boolean uidForeground) { + NetworkStatsService.this.setUidForeground(uid, uidForeground); + } + + @Override + public void advisePersistThreshold(long thresholdBytes) { + NetworkStatsService.this.advisePersistThreshold(thresholdBytes); + } + + @Override + public void forceUpdate() { + NetworkStatsService.this.forceUpdate(); + } + } + @Override protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) { if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return; @@ -1550,6 +1584,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + private void assertSystemReady() { + if (!mSystemReady) { + throw new IllegalStateException("System not ready"); + } + } + private void assertBandwidthControlEnabled() { if (!isBandwidthControlEnabled()) { throw new IllegalStateException("Bandwidth module disabled"); From a32100e85c967a941634955a531365060f5a90a4 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 27 Feb 2018 22:47:01 +0900 Subject: [PATCH 126/881] Minor cleanups to NetworkStats interface tracking. Currently, when a network goes into CONNECTED state, we call updateLinkProperties and then notifyIfacesChangedForNetworkStats. The latter is unnecessary, as there are exactly two cases: 1. networkAgent.linkProperties != null: updateLinkProperties will call notifyIfacesChangedForNetworkStats, because oldLp is null and networkAgent.linkProperties is not null. 2. networkAgent.linkProperties is null: there is no need to call notifyIfacesChangedForNetworkStats, because no interfaces were added or removed. When they are, updateLinkProperties will be called again. Removing the call to notifyIfacesChangedForNetworkStats avoids a stats poll, which is a minor performance improvement. Also, remove the NetworkStatsService code to do asynchronous interface updates, since it has no callers. Bug: 72107146 Test: builds, boots Test: runtest frameworks-net Change-Id: I9337ea26c0505a1c66ceda01254b68e25cd7972c --- .../java/com/android/server/net/NetworkStatsService.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index bfc150e1a9..82981275fc 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -153,8 +153,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { static final boolean LOGV = false; private static final int MSG_PERFORM_POLL = 1; - private static final int MSG_UPDATE_IFACES = 2; - private static final int MSG_REGISTER_GLOBAL_ALERT = 3; + private static final int MSG_REGISTER_GLOBAL_ALERT = 2; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -1533,10 +1532,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mService.performPoll(flags); return true; } - case MSG_UPDATE_IFACES: { - mService.updateIfaces(null); - return true; - } case MSG_REGISTER_GLOBAL_ALERT: { mService.registerGlobalAlert(); return true; From 34dcea11fdc7e01f3317bebdf77597c8d75da411 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 5 Mar 2018 18:14:56 +0900 Subject: [PATCH 127/881] Allow null subscriberId in NetworkStatsManager. Use a MATCH_MOBILE_WILDCARD template to avoid filtering by subscriberId when querying statistics from NetworkStatsService. Bug: 74038898 Change-Id: I4b39e7031416cb33b23d89aa36ff0f774eaa942f Fixes: 74038898 Test: runtest frameworks-net, CTS tests pass --- core/java/android/app/usage/NetworkStats.java | 6 +-- .../app/usage/NetworkStatsManager.java | 40 ++++++++++++------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index d33af4faeb..6ca23496a8 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -24,7 +24,6 @@ import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.IntArray; import android.util.Log; @@ -98,9 +97,8 @@ public final class NetworkStats implements AutoCloseable { /** @hide */ NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp, - long endTimestamp) throws RemoteException, SecurityException { - final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + long endTimestamp, INetworkStatsService statsService) + throws RemoteException, SecurityException { // Open network stats session mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName()); mCloseGuard.open("close"); diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 5576e86edd..2357637b72 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -37,6 +37,8 @@ import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + /** * Provides access to network usage history and statistics. Usage data is collected in * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details. @@ -107,9 +109,15 @@ public class NetworkStatsManager { * {@hide} */ public NetworkStatsManager(Context context) throws ServiceNotFoundException { + this(context, INetworkStatsService.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); + } + + /** @hide */ + @VisibleForTesting + public NetworkStatsManager(Context context, INetworkStatsService service) { mContext = context; - mService = INetworkStatsService.Stub.asInterface( - ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)); + mService = service; setPollOnOpen(true); } @@ -135,7 +143,8 @@ public class NetworkStatsManager { public Bucket querySummaryForDevice(NetworkTemplate template, long startTime, long endTime) throws SecurityException, RemoteException { Bucket bucket = null; - NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); + NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, + mService); bucket = stats.getDeviceSummaryForNetwork(); stats.close(); @@ -208,7 +217,7 @@ public class NetworkStatsManager { } NetworkStats stats; - stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); + stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); stats.startSummaryEnumeration(); stats.close(); @@ -245,7 +254,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, mFlags, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); result.startSummaryEnumeration(); return result; @@ -295,7 +304,7 @@ public class NetworkStatsManager { NetworkStats result; try { - result = new NetworkStats(mContext, template, mFlags, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); result.startHistoryEnumeration(uid, tag); } catch (RemoteException e) { Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e); @@ -341,7 +350,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, mFlags, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); result.startUserUidEnumeration(); return result; } @@ -451,19 +460,20 @@ public class NetworkStatsManager { } private static NetworkTemplate createTemplate(int networkType, String subscriberId) { - NetworkTemplate template = null; + final NetworkTemplate template; switch (networkType) { - case ConnectivityManager.TYPE_MOBILE: { - template = NetworkTemplate.buildTemplateMobileAll(subscriberId); - } break; - case ConnectivityManager.TYPE_WIFI: { + case ConnectivityManager.TYPE_MOBILE: + template = subscriberId == null + ? NetworkTemplate.buildTemplateMobileWildcard() + : NetworkTemplate.buildTemplateMobileAll(subscriberId); + break; + case ConnectivityManager.TYPE_WIFI: template = NetworkTemplate.buildTemplateWifiWildcard(); - } break; - default: { + break; + default: throw new IllegalArgumentException("Cannot create template for network type " + networkType + ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) + "'."); - } } return template; } From ad1f51c7f894f613127e7a5767038b76f5a7a5e1 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 1 Mar 2018 18:53:07 -0800 Subject: [PATCH 128/881] Added implementation for VTI add/remove address This change adds implementation details for add/remove addresses onto a VTI. Bug: 73675031 Test: New tests added, passing on Walleye Change-Id: Idde9d943a5285d2c13c5c6b0f7b8a9faf718e6a5 --- core/java/android/net/IIpSecService.aidl | 5 +- core/java/android/net/IpSecManager.java | 16 +++-- .../java/com/android/server/IpSecService.java | 60 +++++++++++++------ 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 3ce0283d7f..3a3ddcc483 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -16,6 +16,7 @@ package android.net; +import android.net.LinkAddress; import android.net.Network; import android.net.IpSecConfig; import android.net.IpSecUdpEncapResponse; @@ -48,11 +49,11 @@ interface IIpSecService void addAddressToTunnelInterface( int tunnelResourceId, - String localAddr); + in LinkAddress localAddr); void removeAddressFromTunnelInterface( int tunnelResourceId, - String localAddr); + in LinkAddress localAddr); void deleteTunnelInterface(int resourceId); diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index b60984771a..f1beef1f21 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -660,10 +660,14 @@ public final class IpSecManager { * tunneled traffic. * * @param address the local address for traffic inside the tunnel - * @throws IOException if the address could not be added * @hide */ - public void addAddress(LinkAddress address) throws IOException { + public void addAddress(LinkAddress address) { + try { + mService.addAddressToTunnelInterface(mResourceId, address); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -672,10 +676,14 @@ public final class IpSecManager { *

Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed - * @throws IOException if the address could not be removed * @hide */ - public void removeAddress(LinkAddress address) throws IOException { + public void removeAddress(LinkAddress address) { + try { + mService.removeAddressFromTunnelInterface(mResourceId, address); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } private IpSecTunnelInterface(@NonNull IIpSecService service, diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 45a4dfb91b..45e9481c22 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -36,6 +36,7 @@ import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; +import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.net.TrafficStats; @@ -618,10 +619,8 @@ public class IpSecService extends IIpSecService.Stub { spi, mConfig.getMarkValue(), mConfig.getMarkMask()); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { - Log.e(TAG, "Failed to delete SA with ID: " + mResourceId); + } catch (RemoteException | ServiceSpecificException e) { + Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } getResourceTracker().give(); @@ -681,10 +680,8 @@ public class IpSecService extends IIpSecService.Stub { .getNetdInstance() .ipSecDeleteSecurityAssociation( mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { - Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId); + } catch (ServiceSpecificException | RemoteException e) { + Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); } mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; @@ -829,15 +826,13 @@ public class IpSecService extends IIpSecService.Stub { 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff); } } - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { + } catch (ServiceSpecificException | RemoteException e) { Log.e( TAG, "Failed to delete VTI with interface name: " + mInterfaceName + " and id: " - + mResourceId); + + mResourceId, e); } getResourceTracker().give(); @@ -1319,7 +1314,9 @@ public class IpSecService extends IIpSecService.Stub { * from multiple local IP addresses over the same tunnel. */ @Override - public synchronized void addAddressToTunnelInterface(int tunnelResourceId, String localAddr) { + public synchronized void addAddressToTunnelInterface( + int tunnelResourceId, LinkAddress localAddr) { + enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1327,8 +1324,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); - // TODO: Add calls to netd: - // Add address to TunnelInterface + try { + // We can assume general validity of the IP address, since we get them as a + // LinkAddress, which does some validation. + mSrvConfig + .getNetdInstance() + .interfaceAddAddress( + tunnelInterfaceInfo.mInterfaceName, + localAddr.getAddress().getHostAddress(), + localAddr.getPrefixLength()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. + throw new IllegalArgumentException(e); + } } /** @@ -1337,7 +1347,8 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void removeAddressFromTunnelInterface( - int tunnelResourceId, String localAddr) { + int tunnelResourceId, LinkAddress localAddr) { + enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1345,8 +1356,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); - // TODO: Add calls to netd: - // Remove address from TunnelInterface + try { + // We can assume general validity of the IP address, since we get them as a + // LinkAddress, which does some validation. + mSrvConfig + .getNetdInstance() + .interfaceDelAddress( + tunnelInterfaceInfo.mInterfaceName, + localAddr.getAddress().getHostAddress(), + localAddr.getPrefixLength()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. + throw new IllegalArgumentException(e); + } } /** From 11669685cdc91c5bd3b421c922b9f4e94e9d6032 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 6 Mar 2018 13:22:22 -0800 Subject: [PATCH 129/881] Docstring Updates for applyTransportModeTransform -Add anotations to usages of PolicyDirection for apply...() methods. -Update the comments on DIRECTION_IN and DIRECTION_OUT to better reflect their current usage. -Add a better explanation to the rekey procedure doc. -Remove disused createTunnelInterface() stub. Bug: 73751066 Test: make docs Change-Id: I9f2ec864466148a18899f1e952c74a525902ccbc --- core/java/android/net/IpSecManager.java | 88 +++++++++++++------------ 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index b60984771a..fbf305633a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -58,14 +58,18 @@ public final class IpSecManager { private static final String TAG = "IpSecManager"; /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic towards the host. + * Used when applying a transform to direct traffic through an {@link IpSecTransform} + * towards the host. + * + *

See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. */ public static final int DIRECTION_IN = 0; /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic from the host. + * Used when applying a transform to direct traffic through an {@link IpSecTransform} + * away from the host. + * + *

See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. */ public static final int DIRECTION_OUT = 1; @@ -301,19 +305,21 @@ public final class IpSecManager { * *

Rekey Procedure

* - *

When applying a new tranform to a socket, the previous transform will be removed. However, - * inbound traffic on the old transform will continue to be decrypted until that transform is - * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures - * where both transforms are valid until both endpoints are using the new transform and all - * in-flight packets have been received. + *

When applying a new tranform to a socket in the outbound direction, the previous transform + * will be removed and the new transform will take effect immediately, sending all traffic on + * the new transform; however, when applying a transform in the inbound direction, traffic + * on the old transform will continue to be decrypted and delivered until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey + * procedures where both transforms are valid until both endpoints are using the new transform + * and all in-flight packets have been received. * * @param socket a stream socket - * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} + * @param direction the direction in which the transform should be applied * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ public void applyTransportModeTransform( - Socket socket, int direction, IpSecTransform transform) + Socket socket, @PolicyDirection int direction, IpSecTransform transform) throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -334,19 +340,22 @@ public final class IpSecManager { * *

Rekey Procedure

* - *

When applying a new tranform to a socket, the previous transform will be removed. However, - * inbound traffic on the old transform will continue to be decrypted until that transform is - * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures - * where both transforms are valid until both endpoints are using the new transform and all - * in-flight packets have been received. + *

When applying a new tranform to a socket in the outbound direction, the previous transform + * will be removed and the new transform will take effect immediately, sending all traffic on + * the new transform; however, when applying a transform in the inbound direction, traffic + * on the old transform will continue to be decrypted and delivered until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey + * procedures where both transforms are valid until both endpoints are using the new transform + * and all in-flight packets have been received. * * @param socket a datagram socket - * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT + * @param direction the direction in which the transform should be applied * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ public void applyTransportModeTransform( - DatagramSocket socket, int direction, IpSecTransform transform) throws IOException { + DatagramSocket socket, @PolicyDirection int direction, IpSecTransform transform) + throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -366,19 +375,21 @@ public final class IpSecManager { * *

Rekey Procedure

* - *

When applying a new tranform to a socket, the previous transform will be removed. However, - * inbound traffic on the old transform will continue to be decrypted until that transform is - * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures - * where both transforms are valid until both endpoints are using the new transform and all - * in-flight packets have been received. + *

When applying a new tranform to a socket in the outbound direction, the previous transform + * will be removed and the new transform will take effect immediately, sending all traffic on + * the new transform; however, when applying a transform in the inbound direction, traffic + * on the old transform will continue to be decrypted and delivered until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey + * procedures where both transforms are valid until both endpoints are using the new transform + * and all in-flight packets have been received. * * @param socket a socket file descriptor - * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT + * @param direction the direction in which the transform should be applied * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ public void applyTransportModeTransform( - FileDescriptor socket, int direction, IpSecTransform transform) + FileDescriptor socket, @PolicyDirection int direction, IpSecTransform transform) throws IOException { // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() // constructor takes control and closes the user's FD when we exit the method. @@ -389,21 +400,6 @@ public final class IpSecManager { } } - /** - * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to - * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to - * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic). - * Applications should probably not use this API directly. Instead, they should use {@link - * VpnService} to provide VPN capability in a more generic fashion. - * - *

TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. - * - * @param net a {@link Network} that will be tunneled via IP Sec. - * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform. - * @hide - */ - public void applyTunnelModeTransform(Network net, IpSecTransform transform) {} - /** * Remove an IPsec transform from a stream socket. * @@ -770,7 +766,12 @@ public final class IpSecManager { } /** - * Apply a transform to the IpSecTunnelInterface + * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will + * tunnel all traffic for the given direction through the underlying network's interface with + * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional + * IP header and IPsec Header on all inbound traffic). + *

Applications should probably not use this API directly. + * * * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied * transform. @@ -783,8 +784,8 @@ public final class IpSecManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction, - IpSecTransform transform) throws IOException { + public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, + @PolicyDirection int direction, IpSecTransform transform) throws IOException { try { mService.applyTunnelModeTransform( tunnel.getResourceId(), direction, transform.getResourceId()); @@ -792,6 +793,7 @@ public final class IpSecManager { throw e.rethrowFromSystemServer(); } } + /** * Construct an instance of IpSecManager within an application context. * From cec463f0a7766a37a29431876bdb3ceb0b01be16 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 15 Mar 2018 19:41:41 -0700 Subject: [PATCH 130/881] Add support for auth-only transforms Kernel limitations prevent auth-only SAs from being created. Explicitly request a null encryption algorithm instead of omitting the algorithm to comply with the kernel requirement for ESP. Bug: 75049573 Test: CTS tests for auth-only, crypt-only transforms added for all combinations of (UDP, TCP, IPv4, IPv6, UDP-encap) Also added unit tests to ensure correct triggering of NULL_CRYPT usage. Change-Id: Ia9a5cfee9c7786412846bc039f326420f6211c08 --- core/java/android/net/IpSecAlgorithm.java | 7 +++++++ services/core/java/com/android/server/IpSecService.java | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index c69a4d4c0b..f4b328e412 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -37,6 +37,13 @@ import java.util.Arrays; public final class IpSecAlgorithm implements Parcelable { private static final String TAG = "IpSecAlgorithm"; + /** + * Null cipher. + * + * @hide + */ + public static final String CRYPT_NULL = "ecb(cipher_null)"; + /** * AES-CBC Encryption/Ciphering Algorithm. * diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 45a4dfb91b..d3f1a7bbb5 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1467,6 +1467,13 @@ public class IpSecService extends IIpSecService.Stub { IpSecAlgorithm crypt = c.getEncryption(); IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(); + String cryptName; + if (crypt == null) { + cryptName = (authCrypt == null) ? IpSecAlgorithm.CRYPT_NULL : ""; + } else { + cryptName = crypt.getName(); + } + mSrvConfig .getNetdInstance() .ipSecAddSecurityAssociation( @@ -1481,7 +1488,7 @@ public class IpSecService extends IIpSecService.Stub { (auth != null) ? auth.getName() : "", (auth != null) ? auth.getKey() : new byte[] {}, (auth != null) ? auth.getTruncationLengthBits() : 0, - (crypt != null) ? crypt.getName() : "", + cryptName, (crypt != null) ? crypt.getKey() : new byte[] {}, (crypt != null) ? crypt.getTruncationLengthBits() : 0, (authCrypt != null) ? authCrypt.getName() : "", From 95c6602f5046dd527ba5add0923f70f5c6616e91 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 6 Mar 2018 13:22:22 -0800 Subject: [PATCH 131/881] Docstring Updates for applyTransportModeTransform -Add anotations to usages of PolicyDirection for apply...() methods. -Update the comments on DIRECTION_IN and DIRECTION_OUT to better reflect their current usage. -Add a better explanation to the rekey procedure doc. -Remove disused createTunnelInterface() stub. Bug: 73751066 Test: make docs Merged-In: I9f2ec864466148a18899f1e952c74a525902ccbc Change-Id: I9f2ec864466148a18899f1e952c74a525902ccbc (cherry picked from commit f4cdf25a906d0f52ffd76508d660b843b13b3ff8) --- core/java/android/net/IpSecManager.java | 88 +++++++++++++------------ 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index b60984771a..fbf305633a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -58,14 +58,18 @@ public final class IpSecManager { private static final String TAG = "IpSecManager"; /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic towards the host. + * Used when applying a transform to direct traffic through an {@link IpSecTransform} + * towards the host. + * + *

See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. */ public static final int DIRECTION_IN = 0; /** - * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute - * applies to traffic from the host. + * Used when applying a transform to direct traffic through an {@link IpSecTransform} + * away from the host. + * + *

See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. */ public static final int DIRECTION_OUT = 1; @@ -301,19 +305,21 @@ public final class IpSecManager { * *

Rekey Procedure

* - *

When applying a new tranform to a socket, the previous transform will be removed. However, - * inbound traffic on the old transform will continue to be decrypted until that transform is - * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures - * where both transforms are valid until both endpoints are using the new transform and all - * in-flight packets have been received. + *

When applying a new tranform to a socket in the outbound direction, the previous transform + * will be removed and the new transform will take effect immediately, sending all traffic on + * the new transform; however, when applying a transform in the inbound direction, traffic + * on the old transform will continue to be decrypted and delivered until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey + * procedures where both transforms are valid until both endpoints are using the new transform + * and all in-flight packets have been received. * * @param socket a stream socket - * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT} + * @param direction the direction in which the transform should be applied * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ public void applyTransportModeTransform( - Socket socket, int direction, IpSecTransform transform) + Socket socket, @PolicyDirection int direction, IpSecTransform transform) throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -334,19 +340,22 @@ public final class IpSecManager { * *

Rekey Procedure

* - *

When applying a new tranform to a socket, the previous transform will be removed. However, - * inbound traffic on the old transform will continue to be decrypted until that transform is - * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures - * where both transforms are valid until both endpoints are using the new transform and all - * in-flight packets have been received. + *

When applying a new tranform to a socket in the outbound direction, the previous transform + * will be removed and the new transform will take effect immediately, sending all traffic on + * the new transform; however, when applying a transform in the inbound direction, traffic + * on the old transform will continue to be decrypted and delivered until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey + * procedures where both transforms are valid until both endpoints are using the new transform + * and all in-flight packets have been received. * * @param socket a datagram socket - * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT + * @param direction the direction in which the transform should be applied * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ public void applyTransportModeTransform( - DatagramSocket socket, int direction, IpSecTransform transform) throws IOException { + DatagramSocket socket, @PolicyDirection int direction, IpSecTransform transform) + throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -366,19 +375,21 @@ public final class IpSecManager { * *

Rekey Procedure

* - *

When applying a new tranform to a socket, the previous transform will be removed. However, - * inbound traffic on the old transform will continue to be decrypted until that transform is - * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures - * where both transforms are valid until both endpoints are using the new transform and all - * in-flight packets have been received. + *

When applying a new tranform to a socket in the outbound direction, the previous transform + * will be removed and the new transform will take effect immediately, sending all traffic on + * the new transform; however, when applying a transform in the inbound direction, traffic + * on the old transform will continue to be decrypted and delivered until that transform is + * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey + * procedures where both transforms are valid until both endpoints are using the new transform + * and all in-flight packets have been received. * * @param socket a socket file descriptor - * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT + * @param direction the direction in which the transform should be applied * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ public void applyTransportModeTransform( - FileDescriptor socket, int direction, IpSecTransform transform) + FileDescriptor socket, @PolicyDirection int direction, IpSecTransform transform) throws IOException { // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() // constructor takes control and closes the user's FD when we exit the method. @@ -389,21 +400,6 @@ public final class IpSecManager { } } - /** - * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to - * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to - * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic). - * Applications should probably not use this API directly. Instead, they should use {@link - * VpnService} to provide VPN capability in a more generic fashion. - * - *

TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked. - * - * @param net a {@link Network} that will be tunneled via IP Sec. - * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform. - * @hide - */ - public void applyTunnelModeTransform(Network net, IpSecTransform transform) {} - /** * Remove an IPsec transform from a stream socket. * @@ -770,7 +766,12 @@ public final class IpSecManager { } /** - * Apply a transform to the IpSecTunnelInterface + * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will + * tunnel all traffic for the given direction through the underlying network's interface with + * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional + * IP header and IPsec Header on all inbound traffic). + *

Applications should probably not use this API directly. + * * * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied * transform. @@ -783,8 +784,8 @@ public final class IpSecManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction, - IpSecTransform transform) throws IOException { + public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, + @PolicyDirection int direction, IpSecTransform transform) throws IOException { try { mService.applyTunnelModeTransform( tunnel.getResourceId(), direction, transform.getResourceId()); @@ -792,6 +793,7 @@ public final class IpSecManager { throw e.rethrowFromSystemServer(); } } + /** * Construct an instance of IpSecManager within an application context. * From 96a304ec6aad1820daece525711b27ba4ae1859d Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 27 Feb 2018 19:19:40 -0800 Subject: [PATCH 132/881] Check mOwnedByTransform to avoid DELSA on SPI The owned by transform flag prevents the removal of an SPI from accidentally deleting an associated SA in the kernel. That flag wasn't actually being checked, so deleting an SPI would result in the transform being removed. The existing code already guarantees that the SA is deleted when the transform is deleted Bug: 73258845 Test: runtest frameworks-net Change-Id: I4c26aea7af817a5d9e54da5db1cdf4f943bcae06 --- .../core/java/com/android/server/IpSecService.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 45e9481c22..89f599b17f 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -676,10 +676,12 @@ public class IpSecService extends IIpSecService.Stub { @Override public void freeUnderlyingResources() { try { - mSrvConfig - .getNetdInstance() - .ipSecDeleteSecurityAssociation( - mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); + if (!mOwnedByTransform) { + mSrvConfig + .getNetdInstance() + .ipSecDeleteSecurityAssociation( + mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); + } } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); } From 3a48f26dcaaf97ddfbb722a38484e8f5cbf1efc4 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 20 Mar 2018 12:26:10 -0700 Subject: [PATCH 133/881] Expose add/removeAddress for IpSecInterfaces When exposing the APIs, these were missed. The outer structure is exposed, so this exposes the addAddress and removeAddress methods. Bug: 75234273 Test: compilation Change-Id: I79911434f9baa660e4d8564cc59d80da4a710c42 --- core/java/android/net/IpSecManager.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 4e1f83430a..cb4299ef69 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -658,7 +658,8 @@ public final class IpSecManager { * @param address the local address for traffic inside the tunnel * @hide */ - public void addAddress(LinkAddress address) { + @SystemApi + public void addAddress(LinkAddress address) throws IOException { try { mService.addAddressToTunnelInterface(mResourceId, address); } catch (RemoteException e) { @@ -674,7 +675,8 @@ public final class IpSecManager { * @param address to be removed * @hide */ - public void removeAddress(LinkAddress address) { + @SystemApi + public void removeAddress(LinkAddress address) throws IOException { try { mService.removeAddressFromTunnelInterface(mResourceId, address); } catch (RemoteException e) { From f628b3b3c9f42ee45c50bb7867ab5bb442730743 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 15 Mar 2018 19:41:41 -0700 Subject: [PATCH 134/881] Add support for auth-only transforms Kernel limitations prevent auth-only SAs from being created. Explicitly request a null encryption algorithm instead of omitting the algorithm to comply with the kernel requirement for ESP. Bug: 75049573 Test: CTS tests for auth-only, crypt-only transforms added for all combinations of (UDP, TCP, IPv4, IPv6, UDP-encap) Also added unit tests to ensure correct triggering of NULL_CRYPT usage. Merged-In: Ia9a5cfee9c7786412846bc039f326420f6211c08 Change-Id: Ia9a5cfee9c7786412846bc039f326420f6211c08 (cherry picked from commit bf013a3820c69348e034c6340b28e95f3441ebe8) --- core/java/android/net/IpSecAlgorithm.java | 7 +++++++ services/core/java/com/android/server/IpSecService.java | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index c69a4d4c0b..f4b328e412 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -37,6 +37,13 @@ import java.util.Arrays; public final class IpSecAlgorithm implements Parcelable { private static final String TAG = "IpSecAlgorithm"; + /** + * Null cipher. + * + * @hide + */ + public static final String CRYPT_NULL = "ecb(cipher_null)"; + /** * AES-CBC Encryption/Ciphering Algorithm. * diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 45a4dfb91b..d3f1a7bbb5 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1467,6 +1467,13 @@ public class IpSecService extends IIpSecService.Stub { IpSecAlgorithm crypt = c.getEncryption(); IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(); + String cryptName; + if (crypt == null) { + cryptName = (authCrypt == null) ? IpSecAlgorithm.CRYPT_NULL : ""; + } else { + cryptName = crypt.getName(); + } + mSrvConfig .getNetdInstance() .ipSecAddSecurityAssociation( @@ -1481,7 +1488,7 @@ public class IpSecService extends IIpSecService.Stub { (auth != null) ? auth.getName() : "", (auth != null) ? auth.getKey() : new byte[] {}, (auth != null) ? auth.getTruncationLengthBits() : 0, - (crypt != null) ? crypt.getName() : "", + cryptName, (crypt != null) ? crypt.getKey() : new byte[] {}, (crypt != null) ? crypt.getTruncationLengthBits() : 0, (authCrypt != null) ? authCrypt.getName() : "", From c53a274b8fcd54af3ba6239d2d17c402c195b508 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 1 Mar 2018 18:53:07 -0800 Subject: [PATCH 135/881] Added implementation for VTI add/remove address This change adds implementation details for add/remove addresses onto a VTI. Bug: 73675031 Test: New tests added, passing on Walleye Merged-In: Idde9d943a5285d2c13c5c6b0f7b8a9faf718e6a5 Change-Id: Idde9d943a5285d2c13c5c6b0f7b8a9faf718e6a5 (cherry picked from commit ecc9f7cc08804e3fa15fea04ae94ea1bc74edbfe) --- core/java/android/net/IIpSecService.aidl | 5 +- core/java/android/net/IpSecManager.java | 16 +++-- .../java/com/android/server/IpSecService.java | 60 +++++++++++++------ 3 files changed, 57 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 3ce0283d7f..3a3ddcc483 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -16,6 +16,7 @@ package android.net; +import android.net.LinkAddress; import android.net.Network; import android.net.IpSecConfig; import android.net.IpSecUdpEncapResponse; @@ -48,11 +49,11 @@ interface IIpSecService void addAddressToTunnelInterface( int tunnelResourceId, - String localAddr); + in LinkAddress localAddr); void removeAddressFromTunnelInterface( int tunnelResourceId, - String localAddr); + in LinkAddress localAddr); void deleteTunnelInterface(int resourceId); diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index fbf305633a..4e1f83430a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -656,10 +656,14 @@ public final class IpSecManager { * tunneled traffic. * * @param address the local address for traffic inside the tunnel - * @throws IOException if the address could not be added * @hide */ - public void addAddress(LinkAddress address) throws IOException { + public void addAddress(LinkAddress address) { + try { + mService.addAddressToTunnelInterface(mResourceId, address); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** @@ -668,10 +672,14 @@ public final class IpSecManager { *

Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed - * @throws IOException if the address could not be removed * @hide */ - public void removeAddress(LinkAddress address) throws IOException { + public void removeAddress(LinkAddress address) { + try { + mService.removeAddressFromTunnelInterface(mResourceId, address); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } private IpSecTunnelInterface(@NonNull IIpSecService service, diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 45a4dfb91b..45e9481c22 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -36,6 +36,7 @@ import android.net.IpSecTransform; import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; +import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.net.TrafficStats; @@ -618,10 +619,8 @@ public class IpSecService extends IIpSecService.Stub { spi, mConfig.getMarkValue(), mConfig.getMarkMask()); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { - Log.e(TAG, "Failed to delete SA with ID: " + mResourceId); + } catch (RemoteException | ServiceSpecificException e) { + Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } getResourceTracker().give(); @@ -681,10 +680,8 @@ public class IpSecService extends IIpSecService.Stub { .getNetdInstance() .ipSecDeleteSecurityAssociation( mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { - Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId); + } catch (ServiceSpecificException | RemoteException e) { + Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); } mSpi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; @@ -829,15 +826,13 @@ public class IpSecService extends IIpSecService.Stub { 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff); } } - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } catch (RemoteException e) { + } catch (ServiceSpecificException | RemoteException e) { Log.e( TAG, "Failed to delete VTI with interface name: " + mInterfaceName + " and id: " - + mResourceId); + + mResourceId, e); } getResourceTracker().give(); @@ -1319,7 +1314,9 @@ public class IpSecService extends IIpSecService.Stub { * from multiple local IP addresses over the same tunnel. */ @Override - public synchronized void addAddressToTunnelInterface(int tunnelResourceId, String localAddr) { + public synchronized void addAddressToTunnelInterface( + int tunnelResourceId, LinkAddress localAddr) { + enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1327,8 +1324,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); - // TODO: Add calls to netd: - // Add address to TunnelInterface + try { + // We can assume general validity of the IP address, since we get them as a + // LinkAddress, which does some validation. + mSrvConfig + .getNetdInstance() + .interfaceAddAddress( + tunnelInterfaceInfo.mInterfaceName, + localAddr.getAddress().getHostAddress(), + localAddr.getPrefixLength()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. + throw new IllegalArgumentException(e); + } } /** @@ -1337,7 +1347,8 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void removeAddressFromTunnelInterface( - int tunnelResourceId, String localAddr) { + int tunnelResourceId, LinkAddress localAddr) { + enforceNetworkStackPermission(); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1345,8 +1356,21 @@ public class IpSecService extends IIpSecService.Stub { TunnelInterfaceRecord tunnelInterfaceInfo = userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); - // TODO: Add calls to netd: - // Remove address from TunnelInterface + try { + // We can assume general validity of the IP address, since we get them as a + // LinkAddress, which does some validation. + mSrvConfig + .getNetdInstance() + .interfaceDelAddress( + tunnelInterfaceInfo.mInterfaceName, + localAddr.getAddress().getHostAddress(), + localAddr.getPrefixLength()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (ServiceSpecificException e) { + // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. + throw new IllegalArgumentException(e); + } } /** From 902acb89ddaf27abebece6559b987495371e8951 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 20 Mar 2018 12:26:10 -0700 Subject: [PATCH 136/881] Expose add/removeAddress for IpSecInterfaces When exposing the APIs, these were missed. The outer structure is exposed, so this exposes the addAddress and removeAddress methods. Bug: 75234273 Test: compilation Merged-In: I79911434f9baa660e4d8564cc59d80da4a710c42 Change-Id: I79911434f9baa660e4d8564cc59d80da4a710c42 (cherry picked from commit a83601a511c3f11470109d78d1a736acdb9c6bd8) --- core/java/android/net/IpSecManager.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 4e1f83430a..cb4299ef69 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -658,7 +658,8 @@ public final class IpSecManager { * @param address the local address for traffic inside the tunnel * @hide */ - public void addAddress(LinkAddress address) { + @SystemApi + public void addAddress(LinkAddress address) throws IOException { try { mService.addAddressToTunnelInterface(mResourceId, address); } catch (RemoteException e) { @@ -674,7 +675,8 @@ public final class IpSecManager { * @param address to be removed * @hide */ - public void removeAddress(LinkAddress address) { + @SystemApi + public void removeAddress(LinkAddress address) throws IOException { try { mService.removeAddressFromTunnelInterface(mResourceId, address); } catch (RemoteException e) { From 52e219bded0f53dec213147732a26908335dbd4b Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 27 Feb 2018 19:19:40 -0800 Subject: [PATCH 137/881] Check mOwnedByTransform to avoid DELSA on SPI The owned by transform flag prevents the removal of an SPI from accidentally deleting an associated SA in the kernel. That flag wasn't actually being checked, so deleting an SPI would result in the transform being removed. The existing code already guarantees that the SA is deleted when the transform is deleted Bug: 73258845 Test: runtest frameworks-net Merged-In: I4c26aea7af817a5d9e54da5db1cdf4f943bcae06 Change-Id: I4c26aea7af817a5d9e54da5db1cdf4f943bcae06 (cherry picked from commit 22795302be4ec35449908cf566aa7c16945df836) --- .../core/java/com/android/server/IpSecService.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 45e9481c22..89f599b17f 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -676,10 +676,12 @@ public class IpSecService extends IIpSecService.Stub { @Override public void freeUnderlyingResources() { try { - mSrvConfig - .getNetdInstance() - .ipSecDeleteSecurityAssociation( - mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); + if (!mOwnedByTransform) { + mSrvConfig + .getNetdInstance() + .ipSecDeleteSecurityAssociation( + mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); + } } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); } From 2d07666599af3e1518d31fcaab2d0e2065443cc3 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Fri, 16 Mar 2018 17:27:30 -0700 Subject: [PATCH 138/881] Add NonNull Annotations To IpSec API Surface This CL adds NonNull annotations to a large number of method returns and parameters as part of API council feedback. Bug: 72473424 Test: compilation (docstring-only change) Change-Id: I2f865dde56fe12116c461ad98e9460bf1802ce18 --- core/java/android/net/IpSecAlgorithm.java | 8 +++-- core/java/android/net/IpSecManager.java | 44 +++++++++++------------ core/java/android/net/IpSecTransform.java | 6 ++++ 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index f4b328e412..57f05884ce 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -129,7 +129,7 @@ public final class IpSecAlgorithm implements Parcelable { * @param algorithm name of the algorithm. * @param key key padded to a multiple of 8 bits. */ - public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key) { + public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) { this(algorithm, key, key.length * 8); } @@ -144,7 +144,8 @@ public final class IpSecAlgorithm implements Parcelable { * @param key key padded to a multiple of 8 bits. * @param truncLenBits number of bits of output hash to use. */ - public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) { + public IpSecAlgorithm( + @NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) { mName = algorithm; mKey = key.clone(); mTruncLenBits = truncLenBits; @@ -152,11 +153,13 @@ public final class IpSecAlgorithm implements Parcelable { } /** Get the algorithm name */ + @NonNull public String getName() { return mName; } /** Get the key for this algorithm */ + @NonNull public byte[] getKey() { return mKey.clone(); } @@ -270,6 +273,7 @@ public final class IpSecAlgorithm implements Parcelable { } @Override + @NonNull public String toString() { return new StringBuilder() .append("{mName=") diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index cb4299ef69..4157845d61 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -253,8 +253,9 @@ public final class IpSecManager { * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are * currently allocated for this user */ - public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress) - throws ResourceUnavailableException { + @NonNull + public SecurityParameterIndex allocateSecurityParameterIndex( + @NonNull InetAddress destinationAddress) throws ResourceUnavailableException { try { return new SecurityParameterIndex( mService, @@ -280,8 +281,9 @@ public final class IpSecManager { * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be * reserved */ + @NonNull public SecurityParameterIndex allocateSecurityParameterIndex( - InetAddress destinationAddress, int requestedSpi) + @NonNull InetAddress destinationAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); @@ -318,9 +320,8 @@ public final class IpSecManager { * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform( - Socket socket, @PolicyDirection int direction, IpSecTransform transform) - throws IOException { + public void applyTransportModeTransform(@NonNull Socket socket, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -353,9 +354,8 @@ public final class IpSecManager { * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform( - DatagramSocket socket, @PolicyDirection int direction, IpSecTransform transform) - throws IOException { + public void applyTransportModeTransform(@NonNull DatagramSocket socket, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -388,9 +388,8 @@ public final class IpSecManager { * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform( - FileDescriptor socket, @PolicyDirection int direction, IpSecTransform transform) - throws IOException { + public void applyTransportModeTransform(@NonNull FileDescriptor socket, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() // constructor takes control and closes the user's FD when we exit the method. try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { @@ -413,8 +412,7 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(Socket socket) - throws IOException { + public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException { removeTransportModeTransforms(socket.getFileDescriptor$()); } @@ -431,8 +429,7 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(DatagramSocket socket) - throws IOException { + public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException { removeTransportModeTransforms(socket.getFileDescriptor$()); } @@ -449,8 +446,7 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(FileDescriptor socket) - throws IOException { + public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.removeTransportModeTransforms(pfd); } catch (RemoteException e) { @@ -588,6 +584,7 @@ public final class IpSecManager { // safely usable for Encapsulation without allowing a user to possibly unbind from/close // the port, which could potentially impact the traffic of the next user who binds to that // socket. + @NonNull public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) throws IOException, ResourceUnavailableException { /* @@ -617,6 +614,7 @@ public final class IpSecManager { // safely usable for Encapsulation without allowing a user to possibly unbind from/close // the port, which could potentially impact the traffic of the next user who binds to that // socket. + @NonNull public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { return new UdpEncapsulationSocket(mService, 0); @@ -645,6 +643,7 @@ public final class IpSecManager { private int mResourceId = INVALID_RESOURCE_ID; /** Get the underlying SPI held by this object. */ + @NonNull public String getInterfaceName() { return mInterfaceName; } @@ -659,7 +658,7 @@ public final class IpSecManager { * @hide */ @SystemApi - public void addAddress(LinkAddress address) throws IOException { + public void addAddress(@NonNull LinkAddress address) throws IOException { try { mService.addAddressToTunnelInterface(mResourceId, address); } catch (RemoteException e) { @@ -676,7 +675,7 @@ public final class IpSecManager { * @hide */ @SystemApi - public void removeAddress(LinkAddress address) throws IOException { + public void removeAddress(@NonNull LinkAddress address) throws IOException { try { mService.removeAddressFromTunnelInterface(mResourceId, address); } catch (RemoteException e) { @@ -768,6 +767,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) @@ -794,8 +794,8 @@ public final class IpSecManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, - @PolicyDirection int direction, IpSecTransform transform) throws IOException { + public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { try { mService.applyTunnelModeTransform( tunnel.getResourceId(), direction, transform.getResourceId()); diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 60e96f9434..cf58647bbb 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -350,6 +350,7 @@ public final class IpSecTransform implements AutoCloseable { * * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. */ + @NonNull public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an encryption algorithm. Preconditions.checkNotNull(algo); @@ -364,6 +365,7 @@ public final class IpSecTransform implements AutoCloseable { * * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. */ + @NonNull public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an authentication algorithm. Preconditions.checkNotNull(algo); @@ -384,6 +386,7 @@ public final class IpSecTransform implements AutoCloseable { * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to * be applied. */ + @NonNull public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) { Preconditions.checkNotNull(algo); mConfig.setAuthenticatedEncryption(algo); @@ -403,6 +406,7 @@ public final class IpSecTransform implements AutoCloseable { * @param remotePort the UDP port number of the remote host that will send and receive * encapsulated traffic. In the case of IKEv2, this should be port 4500. */ + @NonNull public IpSecTransform.Builder setIpv4Encapsulation( @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { Preconditions.checkNotNull(localSocket); @@ -436,6 +440,7 @@ public final class IpSecTransform implements AutoCloseable { * collides with an existing transform * @throws IOException indicating other errors */ + @NonNull public IpSecTransform buildTransportModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) @@ -472,6 +477,7 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi + @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, From a26fb9005288857602801cb97aa36cf74645b893 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Fri, 16 Mar 2018 17:27:30 -0700 Subject: [PATCH 139/881] Add NonNull Annotations To IpSec API Surface This CL adds NonNull annotations to a large number of method returns and parameters as part of API council feedback. Bug: 72473424 Test: compilation (docstring-only change) Merged-In: I2f865dde56fe12116c461ad98e9460bf1802ce18 Change-Id: I2f865dde56fe12116c461ad98e9460bf1802ce18 (cherry picked from commit 8fd26f67fdfdedb535ddb8c7d5ededa5dcba40f8) --- core/java/android/net/IpSecAlgorithm.java | 8 +++-- core/java/android/net/IpSecManager.java | 44 +++++++++++------------ core/java/android/net/IpSecTransform.java | 6 ++++ 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index c69a4d4c0b..d9ac981959 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -122,7 +122,7 @@ public final class IpSecAlgorithm implements Parcelable { * @param algorithm name of the algorithm. * @param key key padded to a multiple of 8 bits. */ - public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key) { + public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) { this(algorithm, key, key.length * 8); } @@ -137,7 +137,8 @@ public final class IpSecAlgorithm implements Parcelable { * @param key key padded to a multiple of 8 bits. * @param truncLenBits number of bits of output hash to use. */ - public IpSecAlgorithm(@AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) { + public IpSecAlgorithm( + @NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) { mName = algorithm; mKey = key.clone(); mTruncLenBits = truncLenBits; @@ -145,11 +146,13 @@ public final class IpSecAlgorithm implements Parcelable { } /** Get the algorithm name */ + @NonNull public String getName() { return mName; } /** Get the key for this algorithm */ + @NonNull public byte[] getKey() { return mKey.clone(); } @@ -263,6 +266,7 @@ public final class IpSecAlgorithm implements Parcelable { } @Override + @NonNull public String toString() { return new StringBuilder() .append("{mName=") diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index cb4299ef69..4157845d61 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -253,8 +253,9 @@ public final class IpSecManager { * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are * currently allocated for this user */ - public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress) - throws ResourceUnavailableException { + @NonNull + public SecurityParameterIndex allocateSecurityParameterIndex( + @NonNull InetAddress destinationAddress) throws ResourceUnavailableException { try { return new SecurityParameterIndex( mService, @@ -280,8 +281,9 @@ public final class IpSecManager { * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be * reserved */ + @NonNull public SecurityParameterIndex allocateSecurityParameterIndex( - InetAddress destinationAddress, int requestedSpi) + @NonNull InetAddress destinationAddress, int requestedSpi) throws SpiUnavailableException, ResourceUnavailableException { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); @@ -318,9 +320,8 @@ public final class IpSecManager { * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform( - Socket socket, @PolicyDirection int direction, IpSecTransform transform) - throws IOException { + public void applyTransportModeTransform(@NonNull Socket socket, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -353,9 +354,8 @@ public final class IpSecManager { * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform( - DatagramSocket socket, @PolicyDirection int direction, IpSecTransform transform) - throws IOException { + public void applyTransportModeTransform(@NonNull DatagramSocket socket, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -388,9 +388,8 @@ public final class IpSecManager { * @param transform a transport mode {@code IpSecTransform} * @throws IOException indicating that the transform could not be applied */ - public void applyTransportModeTransform( - FileDescriptor socket, @PolicyDirection int direction, IpSecTransform transform) - throws IOException { + public void applyTransportModeTransform(@NonNull FileDescriptor socket, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor() // constructor takes control and closes the user's FD when we exit the method. try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { @@ -413,8 +412,7 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(Socket socket) - throws IOException { + public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException { removeTransportModeTransforms(socket.getFileDescriptor$()); } @@ -431,8 +429,7 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(DatagramSocket socket) - throws IOException { + public void removeTransportModeTransforms(@NonNull DatagramSocket socket) throws IOException { removeTransportModeTransforms(socket.getFileDescriptor$()); } @@ -449,8 +446,7 @@ public final class IpSecManager { * @param socket a socket that previously had a transform applied to it * @throws IOException indicating that the transform could not be removed from the socket */ - public void removeTransportModeTransforms(FileDescriptor socket) - throws IOException { + public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.removeTransportModeTransforms(pfd); } catch (RemoteException e) { @@ -588,6 +584,7 @@ public final class IpSecManager { // safely usable for Encapsulation without allowing a user to possibly unbind from/close // the port, which could potentially impact the traffic of the next user who binds to that // socket. + @NonNull public UdpEncapsulationSocket openUdpEncapsulationSocket(int port) throws IOException, ResourceUnavailableException { /* @@ -617,6 +614,7 @@ public final class IpSecManager { // safely usable for Encapsulation without allowing a user to possibly unbind from/close // the port, which could potentially impact the traffic of the next user who binds to that // socket. + @NonNull public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { return new UdpEncapsulationSocket(mService, 0); @@ -645,6 +643,7 @@ public final class IpSecManager { private int mResourceId = INVALID_RESOURCE_ID; /** Get the underlying SPI held by this object. */ + @NonNull public String getInterfaceName() { return mInterfaceName; } @@ -659,7 +658,7 @@ public final class IpSecManager { * @hide */ @SystemApi - public void addAddress(LinkAddress address) throws IOException { + public void addAddress(@NonNull LinkAddress address) throws IOException { try { mService.addAddressToTunnelInterface(mResourceId, address); } catch (RemoteException e) { @@ -676,7 +675,7 @@ public final class IpSecManager { * @hide */ @SystemApi - public void removeAddress(LinkAddress address) throws IOException { + public void removeAddress(@NonNull LinkAddress address) throws IOException { try { mService.removeAddressFromTunnelInterface(mResourceId, address); } catch (RemoteException e) { @@ -768,6 +767,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) @@ -794,8 +794,8 @@ public final class IpSecManager { */ @SystemApi @RequiresPermission(android.Manifest.permission.NETWORK_STACK) - public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, - @PolicyDirection int direction, IpSecTransform transform) throws IOException { + public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, + @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { try { mService.applyTunnelModeTransform( tunnel.getResourceId(), direction, transform.getResourceId()); diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 60e96f9434..cf58647bbb 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -350,6 +350,7 @@ public final class IpSecTransform implements AutoCloseable { * * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied. */ + @NonNull public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an encryption algorithm. Preconditions.checkNotNull(algo); @@ -364,6 +365,7 @@ public final class IpSecTransform implements AutoCloseable { * * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied. */ + @NonNull public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an authentication algorithm. Preconditions.checkNotNull(algo); @@ -384,6 +386,7 @@ public final class IpSecTransform implements AutoCloseable { * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to * be applied. */ + @NonNull public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) { Preconditions.checkNotNull(algo); mConfig.setAuthenticatedEncryption(algo); @@ -403,6 +406,7 @@ public final class IpSecTransform implements AutoCloseable { * @param remotePort the UDP port number of the remote host that will send and receive * encapsulated traffic. In the case of IKEv2, this should be port 4500. */ + @NonNull public IpSecTransform.Builder setIpv4Encapsulation( @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { Preconditions.checkNotNull(localSocket); @@ -436,6 +440,7 @@ public final class IpSecTransform implements AutoCloseable { * collides with an existing transform * @throws IOException indicating other errors */ + @NonNull public IpSecTransform buildTransportModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) @@ -472,6 +477,7 @@ public final class IpSecTransform implements AutoCloseable { * @hide */ @SystemApi + @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, From 4b3f6f982ef74cc35e914481c94bad4515b0dfbf Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 6 Mar 2018 12:36:54 +0900 Subject: [PATCH 140/881] Add method to NetworkStatsService for UID stats. Useful for clients such as BatteryStats which currently rely on NetworkStatsFactory. Data at that stage is incomplete as it does not account for tethering, VT data and corresponding 464xlat corrections. Test: runtest frameworks-net, CTS tests pass. Change-Id: I763b77f601c827fd2963204694fb5b45425cc791 --- .../android/net/INetworkStatsService.aidl | 10 +++ core/java/android/net/NetworkStats.java | 64 +++++++++++++---- .../internal/net/NetworkStatsFactory.java | 72 ++++++++++++++----- .../server/net/NetworkStatsService.java | 38 ++++++++-- 4 files changed, 149 insertions(+), 35 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 90e3ffd550..eab70418a9 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -44,6 +44,16 @@ interface INetworkStatsService { /** Return data layer snapshot of UID network usage. */ NetworkStats getDataLayerSnapshotForUid(int uid); + + /** Get a detailed snapshot of stats since boot for all UIDs. + * + *

Results will not always be limited to stats on requiredIfaces when specified: stats for + * interfaces stacked on the specified interfaces, or for interfaces on which the specified + * interfaces are stacked on, will also be included. + * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}. + */ + NetworkStats getDetailedUidStats(in String[] requiredIfaces); + /** Return set of any ifaces associated with mobile networks since boot. */ String[] getMobileIfaces(); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 01b2b39213..940f98580c 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -64,6 +64,9 @@ public class NetworkStats implements Parcelable { /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */ public static final int SET_DBG_VPN_OUT = 1002; + /** Include all interfaces when filtering */ + public static final String[] INTERFACES_ALL = null; + /** {@link #tag} value for total data across all tags. */ // TODO: Rename TAG_NONE to TAG_ALL. public static final int TAG_NONE = 0; @@ -359,23 +362,27 @@ public class NetworkStats implements Parcelable { capacity = newLength; } - iface[size] = entry.iface; - uid[size] = entry.uid; - set[size] = entry.set; - tag[size] = entry.tag; - metered[size] = entry.metered; - roaming[size] = entry.roaming; - defaultNetwork[size] = entry.defaultNetwork; - rxBytes[size] = entry.rxBytes; - rxPackets[size] = entry.rxPackets; - txBytes[size] = entry.txBytes; - txPackets[size] = entry.txPackets; - operations[size] = entry.operations; + setValues(size, entry); size++; return this; } + private void setValues(int i, Entry entry) { + iface[i] = entry.iface; + uid[i] = entry.uid; + set[i] = entry.set; + tag[i] = entry.tag; + metered[i] = entry.metered; + roaming[i] = entry.roaming; + defaultNetwork[i] = entry.defaultNetwork; + rxBytes[i] = entry.rxBytes; + rxPackets[i] = entry.rxPackets; + txBytes[i] = entry.txBytes; + txPackets[i] = entry.txPackets; + operations[i] = entry.operations; + } + /** * Return specific stats entry. */ @@ -824,6 +831,39 @@ public class NetworkStats implements Parcelable { return stats; } + /** + * Only keep entries that match all specified filters. + * + *

This mutates the original structure in place. After this method is called, + * size is the number of matching entries, and capacity is the previous capacity. + * @param limitUid UID to filter for, or {@link #UID_ALL}. + * @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}. + * @param limitTag Tag to filter for, or {@link #TAG_ALL}. + */ + public void filter(int limitUid, String[] limitIfaces, int limitTag) { + if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { + return; + } + + Entry entry = new Entry(); + int nextOutputEntry = 0; + for (int i = 0; i < size; i++) { + entry = getValues(i, entry); + final boolean matches = + (limitUid == UID_ALL || limitUid == entry.uid) + && (limitTag == TAG_ALL || limitTag == entry.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, entry.iface)); + + if (matches) { + setValues(nextOutputEntry, entry); + nextOutputEntry++; + } + } + + size = nextOutputEntry; + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 902bd120e8..8172a20632 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -22,16 +22,14 @@ import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static com.android.server.NetworkManagementSocketTagger.kernelToTag; +import android.annotation.Nullable; import android.net.NetworkStats; import android.os.StrictMode; import android.os.SystemClock; -import android.util.ArrayMap; -import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; -import com.google.android.collect.Lists; import libcore.io.IoUtils; @@ -41,8 +39,10 @@ import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.net.ProtocolException; -import java.util.ArrayList; -import java.util.Objects; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Creates {@link NetworkStats} instances by parsing various {@code /proc/} @@ -70,18 +70,55 @@ public class NetworkStatsFactory { private boolean mUseBpfStats; - // TODO: to improve testability and avoid global state, do not use a static variable. - @GuardedBy("sStackedIfaces") - private static final ArrayMap sStackedIfaces = new ArrayMap<>(); + // TODO: only do adjustments in NetworkStatsService and remove this. + /** + * (Stacked interface) -> (base interface) association for all connected ifaces since boot. + * + * Because counters must never roll backwards, once a given interface is stacked on top of an + * underlying interface, the stacked interface can never be stacked on top of + * another interface. */ + private static final ConcurrentHashMap sStackedIfaces + = new ConcurrentHashMap<>(); public static void noteStackedIface(String stackedIface, String baseIface) { - synchronized (sStackedIfaces) { - if (baseIface != null) { - sStackedIfaces.put(stackedIface, baseIface); - } else { - sStackedIfaces.remove(stackedIface); + if (stackedIface != null && baseIface != null) { + sStackedIfaces.put(stackedIface, baseIface); + } + } + + /** + * Get a set of interfaces containing specified ifaces and stacked interfaces. + * + *

The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces + * on which the specified ones are stacked. Stacked interfaces are those noted with + * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method + * is called are guaranteed to be included. + */ + public static String[] augmentWithStackedInterfacesLocked(@Nullable String[] requiredIfaces) { + if (requiredIfaces == NetworkStats.INTERFACES_ALL) { + return null; + } + + HashSet relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces)); + // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse + // elements as they existed upon construction exactly once, and may + // (but are not guaranteed to) reflect any modifications subsequent to construction". + // This is enough here. + for (Map.Entry entry : sStackedIfaces.entrySet()) { + if (relatedIfaces.contains(entry.getKey())) { + relatedIfaces.add(entry.getValue()); + } else if (relatedIfaces.contains(entry.getValue())) { + relatedIfaces.add(entry.getKey()); } } + + String[] outArray = new String[relatedIfaces.size()]; + return relatedIfaces.toArray(outArray); + } + + @VisibleForTesting + public static void clearStackedIfaces() { + sStackedIfaces.clear(); } public NetworkStatsFactory() { @@ -250,12 +287,9 @@ public class NetworkStatsFactory { NetworkStats lastStats) throws IOException { final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); - final ArrayMap stackedIfaces; - synchronized (sStackedIfaces) { - stackedIfaces = new ArrayMap<>(sStackedIfaces); - } // Total 464xlat traffic to subtract from uid 0 on all base interfaces. - final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); + // sStackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. + final NetworkStats adjustments = new NetworkStats(0, sStackedIfaces.size()); NetworkStats.Entry entry = null; // For recycling @@ -269,7 +303,7 @@ public class NetworkStatsFactory { if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { continue; } - final String baseIface = stackedIfaces.get(entry.iface); + final String baseIface = sStackedIfaces.get(entry.iface); if (baseIface == null) { continue; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 82981275fc..e0a86437e0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,6 +27,7 @@ import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.INTERFACES_ALL; import static android.net.NetworkStats.METERED_ALL; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.SET_ALL; @@ -34,6 +35,7 @@ import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; import static android.net.NetworkStats.STATS_PER_IFACE; import static android.net.NetworkStats.STATS_PER_UID; +import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; @@ -128,6 +130,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.NetworkStatsFactory; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; @@ -143,6 +146,7 @@ import java.io.PrintWriter; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Map; /** * Collect and persist detailed network statistics, and provide this data to @@ -726,7 +730,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final long token = Binder.clearCallingIdentity(); final NetworkStats networkLayer; try { - networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid); + networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid, + NetworkStats.INTERFACES_ALL); } finally { Binder.restoreCallingIdentity(token); } @@ -747,6 +752,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return dataLayer; } + @Override + public NetworkStats getDetailedUidStats(String[] requiredIfaces) { + try { + final String[] ifacesToQuery = + NetworkStatsFactory.augmentWithStackedInterfacesLocked(requiredIfaces); + return getNetworkStatsUidDetail(ifacesToQuery); + } catch (RemoteException e) { + Log.wtf(TAG, "Error compiling UID stats", e); + return new NetworkStats(0L, 0); + } + } + @Override public String[] getMobileIfaces() { return mMobileIfaces; @@ -1109,6 +1126,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (isMobile) { mobileIfaces.add(stackedIface); } + + NetworkStatsFactory.noteStackedIface(stackedIface, baseIface); } } } @@ -1130,7 +1149,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void recordSnapshotLocked(long currentTime) throws RemoteException { // snapshot and record current counters; read UID stats first to // avoid over counting dev stats. - final NetworkStats uidSnapshot = getNetworkStatsUidDetail(); + final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL); final NetworkStats xtSnapshot = getNetworkStatsXt(); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); @@ -1464,12 +1483,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Return snapshot of current UID statistics, including any * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations} * values. + * + * @param ifaces A list of interfaces the stats should be restricted to, or + * {@link NetworkStats#INTERFACES_ALL}. */ - private NetworkStats getNetworkStatsUidDetail() throws RemoteException { - final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); + private NetworkStats getNetworkStatsUidDetail(String[] ifaces) + throws RemoteException { + + final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL, + ifaces); // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); + tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1478,10 +1504,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold video calling data usage stats into uid snapshot final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { + vtStats.filter(UID_ALL, ifaces, TAG_ALL); uidSnapshot.combineAllValues(vtStats); } + uidSnapshot.combineAllValues(mUidOperations); + // TODO: apply tethering & VC 464xlat adjustments here + return uidSnapshot; } From 9a713bd28ec77d361041025496d73a8935621f79 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 21 Mar 2018 15:32:42 -0700 Subject: [PATCH 141/881] Add MANAGE_IPSEC_TUNNELS Permission Add a new MANAGE_IPSEC_TUNNELS permission and protect all IPsec Tunnel mode APIs with it. This permission is only granted to the system or through an AppOp. Bug: 66955045 Test: compilation Change-Id: I0f618373b500c493ef2211bece681f74652a1833 --- core/java/android/net/IpSecManager.java | 6 ++++-- core/java/android/net/IpSecTransform.java | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 4157845d61..972b9c0746 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -658,6 +658,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull LinkAddress address) throws IOException { try { mService.addAddressToTunnelInterface(mResourceId, address); @@ -675,6 +676,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull LinkAddress address) throws IOException { try { mService.removeAddressFromTunnelInterface(mResourceId, address); @@ -768,7 +770,7 @@ public final class IpSecManager { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { @@ -793,7 +795,7 @@ public final class IpSecManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { try { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index cf58647bbb..099fe02fdd 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -282,7 +282,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD }) public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback, @@ -325,7 +325,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD }) public void stopNattKeepalive() { @@ -478,7 +478,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) From bd313c2e1926f6debff8625028d4a865a69bf3e3 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 14 Mar 2018 19:01:14 -0700 Subject: [PATCH 142/881] Add documentation for TCP interactions with transforms Updates API documentation to mention that TCP sockets where transforms are deactivated will not send FIN packets. Bug: 74851550 Test: API updates only Change-Id: I8169f221c8c747538a8bddfbf02dcc73c9337189 --- core/java/android/net/IpSecManager.java | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index b60984771a..246d1e1860 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -299,6 +299,19 @@ public final class IpSecManager { * will throw IOException if the user deactivates the transform (by calling {@link * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * + *

Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an + * applied transform before completion of graceful shutdown may result in the shutdown sequence + * failing to complete. As such, applications requiring graceful shutdown MUST close the socket + * prior to deactivating the applied transform. Socket closure may be performed asynchronously + * (in batches), so the returning of a close function does not guarantee shutdown of a socket. + * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is + * sufficient to ensure shutdown. + * + * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), + * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] + * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the + * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. + * *

Rekey Procedure

* *

When applying a new tranform to a socket, the previous transform will be removed. However, @@ -364,6 +377,19 @@ public final class IpSecManager { * will throw IOException if the user deactivates the transform (by calling {@link * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * + *

Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an + * applied transform before completion of graceful shutdown may result in the shutdown sequence + * failing to complete. As such, applications requiring graceful shutdown MUST close the socket + * prior to deactivating the applied transform. Socket closure may be performed asynchronously + * (in batches), so the returning of a close function does not guarantee shutdown of a socket. + * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is + * sufficient to ensure shutdown. + * + * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), + * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] + * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the + * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. + * *

Rekey Procedure

* *

When applying a new tranform to a socket, the previous transform will be removed. However, From 8d66e650a1c2ed67905b6a76694d751cdacf7834 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 26 Mar 2018 13:11:33 -0600 Subject: [PATCH 143/881] API council requested tweaks to TrafficStats. Test: atest android.appsecurity.cts.AppSecurityTests#testAppFailAccessPrivateData Bug: 71584606 Change-Id: I4be8a47d54a04f17cbaac735d543ff7d6370376d --- core/java/android/net/TrafficStats.java | 32 ++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 7922276edb..40d53b741d 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -16,7 +16,6 @@ package android.net; -import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -259,22 +258,35 @@ public class TrafficStats { /** * Set specific UID to use when accounting {@link Socket} traffic * originating from the current thread. Designed for use when performing an - * operation on behalf of another application. + * operation on behalf of another application, or when another application + * is performing operations on your behalf. + *

+ * Any app can accept blame for traffic performed on a socket + * originally created by another app by calling this method with the + * {@link android.system.Os#getuid()} value. However, only apps holding the + * {@code android.Manifest.permission#UPDATE_DEVICE_STATS} permission may + * assign blame to another UIDs. *

* Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. - *

- * To take effect, caller must hold - * {@link android.Manifest.permission#UPDATE_DEVICE_STATS} permission. - * - * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) + @SuppressLint("Doclava125") public static void setThreadStatsUid(int uid) { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); } + /** + * Get the active UID used when accounting {@link Socket} traffic originating + * from the current thread. Only one active tag per thread is supported. + * {@link #tagSocket(Socket)}. + * + * @see #setThreadStatsUid(int) + */ + public static int getThreadStatsUid() { + return NetworkManagementSocketTagger.getThreadSocketStatsUid(); + } + /** * Set specific UID to use when accounting {@link Socket} traffic * originating from the current thread as the calling UID. Designed for use @@ -282,7 +294,11 @@ public class TrafficStats { *

* Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. + * + * @removed + * @deprecated use {@link #setThreadStatsUid(int)} instead. */ + @Deprecated public static void setThreadStatsUidSelf() { setThreadStatsUid(android.os.Process.myUid()); } From 98a09350030930c1add229fa658a4b3902a40be3 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 27 Mar 2018 11:09:16 -0600 Subject: [PATCH 144/881] Don't let callers OOM the system process. Constrain our default history size to 180 days; if we end up needing more, we'll dynamically grow the history object. Test: manual Bug: 70916680 Change-Id: Id885f9800ad8f45fb0c1a89dab5a4b10ffd9e2f2 --- .../com/android/server/net/NetworkStatsCollection.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index a5f8dc72d8..2ef754e2ba 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -16,9 +16,9 @@ package com.android.server.net; -import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; +import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_NO; @@ -42,9 +42,11 @@ import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; import android.service.NetworkStatsCollectionStatsProto; import android.telephony.SubscriptionPlan; +import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.IntArray; +import android.util.MathUtils; import android.util.Pair; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -245,7 +247,10 @@ public class NetworkStatsCollection implements FileRotator.Reader { + " is forbidden for caller " + callerUid); } - final int bucketEstimate = (int) ((end - start) / mBucketDuration); + // 180 days of history should be enough for anyone; if we end up needing + // more, we'll dynamically grow the history object. + final int bucketEstimate = (int) MathUtils.constrain(((end - start) / mBucketDuration), 0, + (180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration); final NetworkStatsHistory combined = new NetworkStatsHistory( mBucketDuration, bucketEstimate, fields); From f685da3d66f0202eab363782df993b2991e3cc5c Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 14 Mar 2018 19:01:14 -0700 Subject: [PATCH 145/881] Add documentation for TCP interactions with transforms Updates API documentation to mention that TCP sockets where transforms are deactivated will not send FIN packets. Bug: 74851550 Test: API updates only Merged-In: I8169f221c8c747538a8bddfbf02dcc73c9337189 Change-Id: I8169f221c8c747538a8bddfbf02dcc73c9337189 (cherry picked from commit bd313c2e1926f6debff8625028d4a865a69bf3e3) --- core/java/android/net/IpSecManager.java | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 972b9c0746..a88fe0428a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -305,6 +305,19 @@ public final class IpSecManager { * will throw IOException if the user deactivates the transform (by calling {@link * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * + *

Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an + * applied transform before completion of graceful shutdown may result in the shutdown sequence + * failing to complete. As such, applications requiring graceful shutdown MUST close the socket + * prior to deactivating the applied transform. Socket closure may be performed asynchronously + * (in batches), so the returning of a close function does not guarantee shutdown of a socket. + * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is + * sufficient to ensure shutdown. + * + * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), + * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] + * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the + * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. + * *

Rekey Procedure

* *

When applying a new tranform to a socket in the outbound direction, the previous transform @@ -373,6 +386,19 @@ public final class IpSecManager { * will throw IOException if the user deactivates the transform (by calling {@link * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}. * + *

Note that when applied to TCP sockets, calling {@link IpSecTransform#close()} on an + * applied transform before completion of graceful shutdown may result in the shutdown sequence + * failing to complete. As such, applications requiring graceful shutdown MUST close the socket + * prior to deactivating the applied transform. Socket closure may be performed asynchronously + * (in batches), so the returning of a close function does not guarantee shutdown of a socket. + * Setting an SO_LINGER timeout results in socket closure being performed synchronously, and is + * sufficient to ensure shutdown. + * + * Specifically, if the transform is deactivated (by calling {@link IpSecTransform#close()}), + * prior to the socket being closed, the standard [FIN - FIN/ACK - ACK], or the reset [RST] + * packets are dropped due to the lack of a valid Transform. Similarly, if a socket without the + * SO_LINGER option set is closed, the delayed/batched FIN packets may be dropped. + * *

Rekey Procedure

* *

When applying a new tranform to a socket in the outbound direction, the previous transform From b6d036d6b34e019b936e2c6cf7615f7633a4bdc3 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 27 Mar 2018 16:55:48 -0700 Subject: [PATCH 146/881] Clarify UDP encapsulation socket API This change updates the getSocket() methods for IPsec to improve clarity of the return types, both for public APIs, and internal-only methods. Bug: 72473753 Test: APIs updated, CTS + unit tests ran. Change-Id: I0afebd432c5d04c47c93daa1ce616d712aa323d7 --- core/java/android/net/IpSecManager.java | 6 +++--- services/core/java/com/android/server/IpSecService.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index b60984771a..5cdac55799 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -484,7 +484,7 @@ public final class IpSecManager { * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the * caller. The caller should not close the {@code FileDescriptor} returned by {@link - * #getSocket}, but should use {@link #close} instead. + * #getFileDescriptor}, but should use {@link #close} instead. * *

Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic * of the next user who binds to that port. To prevent this scenario, these sockets are held @@ -523,8 +523,8 @@ public final class IpSecManager { mCloseGuard.open("constructor"); } - /** Get the wrapped socket. */ - public FileDescriptor getSocket() { + /** Get the encapsulation socket's file descriptor. */ + public FileDescriptor getFileDescriptor() { if (mPfd == null) { return null; } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 45a4dfb91b..d9d24c4902 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -934,7 +934,7 @@ public class IpSecService extends IIpSecService.Stub { return mPort; } - public FileDescriptor getSocket() { + public FileDescriptor getFileDescriptor() { return mSocket; } From b477e70aed4774d9f2d8d1a55b8d65624691bb0c Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 27 Feb 2018 16:47:22 +0900 Subject: [PATCH 147/881] Fix network usage stats on 464xlat tethered. Usage stats corrections for 464xlat in NetworkStatsFactory are not applied to tethered traffic. Add adjustments in NetworkStatsService. After migrating external callers off NetworkStatsFactory, we will be able to only apply adjustments in NetworkStatsService and remove stacked interface tracking from NetworkStatsFactory. Bug: 72107146 Fixes: 72107146 Test: runtest frameworks-net & manual - checked corrected network usage Change-Id: I5ce450e616b4fddf21f2a491fe5d0c9e9f969bda --- core/java/android/net/NetworkStats.java | 75 +++++++++++++++++++ .../internal/net/NetworkStatsFactory.java | 60 ++++----------- .../server/net/NetworkStatsService.java | 8 +- 3 files changed, 92 insertions(+), 51 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 940f98580c..d6cbc88524 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -31,6 +31,7 @@ import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; import java.util.HashSet; +import java.util.Map; import java.util.Objects; /** @@ -97,6 +98,11 @@ public class NetworkStats implements Parcelable { /** Denotes a request for stats at the interface and UID level. */ public static final int STATS_PER_UID = 1; + private static final String CLATD_INTERFACE_PREFIX = "v4-"; + // Delta between IPv4 header (20b) and IPv6 header (40b). + // Used for correct stats accounting on clatd interfaces. + private static final int IPV4V6_HEADER_DELTA = 20; + // TODO: move fields to "mVariable" notation /** @@ -751,6 +757,75 @@ public class NetworkStats implements Parcelable { return result; } + /** + * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * + *

This mutates both base and stacked traffic stats, to account respectively for + * double-counted traffic and IPv4/IPv6 header size difference. + * + *

For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 + * packet on the stacked interface, and once as translated to an IPv6 packet on the + * base interface. For correct stats accounting on the base interface, every 464xlat + * packet needs to be subtracted from the root UID on the base interface both for tx + * and rx traffic (http://b/12249687, http:/b/33681750). + * + *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only + * {@code ConcurrentHashMap} + * @param baseTraffic Traffic on the base interfaces. Will be mutated. + * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. + * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + */ + public static void apply464xlatAdjustments(NetworkStats baseTraffic, + NetworkStats stackedTraffic, Map stackedIfaces) { + // Total 464xlat traffic to subtract from uid 0 on all base interfaces. + // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. + final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); + + // For recycling + Entry entry = null; + Entry adjust = new NetworkStats.Entry(IFACE_ALL, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); + + for (int i = 0; i < stackedTraffic.size; i++) { + entry = stackedTraffic.getValues(i, entry); + if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { + continue; + } + final String baseIface = stackedIfaces.get(entry.iface); + if (baseIface == null) { + continue; + } + // Subtract any 464lat traffic seen for the root UID on the current base interface. + adjust.iface = baseIface; + adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); + adjust.rxPackets = -entry.rxPackets; + adjust.txPackets = -entry.txPackets; + adjustments.combineValues(adjust); + + // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent + // on the stacked interface with prefix "v4-" and drops the IPv6 header size after + // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes + // difference for all packets (http://b/12249687, http:/b/33681750). + entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA; + entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA; + stackedTraffic.setValues(i, entry); + } + + baseTraffic.combineAllValues(adjustments); + } + + /** + * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * + *

This mutates the object this method is called on. Equivalent to calling + * {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as + * base and stacked traffic. + * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + */ + public void apply464xlatAdjustments(Map stackedIfaces) { + apply464xlatAdjustments(this, this, stackedIfaces); + } + /** * Return total statistics grouped by {@link #iface}; doesn't mutate the * original structure. diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 8172a20632..8561bf0279 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -54,11 +54,6 @@ public class NetworkStatsFactory { private static final boolean USE_NATIVE_PARSING = true; private static final boolean SANITY_CHECK_NATIVE = false; - private static final String CLATD_INTERFACE_PREFIX = "v4-"; - // Delta between IPv4 header (20b) and IPv6 header (40b). - // Used for correct stats accounting on clatd interfaces. - private static final int IPV4V6_HEADER_DELTA = 20; - /** Path to {@code /proc/net/dev}. */ private final File mStatsIfaceDev; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ @@ -94,7 +89,7 @@ public class NetworkStatsFactory { * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method * is called are guaranteed to be included. */ - public static String[] augmentWithStackedInterfacesLocked(@Nullable String[] requiredIfaces) { + public static String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { if (requiredIfaces == NetworkStats.INTERFACES_ALL) { return null; } @@ -116,6 +111,15 @@ public class NetworkStatsFactory { return relatedIfaces.toArray(outArray); } + /** + * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. + * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map) + */ + public static void apply464xlatAdjustments(NetworkStats baseTraffic, + NetworkStats stackedTraffic) { + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces); + } + @VisibleForTesting public static void clearStackedIfaces() { sStackedIfaces.clear(); @@ -287,48 +291,10 @@ public class NetworkStatsFactory { NetworkStats lastStats) throws IOException { final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); - // Total 464xlat traffic to subtract from uid 0 on all base interfaces. - // sStackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. - final NetworkStats adjustments = new NetworkStats(0, sStackedIfaces.size()); - NetworkStats.Entry entry = null; // For recycling - - // For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 - // packet on the stacked interface, and once as translated to an IPv6 packet on the - // base interface. For correct stats accounting on the base interface, every 464xlat - // packet needs to be subtracted from the root UID on the base interface both for tx - // and rx traffic (http://b/12249687, http:/b/33681750). - for (int i = 0; i < stats.size(); i++) { - entry = stats.getValues(i, entry); - if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { - continue; - } - final String baseIface = sStackedIfaces.get(entry.iface); - if (baseIface == null) { - continue; - } - - NetworkStats.Entry adjust = - new NetworkStats.Entry(baseIface, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); - // Subtract any 464lat traffic seen for the root UID on the current base interface. - adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); - adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets -= entry.rxPackets; - adjust.txPackets -= entry.txPackets; - adjustments.combineValues(adjust); - - // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent - // on the stacked interface with prefix "v4-" and drops the IPv6 header size after - // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes - // difference for all packets (http://b/12249687, http:/b/33681750). - entry.rxBytes = entry.rxPackets * IPV4V6_HEADER_DELTA; - entry.txBytes = entry.txPackets * IPV4V6_HEADER_DELTA; - entry.rxPackets = 0; - entry.txPackets = 0; - stats.combineValues(entry); - } - - stats.combineAllValues(adjustments); + // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. + // TODO: remove this and only apply adjustments in NetworkStatsService. + stats.apply464xlatAdjustments(sStackedIfaces); return stats; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index e0a86437e0..da40692a43 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -146,7 +146,6 @@ import java.io.PrintWriter; import java.util.Arrays; import java.util.HashSet; import java.util.List; -import java.util.Map; /** * Collect and persist detailed network statistics, and provide this data to @@ -756,7 +755,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { final String[] ifacesToQuery = - NetworkStatsFactory.augmentWithStackedInterfacesLocked(requiredIfaces); + NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); @@ -1490,12 +1489,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats getNetworkStatsUidDetail(String[] ifaces) throws RemoteException { + // TODO: remove 464xlat adjustments from NetworkStatsFactory and apply all at once here. final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL, ifaces); // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1505,13 +1506,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats); uidSnapshot.combineAllValues(vtStats); } uidSnapshot.combineAllValues(mUidOperations); - // TODO: apply tethering & VC 464xlat adjustments here - return uidSnapshot; } From 4076b1311de8f59e1163089e167d5ba851c36355 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 28 Mar 2018 08:52:51 -0700 Subject: [PATCH 148/881] Disallow Reserved SPI Allocation Disallow the allocation of SPIs in the range reserved for future use by RFC 4303. Bug: 77205120 Test: runtest frameworks-net Change-Id: I05e26ed34b5871f1a07d5bd7b58b79a64cd74b67 --- core/java/android/net/IpSecManager.java | 3 ++- services/core/java/com/android/server/IpSecService.java | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 4157845d61..abf51fa7de 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -274,7 +274,8 @@ public final class IpSecManager { * * @param destinationAddress the destination address for traffic bearing the requested SPI. * For inbound traffic, the destination should be an address currently assigned on-device. - * @param requestedSpi the requested SPI, or '0' to allocate a random SPI + * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. The range 1-255 is + * reserved and may not be used. See RFC 4303 Section 2.1. * @return the reserved SecurityParameterIndex * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are * currently allocated for this user diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index d09a161d1e..70efed2c2b 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1065,7 +1065,10 @@ public class IpSecService extends IIpSecService.Stub { public synchronized IpSecSpiResponse allocateSecurityParameterIndex( String destinationAddress, int requestedSpi, IBinder binder) throws RemoteException { checkInetAddress(destinationAddress); - /* requestedSpi can be anything in the int range, so no check is needed. */ + // RFC 4303 Section 2.1 - 0=local, 1-255=reserved. + if (requestedSpi > 0 && requestedSpi < 256) { + throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255."); + } checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); From e6f2de337fea7b77f62585953c51629ab5d56e7a Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 28 Mar 2018 13:10:40 -0700 Subject: [PATCH 149/881] Require explicitly supplied truncation length Instead of providing default truncation lengths (based on RFC or otherwise), this change imposes a restriction that the truncation length must be supplied for all auth or aead algorithms. Bug: 77204048 Test: Updated tests, ran on walleye Change-Id: I4a0e2e71aa97259e56f44e7c8a2ce53135708d97 --- core/java/android/net/IpSecAlgorithm.java | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 57f05884ce..8034bb62c9 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -56,7 +56,8 @@ public final class IpSecAlgorithm implements Parcelable { * new applications and is provided for legacy compatibility with 3gpp infrastructure. * *

Keys for this algorithm must be 128 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 128. + * + *

Valid truncation lengths are multiples of 8 bits from 96 to 128. */ public static final String AUTH_HMAC_MD5 = "hmac(md5)"; @@ -65,7 +66,8 @@ public final class IpSecAlgorithm implements Parcelable { * new applications and is provided for legacy compatibility with 3gpp infrastructure. * *

Keys for this algorithm must be 160 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 160. + * + *

Valid truncation lengths are multiples of 8 bits from 96 to 160. */ public static final String AUTH_HMAC_SHA1 = "hmac(sha1)"; @@ -73,7 +75,8 @@ public final class IpSecAlgorithm implements Parcelable { * SHA256 HMAC Authentication/Integrity Algorithm. * *

Keys for this algorithm must be 256 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 256. + * + *

Valid truncation lengths are multiples of 8 bits from 96 to 256. */ public static final String AUTH_HMAC_SHA256 = "hmac(sha256)"; @@ -81,7 +84,8 @@ public final class IpSecAlgorithm implements Parcelable { * SHA384 HMAC Authentication/Integrity Algorithm. * *

Keys for this algorithm must be 384 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 192 to (default) 384. + * + *

Valid truncation lengths are multiples of 8 bits from 192 to 384. */ public static final String AUTH_HMAC_SHA384 = "hmac(sha384)"; @@ -89,7 +93,8 @@ public final class IpSecAlgorithm implements Parcelable { * SHA512 HMAC Authentication/Integrity Algorithm. * *

Keys for this algorithm must be 512 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 256 to (default) 512. + * + *

Valid truncation lengths are multiples of 8 bits from 256 to 512. */ public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; @@ -112,6 +117,7 @@ public final class IpSecAlgorithm implements Parcelable { AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, + AUTH_HMAC_SHA384, AUTH_HMAC_SHA512, AUTH_CRYPT_AES_GCM }) @@ -126,11 +132,14 @@ public final class IpSecAlgorithm implements Parcelable { * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are * defined as constants in this class. * + *

For algorithms that produce an integrity check value, the truncation length is a required + * parameter. See {@link #IpSecAlgorithm(String algorithm, byte[] key, int truncLenBits)} + * * @param algorithm name of the algorithm. * @param key key padded to a multiple of 8 bits. */ public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) { - this(algorithm, key, key.length * 8); + this(algorithm, key, 0); } /** @@ -228,6 +237,7 @@ public final class IpSecAlgorithm implements Parcelable { case AUTH_CRYPT_AES_GCM: // The keying material for GCM is a key plus a 32-bit salt isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32; + isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128; break; default: throw new IllegalArgumentException("Couldn't find an algorithm: " + name); From 17c972f3c053dff1d5d16e0fa488780f3fcb28dc Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 5 Mar 2018 18:14:56 +0900 Subject: [PATCH 150/881] Allow null subscriberId in NetworkStatsManager. Use a MATCH_MOBILE_WILDCARD template to avoid filtering by subscriberId when querying statistics from NetworkStatsService. Bug: 74038898 Change-Id: I8296220472a9ba37044dd1a5ede9bdb45d3ed339 Fixes: 74038898 Test: runtest frameworks-net, CTS tests pass Merged-In: I1e4e283c6eaecf33d12488e41e0c524f6ff83954 Merged-In: Ia84d2c7cc63bf8b8bf30f133e0382fd7103bf490 (cherry-picked from aosp I4b39e7031416cb33b23d89aa36ff0f774eaa942f) --- core/java/android/app/usage/NetworkStats.java | 6 +-- .../app/usage/NetworkStatsManager.java | 40 ++++++++++++------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index da36157d85..e315e9115f 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -24,7 +24,6 @@ import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; import android.os.RemoteException; -import android.os.ServiceManager; import android.util.IntArray; import android.util.Log; @@ -98,9 +97,8 @@ public final class NetworkStats implements AutoCloseable { /** @hide */ NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp, - long endTimestamp) throws RemoteException, SecurityException { - final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + long endTimestamp, INetworkStatsService statsService) + throws RemoteException, SecurityException { // Open network stats session mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName()); mCloseGuard.open("close"); diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 5576e86edd..2357637b72 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -37,6 +37,8 @@ import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; + /** * Provides access to network usage history and statistics. Usage data is collected in * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details. @@ -107,9 +109,15 @@ public class NetworkStatsManager { * {@hide} */ public NetworkStatsManager(Context context) throws ServiceNotFoundException { + this(context, INetworkStatsService.Stub.asInterface( + ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); + } + + /** @hide */ + @VisibleForTesting + public NetworkStatsManager(Context context, INetworkStatsService service) { mContext = context; - mService = INetworkStatsService.Stub.asInterface( - ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)); + mService = service; setPollOnOpen(true); } @@ -135,7 +143,8 @@ public class NetworkStatsManager { public Bucket querySummaryForDevice(NetworkTemplate template, long startTime, long endTime) throws SecurityException, RemoteException { Bucket bucket = null; - NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); + NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, + mService); bucket = stats.getDeviceSummaryForNetwork(); stats.close(); @@ -208,7 +217,7 @@ public class NetworkStatsManager { } NetworkStats stats; - stats = new NetworkStats(mContext, template, mFlags, startTime, endTime); + stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); stats.startSummaryEnumeration(); stats.close(); @@ -245,7 +254,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, mFlags, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); result.startSummaryEnumeration(); return result; @@ -295,7 +304,7 @@ public class NetworkStatsManager { NetworkStats result; try { - result = new NetworkStats(mContext, template, mFlags, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); result.startHistoryEnumeration(uid, tag); } catch (RemoteException e) { Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e); @@ -341,7 +350,7 @@ public class NetworkStatsManager { } NetworkStats result; - result = new NetworkStats(mContext, template, mFlags, startTime, endTime); + result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); result.startUserUidEnumeration(); return result; } @@ -451,19 +460,20 @@ public class NetworkStatsManager { } private static NetworkTemplate createTemplate(int networkType, String subscriberId) { - NetworkTemplate template = null; + final NetworkTemplate template; switch (networkType) { - case ConnectivityManager.TYPE_MOBILE: { - template = NetworkTemplate.buildTemplateMobileAll(subscriberId); - } break; - case ConnectivityManager.TYPE_WIFI: { + case ConnectivityManager.TYPE_MOBILE: + template = subscriberId == null + ? NetworkTemplate.buildTemplateMobileWildcard() + : NetworkTemplate.buildTemplateMobileAll(subscriberId); + break; + case ConnectivityManager.TYPE_WIFI: template = NetworkTemplate.buildTemplateWifiWildcard(); - } break; - default: { + break; + default: throw new IllegalArgumentException("Cannot create template for network type " + networkType + ", subscriberId '" + NetworkIdentity.scrubSubscriberId(subscriberId) + "'."); - } } return template; } From 8fcf85d6b884b374ee8c11aed454d81f92f85312 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 27 Mar 2018 16:55:48 -0700 Subject: [PATCH 151/881] Clarify UDP encapsulation socket API This change updates the getSocket() methods for IPsec to improve clarity of the return types, both for public APIs, and internal-only methods. Bug: 72473753 Test: APIs updated, CTS + unit tests ran. Merged-In: I0afebd432c5d04c47c93daa1ce616d712aa323d7 Change-Id: I0afebd432c5d04c47c93daa1ce616d712aa323d7 (cherry picked from commit b6d036d6b34e019b936e2c6cf7615f7633a4bdc3) --- core/java/android/net/IpSecManager.java | 6 +++--- services/core/java/com/android/server/IpSecService.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index a88fe0428a..c7234e3165 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -502,7 +502,7 @@ public final class IpSecManager { * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the * caller. The caller should not close the {@code FileDescriptor} returned by {@link - * #getSocket}, but should use {@link #close} instead. + * #getFileDescriptor}, but should use {@link #close} instead. * *

Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic * of the next user who binds to that port. To prevent this scenario, these sockets are held @@ -541,8 +541,8 @@ public final class IpSecManager { mCloseGuard.open("constructor"); } - /** Get the wrapped socket. */ - public FileDescriptor getSocket() { + /** Get the encapsulation socket's file descriptor. */ + public FileDescriptor getFileDescriptor() { if (mPfd == null) { return null; } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index d09a161d1e..06c10564ab 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -931,7 +931,7 @@ public class IpSecService extends IIpSecService.Stub { return mPort; } - public FileDescriptor getSocket() { + public FileDescriptor getFileDescriptor() { return mSocket; } From 73ed7b3c8a3e727bdeb161143e033517a48be88c Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 28 Mar 2018 13:10:40 -0700 Subject: [PATCH 152/881] Require explicitly supplied truncation length Instead of providing default truncation lengths (based on RFC or otherwise), this change imposes a restriction that the truncation length must be supplied for all auth or aead algorithms. Bug: 77204048 Test: Updated tests, ran on walleye Merged-In: I4a0e2e71aa97259e56f44e7c8a2ce53135708d97 Change-Id: I4a0e2e71aa97259e56f44e7c8a2ce53135708d97 (cherry picked from commit e6f2de337fea7b77f62585953c51629ab5d56e7a) --- core/java/android/net/IpSecAlgorithm.java | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 57f05884ce..8034bb62c9 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -56,7 +56,8 @@ public final class IpSecAlgorithm implements Parcelable { * new applications and is provided for legacy compatibility with 3gpp infrastructure. * *

Keys for this algorithm must be 128 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 128. + * + *

Valid truncation lengths are multiples of 8 bits from 96 to 128. */ public static final String AUTH_HMAC_MD5 = "hmac(md5)"; @@ -65,7 +66,8 @@ public final class IpSecAlgorithm implements Parcelable { * new applications and is provided for legacy compatibility with 3gpp infrastructure. * *

Keys for this algorithm must be 160 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 160. + * + *

Valid truncation lengths are multiples of 8 bits from 96 to 160. */ public static final String AUTH_HMAC_SHA1 = "hmac(sha1)"; @@ -73,7 +75,8 @@ public final class IpSecAlgorithm implements Parcelable { * SHA256 HMAC Authentication/Integrity Algorithm. * *

Keys for this algorithm must be 256 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 96 to (default) 256. + * + *

Valid truncation lengths are multiples of 8 bits from 96 to 256. */ public static final String AUTH_HMAC_SHA256 = "hmac(sha256)"; @@ -81,7 +84,8 @@ public final class IpSecAlgorithm implements Parcelable { * SHA384 HMAC Authentication/Integrity Algorithm. * *

Keys for this algorithm must be 384 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 192 to (default) 384. + * + *

Valid truncation lengths are multiples of 8 bits from 192 to 384. */ public static final String AUTH_HMAC_SHA384 = "hmac(sha384)"; @@ -89,7 +93,8 @@ public final class IpSecAlgorithm implements Parcelable { * SHA512 HMAC Authentication/Integrity Algorithm. * *

Keys for this algorithm must be 512 bits in length. - *

Valid truncation lengths are multiples of 8 bits from 256 to (default) 512. + * + *

Valid truncation lengths are multiples of 8 bits from 256 to 512. */ public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; @@ -112,6 +117,7 @@ public final class IpSecAlgorithm implements Parcelable { AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, + AUTH_HMAC_SHA384, AUTH_HMAC_SHA512, AUTH_CRYPT_AES_GCM }) @@ -126,11 +132,14 @@ public final class IpSecAlgorithm implements Parcelable { * Creates an IpSecAlgorithm of one of the supported types. Supported algorithm names are * defined as constants in this class. * + *

For algorithms that produce an integrity check value, the truncation length is a required + * parameter. See {@link #IpSecAlgorithm(String algorithm, byte[] key, int truncLenBits)} + * * @param algorithm name of the algorithm. * @param key key padded to a multiple of 8 bits. */ public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) { - this(algorithm, key, key.length * 8); + this(algorithm, key, 0); } /** @@ -228,6 +237,7 @@ public final class IpSecAlgorithm implements Parcelable { case AUTH_CRYPT_AES_GCM: // The keying material for GCM is a key plus a 32-bit salt isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32; + isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128; break; default: throw new IllegalArgumentException("Couldn't find an algorithm: " + name); From b3b460821b8ccdff6459d25e2d49091685a30ae5 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 28 Mar 2018 08:52:51 -0700 Subject: [PATCH 153/881] Disallow Reserved SPI Allocation Disallow the allocation of SPIs in the range reserved for future use by RFC 4303. Bug: 77205120 Test: runtest frameworks-net Merged-In: I05e26ed34b5871f1a07d5bd7b58b79a64cd74b67 Change-Id: I05e26ed34b5871f1a07d5bd7b58b79a64cd74b67 (cherry picked from commit 4076b1311de8f59e1163089e167d5ba851c36355) --- core/java/android/net/IpSecManager.java | 3 ++- services/core/java/com/android/server/IpSecService.java | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index c7234e3165..1525508326 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -274,7 +274,8 @@ public final class IpSecManager { * * @param destinationAddress the destination address for traffic bearing the requested SPI. * For inbound traffic, the destination should be an address currently assigned on-device. - * @param requestedSpi the requested SPI, or '0' to allocate a random SPI + * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. The range 1-255 is + * reserved and may not be used. See RFC 4303 Section 2.1. * @return the reserved SecurityParameterIndex * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are * currently allocated for this user diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 06c10564ab..bde6bd8db6 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1065,7 +1065,10 @@ public class IpSecService extends IIpSecService.Stub { public synchronized IpSecSpiResponse allocateSecurityParameterIndex( String destinationAddress, int requestedSpi, IBinder binder) throws RemoteException { checkInetAddress(destinationAddress); - /* requestedSpi can be anything in the int range, so no check is needed. */ + // RFC 4303 Section 2.1 - 0=local, 1-255=reserved. + if (requestedSpi > 0 && requestedSpi < 256) { + throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255."); + } checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); From 55fc224c70bf34a0acc8a76b0d729a96b229b57d Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 6 Mar 2018 12:36:54 +0900 Subject: [PATCH 154/881] Add method to NetworkStatsService for UID stats. Useful for clients such as BatteryStats which currently rely on NetworkStatsFactory. Data at that stage is incomplete as it does not account for tethering, VT data and corresponding 464xlat corrections. Test: runtest frameworks-net, CTS tests pass. Bug: b/72107146 Merged-In: I31c5b9b4a7c6e72910152415894a137f000a5858 Merged-In: I2527d95000c7500c824ede70f87ecb38e21ed323 (cherry picked from aosp 4b3f6f982ef74cc35e914481c94bad4515b0dfbf) Change-Id: Ie80f1bb21124241f3414f9be77aceac9a44ec6d1 --- .../android/net/INetworkStatsService.aidl | 10 +++ core/java/android/net/NetworkStats.java | 64 +++++++++++++---- .../internal/net/NetworkStatsFactory.java | 72 ++++++++++++++----- .../server/net/NetworkStatsService.java | 38 ++++++++-- 4 files changed, 149 insertions(+), 35 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 381cfb61de..8e6f272388 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -41,6 +41,16 @@ interface INetworkStatsService { /** Return data layer snapshot of UID network usage. */ NetworkStats getDataLayerSnapshotForUid(int uid); + + /** Get a detailed snapshot of stats since boot for all UIDs. + * + *

Results will not always be limited to stats on requiredIfaces when specified: stats for + * interfaces stacked on the specified interfaces, or for interfaces on which the specified + * interfaces are stacked on, will also be included. + * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}. + */ + NetworkStats getDetailedUidStats(in String[] requiredIfaces); + /** Return set of any ifaces associated with mobile networks since boot. */ String[] getMobileIfaces(); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 16fb858a58..292bf8e196 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -64,6 +64,9 @@ public class NetworkStats implements Parcelable { /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */ public static final int SET_DBG_VPN_OUT = 1002; + /** Include all interfaces when filtering */ + public static final String[] INTERFACES_ALL = null; + /** {@link #tag} value for total data across all tags. */ // TODO: Rename TAG_NONE to TAG_ALL. public static final int TAG_NONE = 0; @@ -366,23 +369,27 @@ public class NetworkStats implements Parcelable { capacity = newLength; } - iface[size] = entry.iface; - uid[size] = entry.uid; - set[size] = entry.set; - tag[size] = entry.tag; - metered[size] = entry.metered; - roaming[size] = entry.roaming; - defaultNetwork[size] = entry.defaultNetwork; - rxBytes[size] = entry.rxBytes; - rxPackets[size] = entry.rxPackets; - txBytes[size] = entry.txBytes; - txPackets[size] = entry.txPackets; - operations[size] = entry.operations; + setValues(size, entry); size++; return this; } + private void setValues(int i, Entry entry) { + iface[i] = entry.iface; + uid[i] = entry.uid; + set[i] = entry.set; + tag[i] = entry.tag; + metered[i] = entry.metered; + roaming[i] = entry.roaming; + defaultNetwork[i] = entry.defaultNetwork; + rxBytes[i] = entry.rxBytes; + rxPackets[i] = entry.rxPackets; + txBytes[i] = entry.txBytes; + txPackets[i] = entry.txPackets; + operations[i] = entry.operations; + } + /** * Return specific stats entry. */ @@ -831,6 +838,39 @@ public class NetworkStats implements Parcelable { return stats; } + /** + * Only keep entries that match all specified filters. + * + *

This mutates the original structure in place. After this method is called, + * size is the number of matching entries, and capacity is the previous capacity. + * @param limitUid UID to filter for, or {@link #UID_ALL}. + * @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}. + * @param limitTag Tag to filter for, or {@link #TAG_ALL}. + */ + public void filter(int limitUid, String[] limitIfaces, int limitTag) { + if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { + return; + } + + Entry entry = new Entry(); + int nextOutputEntry = 0; + for (int i = 0; i < size; i++) { + entry = getValues(i, entry); + final boolean matches = + (limitUid == UID_ALL || limitUid == entry.uid) + && (limitTag == TAG_ALL || limitTag == entry.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, entry.iface)); + + if (matches) { + setValues(nextOutputEntry, entry); + nextOutputEntry++; + } + } + + size = nextOutputEntry; + } + public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 43abadec0d..0cf5375076 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -22,16 +22,14 @@ import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static com.android.server.NetworkManagementSocketTagger.kernelToTag; +import android.annotation.Nullable; import android.net.NetworkStats; import android.os.StrictMode; import android.os.SystemClock; -import android.util.ArrayMap; -import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; -import com.google.android.collect.Lists; import libcore.io.IoUtils; @@ -41,8 +39,10 @@ import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.net.ProtocolException; -import java.util.ArrayList; -import java.util.Objects; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Creates {@link NetworkStats} instances by parsing various {@code /proc/} @@ -72,18 +72,55 @@ public class NetworkStatsFactory { private boolean mUseBpfStats; - // TODO: to improve testability and avoid global state, do not use a static variable. - @GuardedBy("sStackedIfaces") - private static final ArrayMap sStackedIfaces = new ArrayMap<>(); + // TODO: only do adjustments in NetworkStatsService and remove this. + /** + * (Stacked interface) -> (base interface) association for all connected ifaces since boot. + * + * Because counters must never roll backwards, once a given interface is stacked on top of an + * underlying interface, the stacked interface can never be stacked on top of + * another interface. */ + private static final ConcurrentHashMap sStackedIfaces + = new ConcurrentHashMap<>(); public static void noteStackedIface(String stackedIface, String baseIface) { - synchronized (sStackedIfaces) { - if (baseIface != null) { - sStackedIfaces.put(stackedIface, baseIface); - } else { - sStackedIfaces.remove(stackedIface); + if (stackedIface != null && baseIface != null) { + sStackedIfaces.put(stackedIface, baseIface); + } + } + + /** + * Get a set of interfaces containing specified ifaces and stacked interfaces. + * + *

The added stacked interfaces are ifaces stacked on top of the specified ones, or ifaces + * on which the specified ones are stacked. Stacked interfaces are those noted with + * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method + * is called are guaranteed to be included. + */ + public static String[] augmentWithStackedInterfacesLocked(@Nullable String[] requiredIfaces) { + if (requiredIfaces == NetworkStats.INTERFACES_ALL) { + return null; + } + + HashSet relatedIfaces = new HashSet<>(Arrays.asList(requiredIfaces)); + // ConcurrentHashMap's EntrySet iterators are "guaranteed to traverse + // elements as they existed upon construction exactly once, and may + // (but are not guaranteed to) reflect any modifications subsequent to construction". + // This is enough here. + for (Map.Entry entry : sStackedIfaces.entrySet()) { + if (relatedIfaces.contains(entry.getKey())) { + relatedIfaces.add(entry.getValue()); + } else if (relatedIfaces.contains(entry.getValue())) { + relatedIfaces.add(entry.getKey()); } } + + String[] outArray = new String[relatedIfaces.size()]; + return relatedIfaces.toArray(outArray); + } + + @VisibleForTesting + public static void clearStackedIfaces() { + sStackedIfaces.clear(); } public NetworkStatsFactory() { @@ -252,12 +289,9 @@ public class NetworkStatsFactory { NetworkStats lastStats) throws IOException { final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); - final ArrayMap stackedIfaces; - synchronized (sStackedIfaces) { - stackedIfaces = new ArrayMap<>(sStackedIfaces); - } // Total 464xlat traffic to subtract from uid 0 on all base interfaces. - final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); + // sStackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. + final NetworkStats adjustments = new NetworkStats(0, sStackedIfaces.size()); NetworkStats.Entry entry = null; // For recycling @@ -271,7 +305,7 @@ public class NetworkStatsFactory { if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { continue; } - final String baseIface = stackedIfaces.get(entry.iface); + final String baseIface = sStackedIfaces.get(entry.iface); if (baseIface == null) { continue; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 93c04fe206..57828ca5dc 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,6 +27,7 @@ import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.INTERFACES_ALL; import static android.net.NetworkStats.METERED_ALL; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.SET_ALL; @@ -34,6 +35,7 @@ import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; import static android.net.NetworkStats.STATS_PER_IFACE; import static android.net.NetworkStats.STATS_PER_UID; +import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; @@ -127,6 +129,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.NetworkStatsFactory; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; @@ -145,6 +148,7 @@ import java.time.ZoneOffset; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Map; /** * Collect and persist detailed network statistics, and provide this data to @@ -739,7 +743,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final long token = Binder.clearCallingIdentity(); final NetworkStats networkLayer; try { - networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid); + networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid, + NetworkStats.INTERFACES_ALL); } finally { Binder.restoreCallingIdentity(token); } @@ -760,6 +765,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return dataLayer; } + @Override + public NetworkStats getDetailedUidStats(String[] requiredIfaces) { + try { + final String[] ifacesToQuery = + NetworkStatsFactory.augmentWithStackedInterfacesLocked(requiredIfaces); + return getNetworkStatsUidDetail(ifacesToQuery); + } catch (RemoteException e) { + Log.wtf(TAG, "Error compiling UID stats", e); + return new NetworkStats(0L, 0); + } + } + @Override public String[] getMobileIfaces() { return mMobileIfaces; @@ -1119,6 +1136,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (isMobile) { mobileIfaces.add(stackedIface); } + + NetworkStatsFactory.noteStackedIface(stackedIface, baseIface); } } } @@ -1141,7 +1160,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void recordSnapshotLocked(long currentTime) throws RemoteException { // snapshot and record current counters; read UID stats first to // avoid over counting dev stats. - final NetworkStats uidSnapshot = getNetworkStatsUidDetail(); + final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL); final NetworkStats xtSnapshot = getNetworkStatsXt(); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); @@ -1501,12 +1520,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Return snapshot of current UID statistics, including any * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations} * values. + * + * @param ifaces A list of interfaces the stats should be restricted to, or + * {@link NetworkStats#INTERFACES_ALL}. */ - private NetworkStats getNetworkStatsUidDetail() throws RemoteException { - final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); + private NetworkStats getNetworkStatsUidDetail(String[] ifaces) + throws RemoteException { + + final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL, + ifaces); // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); + tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1515,10 +1541,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold video calling data usage stats into uid snapshot final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { + vtStats.filter(UID_ALL, ifaces, TAG_ALL); uidSnapshot.combineAllValues(vtStats); } + uidSnapshot.combineAllValues(mUidOperations); + // TODO: apply tethering & VC 464xlat adjustments here + return uidSnapshot; } From 76d2f53927826ac4a159479e32fc1944d6f39bed Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 2 Apr 2018 16:48:31 +0900 Subject: [PATCH 155/881] Allow applications to query for foreground/background data usage. Currently the NetworkStatsManager APIs allow applications to query for their own data usage by UID and tag, but do not allow applications to query by foreground/background state. This is causing popular apps to resort to parsing xt_qtaguid stats files directly. Because this is no longer allowed for apps targeting P and above, provide replacement functionality. This API allows apps to query for data usage for a given state, but not to receive data usage broken down by state. This is consistent with how the current UID and tag APIs work. It is also not an undue burden on apps: there are currently only two states of interest (FOREGROUND and everything else), and even if we add states in the future, unmodified apps can still obtain total traffic using STATE_ALL. Bug: 72977484 Test: New CTS test added in other change in this topic. Change-Id: Ic8c9194569ffd599b49e4a8197c5c2ea0ec3f7f7 --- core/java/android/app/usage/NetworkStats.java | 35 ++++++++++------- .../app/usage/NetworkStatsManager.java | 38 ++++++++++++------- 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index e315e9115f..7252f028d7 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -67,6 +67,11 @@ public final class NetworkStats implements AutoCloseable { */ private int mTag = android.net.NetworkStats.TAG_NONE; + /** + * State in case it was not specified in the query. + */ + private int mState = Bucket.STATE_ALL; + /** * The session while the query requires it, null if all the stats have been collected or close() * has been called. @@ -267,6 +272,15 @@ public final class NetworkStats implements AutoCloseable { private long mTxBytes; private long mTxPackets; + private static int convertSet(@State int state) { + switch (state) { + case STATE_ALL: return android.net.NetworkStats.SET_ALL; + case STATE_DEFAULT: return android.net.NetworkStats.SET_DEFAULT; + case STATE_FOREGROUND: return android.net.NetworkStats.SET_FOREGROUND; + } + return 0; + } + private static @State int convertState(int networkStatsSet) { switch (networkStatsSet) { case android.net.NetworkStats.SET_ALL : return STATE_ALL; @@ -527,20 +541,13 @@ public final class NetworkStats implements AutoCloseable { /** * Collects history results for uid and resets history enumeration index. */ - void startHistoryEnumeration(int uid) { - startHistoryEnumeration(uid, android.net.NetworkStats.TAG_NONE); - } - - /** - * Collects history results for uid and resets history enumeration index. - */ - void startHistoryEnumeration(int uid, int tag) { + void startHistoryEnumeration(int uid, int tag, int state) { mHistory = null; try { mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid, - android.net.NetworkStats.SET_ALL, tag, - NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp); - setSingleUidTag(uid, tag); + Bucket.convertSet(state), tag, NetworkStatsHistory.FIELD_ALL, + mStartTimeStamp, mEndTimeStamp); + setSingleUidTagState(uid, tag, state); } catch (RemoteException e) { Log.w(TAG, e); // Leaving mHistory null @@ -636,6 +643,7 @@ public final class NetworkStats implements AutoCloseable { fillBucketFromSummaryEntry(bucket); return bucket; } + /** * Getting the next item in a history enumeration. * @param bucketOut Next item will be set here. @@ -648,7 +656,7 @@ public final class NetworkStats implements AutoCloseable { mRecycledHistoryEntry); bucketOut.mUid = Bucket.convertUid(getUid()); bucketOut.mTag = Bucket.convertTag(mTag); - bucketOut.mState = Bucket.STATE_ALL; + bucketOut.mState = mState; bucketOut.mDefaultNetwork = Bucket.DEFAULT_NETWORK_ALL; bucketOut.mMetered = Bucket.METERED_ALL; bucketOut.mRoaming = Bucket.ROAMING_ALL; @@ -691,9 +699,10 @@ public final class NetworkStats implements AutoCloseable { return mUidOrUidIndex; } - private void setSingleUidTag(int uid, int tag) { + private void setSingleUidTagState(int uid, int tag, int state) { mUidOrUidIndex = uid; mTag = tag; + mState = state; } private void stepUid() { diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 2357637b72..b2fe958691 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -263,20 +263,31 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid. * - * #see queryDetailsForUidTag(int, String, long, long, int, int) + * #see queryDetailsForUidTagState(int, String, long, long, int, int, int) */ public NetworkStats queryDetailsForUid(int networkType, String subscriberId, - long startTime, long endTime, int uid) throws SecurityException, RemoteException { - return queryDetailsForUidTag(networkType, subscriberId, startTime, endTime, uid, - NetworkStats.Bucket.TAG_NONE); + long startTime, long endTime, int uid) throws SecurityException { + return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, + NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL); } /** - * Query network usage statistics details for a given uid and tag. Only usable for uids - * belonging to calling user. Result is aggregated over state but not aggregated over time. - * This means buckets' start and end timestamps are going to be between 'startTime' and - * 'endTime' parameters. State is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid the - * same as the 'uid' parameter and tag the same as 'tag' parameter. + * Query network usage statistics details for a given uid and tag. + * + * #see queryDetailsForUidTagState(int, String, long, long, int, int, int) + */ + public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId, + long startTime, long endTime, int uid, int tag) throws SecurityException { + return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, + tag, NetworkStats.Bucket.STATE_ALL); + } + + /** + * Query network usage statistics details for a given uid, tag, and state. Only usable for uids + * belonging to calling user. Result is not aggregated over time. This means buckets' start and + * end timestamps are going to be between 'startTime' and 'endTime' parameters. The uid is going + * to be the same as the 'uid' parameter, the tag the same as the 'tag' parameter, and the state + * the same as the 'state' parameter. * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. @@ -297,17 +308,18 @@ public class NetworkStatsManager { * @return Statistics object or null if an error happened during statistics collection. * @throws SecurityException if permissions are insufficient to read network statistics. */ - public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId, - long startTime, long endTime, int uid, int tag) throws SecurityException { + public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId, + long startTime, long endTime, int uid, int tag, int state) throws SecurityException { NetworkTemplate template; template = createTemplate(networkType, subscriberId); NetworkStats result; try { result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); - result.startHistoryEnumeration(uid, tag); + result.startHistoryEnumeration(uid, tag, state); } catch (RemoteException e) { - Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e); + Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag + + " state=" + state, e); return null; } From f2822d3a239278a8a77849d3d62ce35551160257 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 27 Feb 2018 16:47:22 +0900 Subject: [PATCH 156/881] Fix network usage stats on 464xlat tethered. Usage stats corrections for 464xlat in NetworkStatsFactory are not applied to tethered traffic. Add adjustments in NetworkStatsService. After migrating external callers off NetworkStatsFactory, we will be able to only apply adjustments in NetworkStatsService and remove stacked interface tracking from NetworkStatsFactory. Bug: 72107146 Fixes: 72107146 Test: runtest frameworks-net & manual - checked corrected network usage Merged-In: Ieb25c41c651499fdd01225ae5ac21d95e3d823f5 Merged-In: I016722f3a0ae2ae0a1d48bfacc4fe07ee3578ef7 (cherry-pick of aosp I5ce450e616b4fddf21f2a491fe5d0c9e9f969bda) Change-Id: Id41cf22a0f9a63cb1832e9375bfb045861f08e52 --- core/java/android/net/NetworkStats.java | 75 +++++++++++++++++++ .../internal/net/NetworkStatsFactory.java | 60 ++++----------- .../server/net/NetworkStatsService.java | 8 +- 3 files changed, 92 insertions(+), 51 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 292bf8e196..f0dd2629f9 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -31,6 +31,7 @@ import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; import java.util.HashSet; +import java.util.Map; import java.util.Objects; /** @@ -97,6 +98,11 @@ public class NetworkStats implements Parcelable { /** Denotes a request for stats at the interface and UID level. */ public static final int STATS_PER_UID = 1; + private static final String CLATD_INTERFACE_PREFIX = "v4-"; + // Delta between IPv4 header (20b) and IPv6 header (40b). + // Used for correct stats accounting on clatd interfaces. + private static final int IPV4V6_HEADER_DELTA = 20; + // TODO: move fields to "mVariable" notation /** @@ -758,6 +764,75 @@ public class NetworkStats implements Parcelable { return result; } + /** + * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * + *

This mutates both base and stacked traffic stats, to account respectively for + * double-counted traffic and IPv4/IPv6 header size difference. + * + *

For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 + * packet on the stacked interface, and once as translated to an IPv6 packet on the + * base interface. For correct stats accounting on the base interface, every 464xlat + * packet needs to be subtracted from the root UID on the base interface both for tx + * and rx traffic (http://b/12249687, http:/b/33681750). + * + *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only + * {@code ConcurrentHashMap} + * @param baseTraffic Traffic on the base interfaces. Will be mutated. + * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. + * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + */ + public static void apply464xlatAdjustments(NetworkStats baseTraffic, + NetworkStats stackedTraffic, Map stackedIfaces) { + // Total 464xlat traffic to subtract from uid 0 on all base interfaces. + // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. + final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); + + // For recycling + Entry entry = null; + Entry adjust = new NetworkStats.Entry(IFACE_ALL, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); + + for (int i = 0; i < stackedTraffic.size; i++) { + entry = stackedTraffic.getValues(i, entry); + if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { + continue; + } + final String baseIface = stackedIfaces.get(entry.iface); + if (baseIface == null) { + continue; + } + // Subtract any 464lat traffic seen for the root UID on the current base interface. + adjust.iface = baseIface; + adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); + adjust.rxPackets = -entry.rxPackets; + adjust.txPackets = -entry.txPackets; + adjustments.combineValues(adjust); + + // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent + // on the stacked interface with prefix "v4-" and drops the IPv6 header size after + // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes + // difference for all packets (http://b/12249687, http:/b/33681750). + entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA; + entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA; + stackedTraffic.setValues(i, entry); + } + + baseTraffic.combineAllValues(adjustments); + } + + /** + * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * + *

This mutates the object this method is called on. Equivalent to calling + * {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as + * base and stacked traffic. + * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + */ + public void apply464xlatAdjustments(Map stackedIfaces) { + apply464xlatAdjustments(this, this, stackedIfaces); + } + /** * Return total statistics grouped by {@link #iface}; doesn't mutate the * original structure. diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 0cf5375076..98afebc51b 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -56,11 +56,6 @@ public class NetworkStatsFactory { private static final boolean USE_NATIVE_PARSING = true; private static final boolean SANITY_CHECK_NATIVE = false; - private static final String CLATD_INTERFACE_PREFIX = "v4-"; - // Delta between IPv4 header (20b) and IPv6 header (40b). - // Used for correct stats accounting on clatd interfaces. - private static final int IPV4V6_HEADER_DELTA = 20; - /** Path to {@code /proc/net/dev}. */ private final File mStatsIfaceDev; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ @@ -96,7 +91,7 @@ public class NetworkStatsFactory { * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method * is called are guaranteed to be included. */ - public static String[] augmentWithStackedInterfacesLocked(@Nullable String[] requiredIfaces) { + public static String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { if (requiredIfaces == NetworkStats.INTERFACES_ALL) { return null; } @@ -118,6 +113,15 @@ public class NetworkStatsFactory { return relatedIfaces.toArray(outArray); } + /** + * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. + * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map) + */ + public static void apply464xlatAdjustments(NetworkStats baseTraffic, + NetworkStats stackedTraffic) { + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces); + } + @VisibleForTesting public static void clearStackedIfaces() { sStackedIfaces.clear(); @@ -289,48 +293,10 @@ public class NetworkStatsFactory { NetworkStats lastStats) throws IOException { final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); - // Total 464xlat traffic to subtract from uid 0 on all base interfaces. - // sStackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. - final NetworkStats adjustments = new NetworkStats(0, sStackedIfaces.size()); - NetworkStats.Entry entry = null; // For recycling - - // For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 - // packet on the stacked interface, and once as translated to an IPv6 packet on the - // base interface. For correct stats accounting on the base interface, every 464xlat - // packet needs to be subtracted from the root UID on the base interface both for tx - // and rx traffic (http://b/12249687, http:/b/33681750). - for (int i = 0; i < stats.size(); i++) { - entry = stats.getValues(i, entry); - if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { - continue; - } - final String baseIface = sStackedIfaces.get(entry.iface); - if (baseIface == null) { - continue; - } - - NetworkStats.Entry adjust = - new NetworkStats.Entry(baseIface, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); - // Subtract any 464lat traffic seen for the root UID on the current base interface. - adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); - adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets -= entry.rxPackets; - adjust.txPackets -= entry.txPackets; - adjustments.combineValues(adjust); - - // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent - // on the stacked interface with prefix "v4-" and drops the IPv6 header size after - // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes - // difference for all packets (http://b/12249687, http:/b/33681750). - entry.rxBytes = entry.rxPackets * IPV4V6_HEADER_DELTA; - entry.txBytes = entry.txPackets * IPV4V6_HEADER_DELTA; - entry.rxPackets = 0; - entry.txPackets = 0; - stats.combineValues(entry); - } - - stats.combineAllValues(adjustments); + // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. + // TODO: remove this and only apply adjustments in NetworkStatsService. + stats.apply464xlatAdjustments(sStackedIfaces); return stats; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 57828ca5dc..4e848f8f36 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -148,7 +148,6 @@ import java.time.ZoneOffset; import java.util.Arrays; import java.util.HashSet; import java.util.List; -import java.util.Map; /** * Collect and persist detailed network statistics, and provide this data to @@ -769,7 +768,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { final String[] ifacesToQuery = - NetworkStatsFactory.augmentWithStackedInterfacesLocked(requiredIfaces); + NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); @@ -1527,12 +1526,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats getNetworkStatsUidDetail(String[] ifaces) throws RemoteException { + // TODO: remove 464xlat adjustments from NetworkStatsFactory and apply all at once here. final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL, ifaces); // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1542,13 +1543,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats); uidSnapshot.combineAllValues(vtStats); } uidSnapshot.combineAllValues(mUidOperations); - // TODO: apply tethering & VC 464xlat adjustments here - return uidSnapshot; } From a10a7f99c4b3de81bbbd246eeecc95d77730aced Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 15 Mar 2018 18:06:06 -0700 Subject: [PATCH 157/881] Add AppOps Checks for MANAGE_IPSEC_TUNNELS Adds support for a new AppOp to permit services to use IpSec tunnel mode. The IpSecService now needs a context so change the service mode to a cached service rather than a static service. Bug: 66955045 Test: runtest frameworks-net Change-Id: I17a4a286225b432c3e15ea1587d946189931b4f4 --- core/java/android/net/IIpSecService.aidl | 20 ++++--- core/java/android/net/IpSecManager.java | 25 +++++--- core/java/android/net/IpSecTransform.java | 3 +- .../java/com/android/server/IpSecService.java | 59 ++++++++++++++----- 4 files changed, 76 insertions(+), 31 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 3a3ddcc483..d6774d47b4 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -45,25 +45,31 @@ interface IIpSecService in String localAddr, in String remoteAddr, in Network underlyingNetwork, - in IBinder binder); + in IBinder binder, + in String callingPackage); void addAddressToTunnelInterface( int tunnelResourceId, - in LinkAddress localAddr); + in LinkAddress localAddr, + in String callingPackage); void removeAddressFromTunnelInterface( int tunnelResourceId, - in LinkAddress localAddr); + in LinkAddress localAddr, + in String callingPackage); - void deleteTunnelInterface(int resourceId); + void deleteTunnelInterface(int resourceId, in String callingPackage); - IpSecTransformResponse createTransform(in IpSecConfig c, in IBinder binder); + IpSecTransformResponse createTransform( + in IpSecConfig c, in IBinder binder, in String callingPackage); void deleteTransform(int transformId); - void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); + void applyTransportModeTransform( + in ParcelFileDescriptor socket, int direction, int transformId); - void applyTunnelModeTransform(int tunnelResourceId, int direction, int transformResourceId); + void applyTunnelModeTransform( + int tunnelResourceId, int direction, int transformResourceId, in String callingPackage); void removeTransportModeTransforms(in ParcelFileDescriptor socket); } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 1525508326..e0654fde6e 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -140,6 +140,7 @@ public final class IpSecManager { } } + private final Context mContext; private final IIpSecService mService; /** @@ -661,6 +662,7 @@ public final class IpSecManager { */ @SystemApi public static final class IpSecTunnelInterface implements AutoCloseable { + private final String mOpPackageName; private final IIpSecService mService; private final InetAddress mRemoteAddress; private final InetAddress mLocalAddress; @@ -688,7 +690,8 @@ public final class IpSecManager { @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull LinkAddress address) throws IOException { try { - mService.addAddressToTunnelInterface(mResourceId, address); + mService.addAddressToTunnelInterface( + mResourceId, address, mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -706,16 +709,18 @@ public final class IpSecManager { @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull LinkAddress address) throws IOException { try { - mService.removeAddressFromTunnelInterface(mResourceId, address); + mService.removeAddressFromTunnelInterface( + mResourceId, address, mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - private IpSecTunnelInterface(@NonNull IIpSecService service, + private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { + mOpPackageName = ctx.getOpPackageName(); mService = service; mLocalAddress = localAddress; mRemoteAddress = remoteAddress; @@ -727,7 +732,8 @@ public final class IpSecManager { localAddress.getHostAddress(), remoteAddress.getHostAddress(), underlyingNetwork, - new Binder()); + new Binder(), + mOpPackageName); switch (result.status) { case Status.OK: break; @@ -756,7 +762,7 @@ public final class IpSecManager { @Override public void close() { try { - mService.deleteTunnelInterface(mResourceId); + mService.deleteTunnelInterface(mResourceId, mOpPackageName); mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -801,7 +807,8 @@ public final class IpSecManager { public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { - return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork); + return new IpSecTunnelInterface( + mContext, mService, localAddress, remoteAddress, underlyingNetwork); } /** @@ -827,7 +834,8 @@ public final class IpSecManager { @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { try { mService.applyTunnelModeTransform( - tunnel.getResourceId(), direction, transform.getResourceId()); + tunnel.getResourceId(), direction, + transform.getResourceId(), mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -839,7 +847,8 @@ public final class IpSecManager { * @param context the application context for this manager * @hide */ - public IpSecManager(IIpSecService service) { + public IpSecManager(Context ctx, IIpSecService service) { + mContext = ctx; mService = checkNotNull(service, "missing service"); } } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 099fe02fdd..fb5f46c117 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -130,7 +130,8 @@ public final class IpSecTransform implements AutoCloseable { synchronized (this) { try { IIpSecService svc = getIpSecService(); - IpSecTransformResponse result = svc.createTransform(mConfig, new Binder()); + IpSecTransformResponse result = svc.createTransform( + mConfig, new Binder(), mContext.getOpPackageName()); int status = result.status; checkResultStatus(status); mResourceId = result.resourceId; diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index bde6bd8db6..cd90e3f9b0 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -24,6 +24,8 @@ import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; +import android.annotation.NonNull; +import android.app.AppOpsManager; import android.content.Context; import android.net.ConnectivityManager; import android.net.IIpSecService; @@ -42,6 +44,7 @@ import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; +import android.os.DeadSystemException; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -974,6 +977,13 @@ public class IpSecService extends IIpSecService.Stub { return service; } + @NonNull + private AppOpsManager getAppOpsManager() { + AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + if(appOps == null) throw new RuntimeException("System Server couldn't get AppOps"); + return appOps; + } + /** @hide */ @VisibleForTesting public IpSecService(Context context, IpSecServiceConfiguration config) { @@ -1240,7 +1250,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized IpSecTunnelInterfaceResponse createTunnelInterface( - String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder) { + String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, + String callingPackage) { + enforceTunnelPermissions(callingPackage); checkNotNull(binder, "Null Binder passed to createTunnelInterface"); checkNotNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); @@ -1320,8 +1332,8 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void addAddressToTunnelInterface( - int tunnelResourceId, LinkAddress localAddr) { - enforceNetworkStackPermission(); + int tunnelResourceId, LinkAddress localAddr, String callingPackage) { + enforceTunnelPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1352,10 +1364,10 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void removeAddressFromTunnelInterface( - int tunnelResourceId, LinkAddress localAddr) { - enforceNetworkStackPermission(); - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int tunnelResourceId, LinkAddress localAddr, String callingPackage) { + enforceTunnelPermissions(callingPackage); + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw // IllegalArgumentException TunnelInterfaceRecord tunnelInterfaceInfo = @@ -1383,7 +1395,9 @@ public class IpSecService extends IIpSecService.Stub { * server */ @Override - public synchronized void deleteTunnelInterface(int resourceId) throws RemoteException { + public synchronized void deleteTunnelInterface( + int resourceId, String callingPackage) throws RemoteException { + enforceTunnelPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); releaseResource(userRecord.mTunnelInterfaceRecords, resourceId); } @@ -1469,7 +1483,6 @@ public class IpSecService extends IIpSecService.Stub { case IpSecTransform.MODE_TRANSPORT: break; case IpSecTransform.MODE_TUNNEL: - enforceNetworkStackPermission(); break; default: throw new IllegalArgumentException( @@ -1477,9 +1490,20 @@ public class IpSecService extends IIpSecService.Stub { } } - private void enforceNetworkStackPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK, - "IpSecService"); + private void enforceTunnelPermissions(String callingPackage) { + checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); + switch (getAppOpsManager().noteOp( + AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, + Binder.getCallingUid(), callingPackage)) { + case AppOpsManager.MODE_DEFAULT: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); + break; + case AppOpsManager.MODE_ALLOWED: + return; + default: + throw new SecurityException("Request to ignore AppOps for non-legacy API"); + } } private void createOrUpdateTransform( @@ -1535,8 +1559,12 @@ public class IpSecService extends IIpSecService.Stub { * result in all of those sockets becoming unable to send or receive data. */ @Override - public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder) - throws RemoteException { + public synchronized IpSecTransformResponse createTransform( + IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { + checkNotNull(c); + if (c.getMode() == IpSecTransform.MODE_TUNNEL) { + enforceTunnelPermissions(callingPackage); + } checkIpSecConfig(c); checkNotNull(binder, "Null Binder passed to createTransform"); final int resourceId = mNextResourceId++; @@ -1657,8 +1685,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void applyTunnelModeTransform( - int tunnelResourceId, int direction, int transformResourceId) throws RemoteException { - enforceNetworkStackPermission(); + int tunnelResourceId, int direction, + int transformResourceId, String callingPackage) throws RemoteException { + enforceTunnelPermissions(callingPackage); checkDirection(direction); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); From fbbce98bc363363edac120b94a780a9fa1331467 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 2 Apr 2018 18:12:34 -0700 Subject: [PATCH 158/881] Force creation of Socket upon Transform application This change forces Socket and DatagramSocket to populate the SocketImpl, ensuring that the socket file descriptor can be retrieved when applying Transport mode Transforms This is done by calling getSoLinger(), triggering a getImpl(), which triggers setImpl() if needed. Bug: 77491294 Test: Added tests in IpSecManagerTest, ran on walleye Change-Id: I40da08b031357710eb794e0f866aec5660c79594 --- core/java/android/net/IpSecManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 719b81c7df..cc227713cb 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -336,6 +336,9 @@ public final class IpSecManager { */ public void applyTransportModeTransform(@NonNull Socket socket, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { + // Ensure creation of FD. See b/77548890 for more details. + socket.getSoLinger(); + applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -440,6 +443,9 @@ public final class IpSecManager { * @throws IOException indicating that the transform could not be removed from the socket */ public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException { + // Ensure creation of FD. See b/77548890 for more details. + socket.getSoLinger(); + removeTransportModeTransforms(socket.getFileDescriptor$()); } From ad4bca35e7dbce512176dfcd45ccb671b9d3a83b Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 2 Apr 2018 18:12:34 -0700 Subject: [PATCH 159/881] Force creation of Socket upon Transform application This change forces Socket and DatagramSocket to populate the SocketImpl, ensuring that the socket file descriptor can be retrieved when applying Transport mode Transforms This is done by calling getSoLinger(), triggering a getImpl(), which triggers setImpl() if needed. Bug: 77491294 Test: Added tests in IpSecManagerTest, ran on walleye Merged-In: I40da08b031357710eb794e0f866aec5660c79594 Change-Id: I40da08b031357710eb794e0f866aec5660c79594 (cherry picked from commit fbbce98bc363363edac120b94a780a9fa1331467) --- core/java/android/net/IpSecManager.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index e0654fde6e..0d04fe5a91 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -337,6 +337,9 @@ public final class IpSecManager { */ public void applyTransportModeTransform(@NonNull Socket socket, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { + // Ensure creation of FD. See b/77548890 for more details. + socket.getSoLinger(); + applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform); } @@ -441,6 +444,9 @@ public final class IpSecManager { * @throws IOException indicating that the transform could not be removed from the socket */ public void removeTransportModeTransforms(@NonNull Socket socket) throws IOException { + // Ensure creation of FD. See b/77548890 for more details. + socket.getSoLinger(); + removeTransportModeTransforms(socket.getFileDescriptor$()); } From a0c566ec9fdf212558f3ab3a903148124e6e49bd Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 30 Mar 2018 16:25:11 -0600 Subject: [PATCH 160/881] API council requested tweaks to SubscriptionPlan. Return new shiny Range<> object instead of Pair<>. Tell developers what permission to check on refresh broadcast. Describe what exceptions might be thrown, and that an empty list is okay. Allow creation of plans with richer Period object, instead of forcing them into rigid week or day options. Protect SubscriptionPlan broadcast. Test: atest android.util.RecurrenceRuleTest Test: atest com.android.server.NetworkPolicyManagerServiceTest Bug: 74945820 Change-Id: I7e555798e0cfaa214ca93d9df627c6443fc5d986 --- .../com/android/server/net/NetworkStatsCollection.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 2ef754e2ba..ab525237db 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -47,7 +47,7 @@ import android.util.ArrayMap; import android.util.AtomicFile; import android.util.IntArray; import android.util.MathUtils; -import android.util.Pair; +import android.util.Range; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -266,11 +266,11 @@ public class NetworkStatsCollection implements FileRotator.Reader { long collectEnd = end; if (augmentEnd != SubscriptionPlan.TIME_UNKNOWN) { - final Iterator> it = augmentPlan.cycleIterator(); + final Iterator> it = augmentPlan.cycleIterator(); while (it.hasNext()) { - final Pair cycle = it.next(); - final long cycleStart = cycle.first.toInstant().toEpochMilli(); - final long cycleEnd = cycle.second.toInstant().toEpochMilli(); + final Range cycle = it.next(); + final long cycleStart = cycle.getLower().toInstant().toEpochMilli(); + final long cycleEnd = cycle.getUpper().toInstant().toEpochMilli(); if (cycleStart <= augmentEnd && augmentEnd < cycleEnd) { augmentStart = cycleStart; collectStart = Long.min(collectStart, augmentStart); From e84200fc5b1a7a469822fee2cceb2d469e8aeea2 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 3 Apr 2018 20:30:54 -0700 Subject: [PATCH 161/881] Update IpSecManager to use InetAddress and prefixLen LinkAddress constructors are currently @hide; this change updates IpSecManager to use InetAddress and prefixLen, and then construct a LinkAddress internally. LinkAddress is used over the binder interface to IpSecService to ensure validity. Bug: 77528639 Test: CTS, Java unit tests ran on walleye Change-Id: I19e124adef6d9f4992d8293db3190bcf74c95848 --- core/java/android/net/IpSecManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index e0654fde6e..ade6374675 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -684,14 +684,15 @@ public final class IpSecManager { * tunneled traffic. * * @param address the local address for traffic inside the tunnel + * @param prefixLen length of the InetAddress prefix * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) - public void addAddress(@NonNull LinkAddress address) throws IOException { + public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { mService.addAddressToTunnelInterface( - mResourceId, address, mOpPackageName); + mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -703,14 +704,15 @@ public final class IpSecManager { *

Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed + * @param prefixLen length of the InetAddress prefix * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) - public void removeAddress(@NonNull LinkAddress address) throws IOException { + public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { mService.removeAddressFromTunnelInterface( - mResourceId, address, mOpPackageName); + mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } From e91692a3e38d33a8b33c14d437355e55f6330203 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 6 Apr 2018 22:56:52 +0900 Subject: [PATCH 162/881] Add @param tag for state in queryDetailsForUidTagState. Change-Id: I22de424ccb2b30b2a56edd17dc982565b8aa7d4a Fix: 77518425 Test: make doc-comment-check-docs --- core/java/android/app/usage/NetworkStatsManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index b2fe958691..85f4efc3f7 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -305,6 +305,8 @@ public class NetworkStatsManager { * {@link java.lang.System#currentTimeMillis}. * @param uid UID of app * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags. + * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate + * traffic from all states. * @return Statistics object or null if an error happened during statistics collection. * @throws SecurityException if permissions are insufficient to read network statistics. */ From 63f789c5e48a34be533d7495208ceb088b048989 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 4 Apr 2018 14:51:26 +0900 Subject: [PATCH 163/881] Do not register callback for < MIN_THRESHOLD_BYTES This also avoids returning a nonzero multipath preference if remaining data is low but nonzero. Bug: b/72877610 Change-Id: I2459ded06de77d284ae1fe81a60d9e1df56b0c26 Fixes: b/72877610 Test: Tests in go/ag/3842960 pass --- core/java/android/app/usage/NetworkStatsManager.java | 10 ++++++++++ .../com/android/server/net/NetworkStatsObservers.java | 4 +--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index b2fe958691..34f3a8da95 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -35,6 +35,7 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; +import android.util.DataUnit; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -95,6 +96,15 @@ public class NetworkStatsManager { /** @hide */ public static final int CALLBACK_RELEASED = 1; + /** + * Minimum data usage threshold for registering usage callbacks. + * + * Requests registered with a threshold lower than this will only be triggered once this minimum + * is reached. + * @hide + */ + public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2); + private final Context mContext; private final INetworkStatsService mService; diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java index 741c2062bd..d8408730dd 100644 --- a/services/core/java/com/android/server/net/NetworkStatsObservers.java +++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java @@ -16,7 +16,7 @@ package com.android.server.net; -import static android.net.TrafficStats.MB_IN_BYTES; +import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES; import static com.android.internal.util.Preconditions.checkArgument; @@ -52,8 +52,6 @@ class NetworkStatsObservers { private static final String TAG = "NetworkStatsObservers"; private static final boolean LOGV = false; - private static final long MIN_THRESHOLD_BYTES = 2 * MB_IN_BYTES; - private static final int MSG_REGISTER = 1; private static final int MSG_UNREGISTER = 2; private static final int MSG_UPDATE_STATS = 3; From ba804c21251f5da3f4551f22e95ae14d6d55bd94 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Mon, 9 Apr 2018 21:24:35 -0700 Subject: [PATCH 164/881] [DO NOT MERGE] - Hide Tunnel Mode IpSec API Hide the tunnel mode of the IpSec API because there is a disincentive to launch it without a supported customer use case. That use case, IWLAN is having its APIs hidden, so we should hide these as well to avoid constraining future implementation. Also, due to issues with the lifetime of the NATT management object, this API needs to be hidden until such time as the lifetime of the Keepalive can be handled independently of the lifetime of a Transform. Bug: 72523623 Test: compilation (api removal) Change-Id: I076030bdbab1cd7d69f6a034577d529970b050dc --- core/java/android/net/IpSecManager.java | 6 ------ core/java/android/net/IpSecTransform.java | 5 ----- 2 files changed, 11 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 87323755a9..a61ea50d6f 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -20,7 +20,6 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; -import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; @@ -666,7 +665,6 @@ public final class IpSecManager { * to create Network objects which are accessible to the Android system. * @hide */ - @SystemApi public static final class IpSecTunnelInterface implements AutoCloseable { private final String mOpPackageName; private final IIpSecService mService; @@ -693,7 +691,6 @@ public final class IpSecManager { * @param prefixLen length of the InetAddress prefix * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { @@ -713,7 +710,6 @@ public final class IpSecManager { * @param prefixLen length of the InetAddress prefix * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { @@ -809,7 +805,6 @@ public final class IpSecManager { * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open * @hide */ - @SystemApi @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @@ -836,7 +831,6 @@ public final class IpSecManager { * layer failure. * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index fb5f46c117..62f7996564 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -22,7 +22,6 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; -import android.annotation.SystemApi; import android.content.Context; import android.os.Binder; import android.os.Handler; @@ -250,7 +249,6 @@ public final class IpSecTransform implements AutoCloseable { * * @hide */ - @SystemApi public static class NattKeepaliveCallback { /** The specified {@code Network} is not connected. */ public static final int ERROR_INVALID_NETWORK = 1; @@ -281,7 +279,6 @@ public final class IpSecTransform implements AutoCloseable { * * @hide */ - @SystemApi @RequiresPermission(anyOf = { android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD @@ -324,7 +321,6 @@ public final class IpSecTransform implements AutoCloseable { * * @hide */ - @SystemApi @RequiresPermission(anyOf = { android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD @@ -477,7 +473,6 @@ public final class IpSecTransform implements AutoCloseable { * @throws IOException indicating other errors * @hide */ - @SystemApi @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTransform buildTunnelModeTransform( From 9ad30adb820301b3fb1ed002d3d62065423a72f5 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 2 Apr 2018 19:29:26 +0900 Subject: [PATCH 165/881] Address API comments on NetworkStats#getDefaultNetwork. Bug: 76449091 Test: android.app.usage.cts.NetworkUsageStatsTest passes Change-Id: I7f21e0bd7bc4b726058fc2e25542ff2c3173fabe --- core/java/android/app/usage/NetworkStats.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 7252f028d7..216a4a0987 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -237,20 +237,26 @@ public final class NetworkStats implements AutoCloseable { DEFAULT_NETWORK_YES }) @Retention(RetentionPolicy.SOURCE) - public @interface DefaultNetwork {} + public @interface DefaultNetworkStatus {} /** - * Combined usage for this network regardless of whether it was the active default network. + * Combined usage for this network regardless of default network status. */ public static final int DEFAULT_NETWORK_ALL = -1; /** - * Usage that occurs while this network is not the active default network. + * Usage that occurs while this network is not a default network. + * + *

This implies that the app responsible for this usage requested that it occur on a + * specific network different from the one(s) the system would have selected for it. */ public static final int DEFAULT_NETWORK_NO = 0x1; /** - * Usage that occurs while this network is the active default network. + * Usage that occurs while this network is a default network. + * + *

This implies that the app either did not select a specific network for this usage, + * or it selected a network that the system could have selected for app traffic. */ public static final int DEFAULT_NETWORK_YES = 0x2; @@ -262,7 +268,7 @@ public final class NetworkStats implements AutoCloseable { private int mUid; private int mTag; private int mState; - private int mDefaultNetwork; + private int mDefaultNetworkStatus; private int mMetered; private int mRoaming; private long mBeginTimeStamp; @@ -323,8 +329,9 @@ public final class NetworkStats implements AutoCloseable { return 0; } - private static @DefaultNetwork int convertDefaultNetwork(int defaultNetwork) { - switch (defaultNetwork) { + private static @DefaultNetworkStatus int convertDefaultNetworkStatus( + int defaultNetworkStatus) { + switch (defaultNetworkStatus) { case android.net.NetworkStats.DEFAULT_NETWORK_ALL : return DEFAULT_NETWORK_ALL; case android.net.NetworkStats.DEFAULT_NETWORK_NO: return DEFAULT_NETWORK_NO; case android.net.NetworkStats.DEFAULT_NETWORK_YES: return DEFAULT_NETWORK_YES; @@ -397,18 +404,15 @@ public final class NetworkStats implements AutoCloseable { } /** - * Default network state. One of the following values:

+ * Default network status. One of the following values:

*

    *
  • {@link #DEFAULT_NETWORK_ALL}
  • *
  • {@link #DEFAULT_NETWORK_NO}
  • *
  • {@link #DEFAULT_NETWORK_YES}
  • *
- *

Indicates whether the network usage occurred on the system default network for this - * type of traffic, or whether the application chose to send this traffic on a network that - * was not the one selected by the system. */ - public @DefaultNetwork int getDefaultNetwork() { - return mDefaultNetwork; + public @DefaultNetworkStatus int getDefaultNetworkStatus() { + return mDefaultNetworkStatus; } /** @@ -605,7 +609,7 @@ public final class NetworkStats implements AutoCloseable { bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid); bucketOut.mTag = Bucket.convertTag(mRecycledSummaryEntry.tag); bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set); - bucketOut.mDefaultNetwork = Bucket.convertDefaultNetwork( + bucketOut.mDefaultNetworkStatus = Bucket.convertDefaultNetworkStatus( mRecycledSummaryEntry.defaultNetwork); bucketOut.mMetered = Bucket.convertMetered(mRecycledSummaryEntry.metered); bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming); @@ -657,7 +661,7 @@ public final class NetworkStats implements AutoCloseable { bucketOut.mUid = Bucket.convertUid(getUid()); bucketOut.mTag = Bucket.convertTag(mTag); bucketOut.mState = mState; - bucketOut.mDefaultNetwork = Bucket.DEFAULT_NETWORK_ALL; + bucketOut.mDefaultNetworkStatus = Bucket.DEFAULT_NETWORK_ALL; bucketOut.mMetered = Bucket.METERED_ALL; bucketOut.mRoaming = Bucket.ROAMING_ALL; bucketOut.mBeginTimeStamp = mRecycledHistoryEntry.bucketStart; From badc54893b0b2585a477c6eaee75c783776dc1e4 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 12 Apr 2018 19:26:34 +0900 Subject: [PATCH 166/881] Add rate limiting and logging for NetworkStats. Bug: 77908520, 77808546, 77853238, 77154412 Test: atest com.android.server.net.NetworkStatsServiceTest Test: manual: flashed, verified network usage updated Change-Id: I905dbea85e00f80103916939f6d4bf8cab931d03 --- .../server/net/NetworkStatsService.java | 65 +++++++++++++++++-- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4e848f8f36..e3ff72b9a9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -286,6 +286,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private long mPersistThreshold = 2 * MB_IN_BYTES; private long mGlobalAlertBytes; + private static final long POLL_RATE_LIMIT_MS = 15_000; + + private long mLastStatsSessionPoll; + + /** Map from UID to number of opened sessions */ + @GuardedBy("mOpenSessionCallsPerUid") + private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray(); + + private final static int DUMP_STATS_SESSION_COUNT = 20; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -509,10 +519,31 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return openSessionInternal(flags, callingPackage); } + private boolean isRateLimitedForPoll(int callingUid) { + if (callingUid == android.os.Process.SYSTEM_UID) { + return false; + } + + final long lastCallTime; + final long now = SystemClock.elapsedRealtime(); + synchronized (mOpenSessionCallsPerUid) { + int calls = mOpenSessionCallsPerUid.get(callingUid, 0); + mOpenSessionCallsPerUid.put(callingUid, calls + 1); + lastCallTime = mLastStatsSessionPoll; + mLastStatsSessionPoll = now; + } + + return now - lastCallTime < POLL_RATE_LIMIT_MS; + } + private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { assertBandwidthControlEnabled(); - if ((flags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) { + final int callingUid = Binder.getCallingUid(); + final int usedFlags = isRateLimitedForPoll(callingUid) + ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN) + : flags; + if ((usedFlags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) { final long ident = Binder.clearCallingIdentity(); try { performPoll(FLAG_PERSIST_ALL); @@ -525,7 +556,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // for its lifetime; when caller closes only weak references remain. return new INetworkStatsSession.Stub() { - private final int mCallingUid = Binder.getCallingUid(); + private final int mCallingUid = callingUid; private final String mCallingPackage = callingPackage; private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel( callingPackage); @@ -559,20 +590,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDeviceSummaryForNetwork( NetworkTemplate template, long start, long end) { - return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, + return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel, mCallingUid); } @Override public NetworkStats getSummaryForNetwork( NetworkTemplate template, long start, long end) { - return internalGetSummaryForNetwork(template, flags, start, end, mAccessLevel, + return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel, mCallingUid); } @Override public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { - return internalGetHistoryForNetwork(template, flags, fields, mAccessLevel, + return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel, mCallingUid); } @@ -1461,6 +1492,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } pw.decreaseIndent(); + // Get the top openSession callers + final SparseIntArray calls; + synchronized (mOpenSessionCallsPerUid) { + calls = mOpenSessionCallsPerUid.clone(); + } + + final int N = calls.size(); + final long[] values = new long[N]; + for (int j = 0; j < N; j++) { + values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j); + } + Arrays.sort(values); + + pw.println("Top openSession callers (uid=count):"); + pw.increaseIndent(); + final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT); + for (int j = N - 1; j >= end; j--) { + final int uid = (int) (values[j] & 0xffffffff); + final int count = (int) (values[j] >> 32); + pw.print(uid); pw.print("="); pw.println(count); + } + pw.decreaseIndent(); + pw.println(); + pw.println("Dev stats:"); pw.increaseIndent(); mDevRecorder.dumpLocked(pw, fullHistory); From c0318d130e66ed6eeea0578b76b20e29aa09c499 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 13 Apr 2018 13:29:59 -0600 Subject: [PATCH 167/881] OP_GET_USAGE_STATS should be noted, not checked. Per email feedback, we should be using "noteOp" instead of "checkOp" when testing if caller holds OP_GET_USAGE_STATS, so that we record that caller used the operation. Bug: 77662908 Test: builds, boots Exempt-From-Owner-Approval: keep tests passing Change-Id: I3a60345d590534fdbc2c1248e0d30dc85a5d6772 --- .../core/java/com/android/server/net/NetworkStatsAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 98fe770774..cebc472178 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -174,7 +174,7 @@ public final class NetworkStatsAccess { AppOpsManager appOps = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); - final int mode = appOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, + final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage); if (mode == AppOpsManager.MODE_DEFAULT) { // The default behavior here is to check if PackageManager has given the app From 53323c2812ff8fcf47976360d5e398ee5a744502 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 13 Apr 2018 14:28:30 -0600 Subject: [PATCH 168/881] Don't process broadcasts until really ready. Someone started setting mSystemReady too early, when we really want to know SystemServer's real ready state. Add a variable to track that, and don't process broadcasts until that's set. Bug: 78020762 Test: builds, boots Change-Id: I65213e46044c95fb0a8a4b09b9aa463bb15c1844 --- .../core/java/com/android/server/net/NetworkStatsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index e3ff72b9a9..e7f92dca60 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -282,7 +282,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private Handler mHandler; private Handler.Callback mHandlerCallback; - private boolean mSystemReady; + private volatile boolean mSystemReady; private long mPersistThreshold = 2 * MB_IN_BYTES; private long mGlobalAlertBytes; From f28796042a83ac44c79a8c37511d5263b5e13a30 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 16 Apr 2018 16:39:55 +0000 Subject: [PATCH 169/881] Revert "OP_GET_USAGE_STATS should be noted, not checked." This reverts commit c0318d130e66ed6eeea0578b76b20e29aa09c499. Reason for revert: ijpedowitz@ Bug: 77662908 Change-Id: I5dd0ad5038df90ea8a80ba6f583ee46fb24600c2 Exempt-From-Owner-Approval: keep tests passing --- .../core/java/com/android/server/net/NetworkStatsAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index cebc472178..98fe770774 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -174,7 +174,7 @@ public final class NetworkStatsAccess { AppOpsManager appOps = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); - final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, + final int mode = appOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage); if (mode == AppOpsManager.MODE_DEFAULT) { // The default behavior here is to check if PackageManager has given the app From 2f036210f4ca7a6ada7079d5593f483290956218 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 16 Apr 2018 16:50:34 +0000 Subject: [PATCH 170/881] Revert "Revert "OP_GET_USAGE_STATS should be noted, not checked."" This reverts commit f28796042a83ac44c79a8c37511d5263b5e13a30. Reason for revert: ijpedowitz@ Bug: 77662908 Change-Id: I596d330d64942105f447bb613012bb11e281a805 Exempt-From-Owner-Approval: keep tests passing --- .../core/java/com/android/server/net/NetworkStatsAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 98fe770774..cebc472178 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -174,7 +174,7 @@ public final class NetworkStatsAccess { AppOpsManager appOps = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); - final int mode = appOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, + final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage); if (mode == AppOpsManager.MODE_DEFAULT) { // The default behavior here is to check if PackageManager has given the app From f2a431ac181a374807745e3a9858911a601c6ef8 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 12 Apr 2018 14:26:32 -0600 Subject: [PATCH 171/881] Add tracing for network statistics and policy. These trace points surround areas of heavy lifting to help us debug code that might be taking longer than expected. (For example, slow getting data from eBPF, slow recording into data structures, slow writing to disk, or slow evaluating policy.) Typical timings on a taimen: performPollLocked: 25.5ms snapshotUid: 4.4ms snapshotXt: 1.4ms [persisting]: 13.4ms updateNotifications: 3.3ms Bug: 77908520, 77808546, 77853238, 77154412 Test: builds, boots Change-Id: I072bfecffee01eeec7e4cbad439bd1cdc166febc --- .../server/net/NetworkStatsService.java | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index e7f92dca60..7ee17bc2f8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -43,6 +43,7 @@ import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; +import static android.os.Trace.TRACE_TAG_NETWORK; import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; @@ -109,6 +110,7 @@ import android.os.Messenger; import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; +import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; @@ -1190,27 +1192,43 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void recordSnapshotLocked(long currentTime) throws RemoteException { // snapshot and record current counters; read UID stats first to // avoid over counting dev stats. + Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid"); final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL); + Trace.traceEnd(TRACE_TAG_NETWORK); + Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt"); final NetworkStats xtSnapshot = getNetworkStatsXt(); + Trace.traceEnd(TRACE_TAG_NETWORK); + Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev"); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); + Trace.traceEnd(TRACE_TAG_NETWORK); // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats // providers that isn't already counted by dev and XT stats. + Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotTether"); final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); + Trace.traceEnd(TRACE_TAG_NETWORK); xtSnapshot.combineAllValues(tetherSnapshot); devSnapshot.combineAllValues(tetherSnapshot); // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. + Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev"); mDevRecorder.recordSnapshotLocked( devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime); + Trace.traceEnd(TRACE_TAG_NETWORK); + Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt"); mXtRecorder.recordSnapshotLocked( xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime); + Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. VpnInfo[] vpnArray = mConnManager.getAllVpnInfo(); + Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); + Trace.traceEnd(TRACE_TAG_NETWORK); + Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag"); mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); + Trace.traceEnd(TRACE_TAG_NETWORK); // We need to make copies of member fields that are sent to the observer to avoid // a race condition between the service handler thread and the observer's @@ -1255,8 +1273,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void performPollLocked(int flags) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); - - final long startRealtime = SystemClock.elapsedRealtime(); + Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked"); final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0; @@ -1276,6 +1293,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // persist any pending data depending on requested flags + Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]"); if (persistForce) { mDevRecorder.forcePersistLocked(currentTime); mXtRecorder.forcePersistLocked(currentTime); @@ -1291,11 +1309,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mUidTagRecorder.maybePersistLocked(currentTime); } } - - if (LOGV) { - final long duration = SystemClock.elapsedRealtime() - startRealtime; - Slog.v(TAG, "performPollLocked() took " + duration + "ms"); - } + Trace.traceEnd(TRACE_TAG_NETWORK); if (mSettings.getSampleEnabled()) { // sample stats after each full poll @@ -1307,6 +1321,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, READ_NETWORK_USAGE_HISTORY); + + Trace.traceEnd(TRACE_TAG_NETWORK); } /** @@ -1389,12 +1405,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal { @Override public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { - return NetworkStatsService.this.getNetworkTotalBytes(template, start, end); + Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes"); + try { + return NetworkStatsService.this.getNetworkTotalBytes(template, start, end); + } finally { + Trace.traceEnd(TRACE_TAG_NETWORK); + } } @Override public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { - return NetworkStatsService.this.getNetworkUidBytes(template, start, end); + Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes"); + try { + return NetworkStatsService.this.getNetworkUidBytes(template, start, end); + } finally { + Trace.traceEnd(TRACE_TAG_NETWORK); + } } @Override From 4eade4d5eb5089d484e3ed1b760d0f499241af34 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 16 Apr 2018 16:39:55 +0000 Subject: [PATCH 172/881] Revert "OP_GET_USAGE_STATS should be noted, not checked." This reverts commit c0318d130e66ed6eeea0578b76b20e29aa09c499. Reason for revert: ijpedowitz@ Bug: 77662908 Change-Id: I5dd0ad5038df90ea8a80ba6f583ee46fb24600c2 Exempt-From-Owner-Approval: keep tests passing (cherry picked from commit f28796042a83ac44c79a8c37511d5263b5e13a30) --- .../core/java/com/android/server/net/NetworkStatsAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index cebc472178..98fe770774 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -174,7 +174,7 @@ public final class NetworkStatsAccess { AppOpsManager appOps = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); - final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, + final int mode = appOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, callingUid, callingPackage); if (mode == AppOpsManager.MODE_DEFAULT) { // The default behavior here is to check if PackageManager has given the app From 02ad62281bb72ab7a061bbcce873da7d68af108a Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 18 Apr 2018 15:42:57 -0600 Subject: [PATCH 173/881] Never interact with "phone" while holding locks. We've seen devices where heavy communication between "system_server" and the "phone" process can exhuast Binder threads, especially when calling while holding locks. To mitigate this, we now interact with the "phone" process before acquiring any locks. Update our internal data structures either when we see a connectivity change, or when SubscriptionManager tells us something changed. Fix bug in resolveSubscriptionPlan() that always picked the 0'th SubscriptionPlan instead of looking for the currently active plan; we now use the same logic for both NSS and NPMS. Bug: 77908520, 77154412 Test: atest com.android.server.NetworkPolicyManagerServiceTest Test: atest com.android.server.net.NetworkStatsServiceTest Change-Id: I177d3fa6cddc78d745b35a9ede12451d458b892c --- .../android/server/net/NetworkStatsService.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 7ee17bc2f8..ae7058d42e 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -116,7 +116,6 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; -import android.telephony.SubscriptionManager; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.text.format.DateUtils; @@ -679,22 +678,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) { SubscriptionPlan plan = null; if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0 - && (template.getMatchRule() == NetworkTemplate.MATCH_MOBILE) && mSettings.getAugmentEnabled()) { if (LOGD) Slog.d(TAG, "Resolving plan for " + template); final long token = Binder.clearCallingIdentity(); try { - final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class); - final TelephonyManager tm = mContext.getSystemService(TelephonyManager.class); - for (int subId : sm.getActiveSubscriptionIdList()) { - if (template.matchesSubscriberId(tm.getSubscriberId(subId))) { - if (LOGD) Slog.d(TAG, "Found active matching subId " + subId); - final List plans = sm.getSubscriptionPlans(subId); - if (!plans.isEmpty()) { - plan = plans.get(0); - } - } - } + plan = LocalServices.getService(NetworkPolicyManagerInternal.class) + .getSubscriptionPlan(template); } finally { Binder.restoreCallingIdentity(token); } From 32181a737930828ab077a218878549a48b41866f Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 20 Apr 2018 10:59:09 -0600 Subject: [PATCH 174/881] Give CTS a way to force-poll network stats. Collecting network statistics is pretty heavy, which is why we're throttling callers. However, to keep CTS running fast, we provide a way for tests to force a poll event, instead of making them wait for the throttle timeout. Bug: 77908520 Test: atest cts/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java Change-Id: Ia792f0cd495023366ff8c4839df54e7da2ae8331 --- .../android/app/usage/NetworkStatsManager.java | 15 ++++++++++++++- .../android/server/net/NetworkStatsService.java | 3 ++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 0b21196f5d..9f46f207d6 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -20,6 +20,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; import android.annotation.SystemService; +import android.annotation.TestApi; import android.app.usage.NetworkStats.Bucket; import android.content.Context; import android.net.ConnectivityManager; @@ -111,7 +112,9 @@ public class NetworkStatsManager { /** @hide */ public static final int FLAG_POLL_ON_OPEN = 1 << 0; /** @hide */ - public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 1; + public static final int FLAG_POLL_FORCE = 1 << 1; + /** @hide */ + public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2; private int mFlags; @@ -140,6 +143,16 @@ public class NetworkStatsManager { } } + /** @hide */ + @TestApi + public void setPollForce(boolean pollForce) { + if (pollForce) { + mFlags |= FLAG_POLL_FORCE; + } else { + mFlags &= ~FLAG_POLL_FORCE; + } + } + /** @hide */ public void setAugmentWithSubscriptionPlan(boolean augmentWithSubscriptionPlan) { if (augmentWithSubscriptionPlan) { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index ae7058d42e..9ef6c66b07 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -544,7 +544,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int usedFlags = isRateLimitedForPoll(callingUid) ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN) : flags; - if ((usedFlags & NetworkStatsManager.FLAG_POLL_ON_OPEN) != 0) { + if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN + | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) { final long ident = Binder.clearCallingIdentity(); try { performPoll(FLAG_PERSIST_ALL); From 21c4188a979c55f336728397e18273978d11f7f4 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 3 Apr 2018 16:13:19 -0700 Subject: [PATCH 175/881] Rework Exception Handling for IpSecManager In order to properly support EOPNOTSUPP this CL applies a consistent approach to handling Exceptions. Hereafter, all exceptions that aren't of a special method-specific type (such as SpiUnavailableException) will all be returned to the calling process unchanged. At the API call site, the ServiceSpecificException, which is really an Errno, will be inspected and either converted to an unchecked exception for types we know, or it will be converted to an IOException in cases where that method can return a checked exception. In cases where we do not expect an errno, we will simply throw a generic RuntimeException. This means all API calls will now properly throw UnsupportedOperationException and may be CTS tested accordingly. Bug: 72420898 Test: runtest frameworks-net Change-Id: I4a00e221618896223fcdb4b4279fb14cd14e34d8 --- core/java/android/net/IpSecManager.java | 147 ++++++++++++++++-- core/java/android/net/IpSecTransform.java | 16 ++ .../java/com/android/server/IpSecService.java | 71 +++------ 3 files changed, 173 insertions(+), 61 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index a61ea50d6f..d4c3edca43 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -26,6 +26,9 @@ import android.content.Context; import android.os.Binder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.system.ErrnoException; +import android.system.OsConstants; import android.util.AndroidException; import android.util.Log; @@ -172,11 +175,16 @@ public final class IpSecManager { public void close() { try { mService.releaseSecurityParameterIndex(mResourceId); - mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } - mCloseGuard.close(); } /** Check that the SPI was closed properly. */ @@ -227,7 +235,6 @@ public final class IpSecManager { throw new RuntimeException( "Invalid Resource ID returned by IpSecService: " + status); } - } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -239,6 +246,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("SecurityParameterIndex{spi=") + .append(mSpi) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } /** @@ -261,7 +279,11 @@ public final class IpSecManager { mService, destinationAddress, IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); + } catch (ServiceSpecificException e) { + throw rethrowUncheckedExceptionFromServiceSpecificException(e); } catch (SpiUnavailableException unlikely) { + // Because this function allocates a totally random SPI, it really shouldn't ever + // fail to allocate an SPI; we simply need this because the exception is checked. throw new ResourceUnavailableException("No SPIs available"); } } @@ -274,8 +296,8 @@ public final class IpSecManager { * * @param destinationAddress the destination address for traffic bearing the requested SPI. * For inbound traffic, the destination should be an address currently assigned on-device. - * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. The range 1-255 is - * reserved and may not be used. See RFC 4303 Section 2.1. + * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See + * RFC 4303 Section 2.1. * @return the reserved SecurityParameterIndex * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are * currently allocated for this user @@ -289,7 +311,11 @@ public final class IpSecManager { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); } - return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); + try { + return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); + } catch (ServiceSpecificException e) { + throw rethrowUncheckedExceptionFromServiceSpecificException(e); + } } /** @@ -424,6 +450,8 @@ public final class IpSecManager { // constructor takes control and closes the user's FD when we exit the method. try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -482,6 +510,8 @@ public final class IpSecManager { public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.removeTransportModeTransforms(pfd); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -575,6 +605,13 @@ public final class IpSecManager { mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } try { @@ -583,7 +620,6 @@ public final class IpSecManager { Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); throw e; } - mCloseGuard.close(); } /** Check that the socket was closed properly. */ @@ -600,6 +636,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("UdpEncapsulationSocket{port=") + .append(mPort) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } }; /** @@ -627,7 +674,11 @@ public final class IpSecManager { if (port == 0) { throw new IllegalArgumentException("Specified port must be a valid port number!"); } - return new UdpEncapsulationSocket(mService, port); + try { + return new UdpEncapsulationSocket(mService, port); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -650,7 +701,11 @@ public final class IpSecManager { @NonNull public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { - return new UdpEncapsulationSocket(mService, 0); + try { + return new UdpEncapsulationSocket(mService, 0); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -696,6 +751,8 @@ public final class IpSecManager { try { mService.addAddressToTunnelInterface( mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -715,6 +772,8 @@ public final class IpSecManager { try { mService.removeAddressFromTunnelInterface( mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -767,11 +826,16 @@ public final class IpSecManager { public void close() { try { mService.deleteTunnelInterface(mResourceId, mOpPackageName); - mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } - mCloseGuard.close(); } /** Check that the Interface was closed properly. */ @@ -788,6 +852,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("IpSecTunnelInterface{ifname=") + .append(mInterfaceName) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } /** @@ -810,8 +885,12 @@ public final class IpSecManager { public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { - return new IpSecTunnelInterface( - mContext, mService, localAddress, remoteAddress, underlyingNetwork); + try { + return new IpSecTunnelInterface( + mContext, mService, localAddress, remoteAddress, underlyingNetwork); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -838,6 +917,8 @@ public final class IpSecManager { mService.applyTunnelModeTransform( tunnel.getResourceId(), direction, transform.getResourceId(), mContext.getOpPackageName()); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -853,4 +934,44 @@ public final class IpSecManager { mContext = ctx; mService = checkNotNull(service, "missing service"); } + + private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) { + // OsConstants are late binding, so switch statements can't be used. + if (sse.errorCode == OsConstants.EINVAL) { + throw new IllegalArgumentException(sse); + } else if (sse.errorCode == OsConstants.EAGAIN) { + throw new IllegalStateException(sse); + } else if (sse.errorCode == OsConstants.EOPNOTSUPP) { + throw new UnsupportedOperationException(sse); + } + } + + /** + * Convert an Errno SSE to the correct Unchecked exception type. + * + * This method never actually returns. + */ + // package + static RuntimeException + rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse) { + maybeHandleServiceSpecificException(sse); + throw new RuntimeException(sse); + } + + /** + * Convert an Errno SSE to the correct Checked or Unchecked exception type. + * + * This method may throw IOException, or it may throw an unchecked exception; it will never + * actually return. + */ + // package + static IOException rethrowCheckedExceptionFromServiceSpecificException( + ServiceSpecificException sse) throws IOException { + // First see if this is an unchecked exception of a type we know. + // If so, then we prefer the unchecked (specific) type of exception. + maybeHandleServiceSpecificException(sse); + // If not, then all we can do is provide the SSE in the form of an IOException. + throw new ErrnoException( + "IpSec encountered errno=" + sse.errorCode, sse.errorCode).rethrowAsIOException(); + } } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 62f7996564..a12df28eac 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -28,6 +28,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -136,6 +137,8 @@ public final class IpSecTransform implements AutoCloseable { mResourceId = result.resourceId; Log.d(TAG, "Added Transform with Id " + mResourceId); mCloseGuard.open("build"); + } catch (ServiceSpecificException e) { + throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -180,6 +183,10 @@ public final class IpSecTransform implements AutoCloseable { stopNattKeepalive(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); } finally { mResourceId = INVALID_RESOURCE_ID; mCloseGuard.close(); @@ -502,4 +509,13 @@ public final class IpSecTransform implements AutoCloseable { mConfig = new IpSecConfig(); } } + + @Override + public String toString() { + return new StringBuilder() + .append("IpSecTransform{resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index cd90e3f9b0..33ca02fecb 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1101,9 +1101,11 @@ public class IpSecService extends IIpSecService.Stub { new RefcountedResource( new SpiRecord(resourceId, "", destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { - // TODO: Add appropriate checks when other ServiceSpecificException types are supported - return new IpSecSpiResponse( - IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi); + if (e.errorCode == OsConstants.ENOENT) { + return new IpSecSpiResponse( + IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi); + } + throw e; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1115,7 +1117,6 @@ public class IpSecService extends IIpSecService.Stub { */ private void releaseResource(RefcountedResourceArray resArray, int resourceId) throws RemoteException { - resArray.getRefcountedResourceOrThrow(resourceId).userRelease(); } @@ -1315,15 +1316,12 @@ public class IpSecService extends IIpSecService.Stub { releaseNetId(ikey); releaseNetId(okey); throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (Throwable t) { + // Release keys if we got an error. + releaseNetId(ikey); + releaseNetId(okey); + throw t; } - - // If we make it to here, then something has gone wrong and we couldn't create a VTI. - // Release the keys that we reserved, and return an error status. - releaseNetId(ikey); - releaseNetId(okey); - return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } /** @@ -1352,9 +1350,6 @@ public class IpSecService extends IIpSecService.Stub { localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. - throw new IllegalArgumentException(e); } } @@ -1384,9 +1379,6 @@ public class IpSecService extends IIpSecService.Stub { localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. - throw new IllegalArgumentException(e); } } @@ -1590,12 +1582,7 @@ public class IpSecService extends IIpSecService.Stub { dependencies.add(refcountedSpiRecord); SpiRecord spiRecord = refcountedSpiRecord.getResource(); - try { - createOrUpdateTransform(c, resourceId, spiRecord, socketRecord); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); - } + createOrUpdateTransform(c, resourceId, spiRecord, socketRecord); // SA was created successfully, time to construct a record and lock it away userRecord.mTransformRecords.put( @@ -1642,23 +1629,15 @@ public class IpSecService extends IIpSecService.Stub { c.getMode() == IpSecTransform.MODE_TRANSPORT, "Transform mode was not Transport mode; cannot be applied to a socket"); - try { - mSrvConfig - .getNetdInstance() - .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), - resourceId, - direction, - c.getSourceAddress(), - c.getDestinationAddress(), - info.getSpiRecord().getSpi()); - } catch (ServiceSpecificException e) { - if (e.errorCode == EINVAL) { - throw new IllegalArgumentException(e.toString()); - } else { - throw e; - } - } + mSrvConfig + .getNetdInstance() + .ipSecApplyTransportModeTransform( + socket.getFileDescriptor(), + resourceId, + direction, + c.getSourceAddress(), + c.getDestinationAddress(), + info.getSpiRecord().getSpi()); } /** @@ -1670,13 +1649,9 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) throws RemoteException { - try { - mSrvConfig - .getNetdInstance() - .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } + mSrvConfig + .getNetdInstance() + .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); } /** From dd65497239c3e4a57d6e2c263b70142352089354 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 18 Apr 2018 15:44:46 -0700 Subject: [PATCH 176/881] Use eBPF map data for per iface stats After adding the xt_bpf module and ifaceStatsMap, eBPF tool can now support reading per interface data. So networkStatsFactory should move away from parsing proc/net/dev and use the eBPF map stats instead. Bug: 72111305 Test: atest com.android.server.net.NetworkStatsServiceTest Change-Id: Ibcc6150d00835b3bd33af22a72e4a86e172581cf --- .../internal/net/NetworkStatsFactory.java | 19 ++++- ...droid_internal_net_NetworkStatsFactory.cpp | 81 +++++++++++-------- 2 files changed, 63 insertions(+), 37 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 8561bf0279..814b811e64 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -176,6 +176,14 @@ public class NetworkStatsFactory { return stats; } + public NetworkStats readBpfNetworkStatsDev() throws IOException { + final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); + if (nativeReadNetworkStatsDev(stats) != 0) { + throw new IOException("Failed to parse bpf iface stats"); + } + return stats; + } + /** * Parse and return interface-level summary {@link NetworkStats} measured * using {@code /proc/net/dev} style hooks, which may include non IP layer @@ -186,9 +194,9 @@ public class NetworkStatsFactory { */ public NetworkStats readNetworkStatsSummaryDev() throws IOException { - // Return the stats get from /proc/net/dev if switched to bpf module. + // Return xt_bpf stats if switched to bpf module. if (mUseBpfStats) - return readNetworkStatsIfaceDev(); + return readBpfNetworkStatsDev(); final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); @@ -242,9 +250,9 @@ public class NetworkStatsFactory { */ public NetworkStats readNetworkStatsSummaryXt() throws IOException { - // Return the stats get from /proc/net/dev if qtaguid module is replaced. + // Return xt_bpf stats if qtaguid module is replaced. if (mUseBpfStats) - return readNetworkStatsIfaceDev(); + return readBpfNetworkStatsDev(); final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); @@ -406,4 +414,7 @@ public class NetworkStatsFactory { @VisibleForTesting public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats); + + @VisibleForTesting + public static native int nativeReadNetworkStatsDev(NetworkStats stats); } diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 99d9839570..c15b7ee4fe 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -205,37 +205,8 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, return 0; } -static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path, - jint limitUid, jobjectArray limitIfacesObj, jint limitTag, - jboolean useBpfStats) { - ScopedUtfChars path8(env, path); - if (path8.c_str() == NULL) { - return -1; - } - - std::vector limitIfaces; - if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { - int num = env->GetArrayLength(limitIfacesObj); - for (int i = 0; i < num; i++) { - jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i); - ScopedUtfChars string8(env, string); - if (string8.c_str() != NULL) { - limitIfaces.push_back(std::string(string8.c_str())); - } - } - } - std::vector lines; - - - if (useBpfStats) { - if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0) - return -1; - } else { - if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag, - limitUid, path8.c_str()) < 0) - return -1; - } - +static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats, + std::vector& lines) { int size = lines.size(); bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity); @@ -308,14 +279,58 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstr env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray()); } - return 0; } +static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path, + jint limitUid, jobjectArray limitIfacesObj, jint limitTag, + jboolean useBpfStats) { + ScopedUtfChars path8(env, path); + if (path8.c_str() == NULL) { + return -1; + } + + std::vector limitIfaces; + if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { + int num = env->GetArrayLength(limitIfacesObj); + for (int i = 0; i < num; i++) { + jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i); + ScopedUtfChars string8(env, string); + if (string8.c_str() != NULL) { + limitIfaces.push_back(std::string(string8.c_str())); + } + } + } + std::vector lines; + + + if (useBpfStats) { + if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0) + return -1; + } else { + if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag, + limitUid, path8.c_str()) < 0) + return -1; + } + + return statsLinesToNetworkStats(env, clazz, stats, lines); +} + +static int readNetworkStatsDev(JNIEnv* env, jclass clazz, jobject stats) { + std::vector lines; + + if (parseBpfNetworkStatsDev(&lines) < 0) + return -1; + + return statsLinesToNetworkStats(env, clazz, stats, lines); +} + static const JNINativeMethod gMethods[] = { { "nativeReadNetworkStatsDetail", "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I", - (void*) readNetworkStatsDetail } + (void*) readNetworkStatsDetail }, + { "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I", + (void*) readNetworkStatsDev }, }; int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { From 1199060152d65d20104020dcfa9852fdec6be470 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Tue, 1 May 2018 13:51:13 -0700 Subject: [PATCH 177/881] Remove the unused file parsing function With the new xt_bpf support for iface stats. We no longer need to parse the per interface stats from /proc/net/dev. And since the old xt_qtaguid code path also not depend on it, we can completly remove that helper function since no caller is depending on it now. Bug: 72111305 Test: runtest frameworks-net -c com.android.internal.net.NetworkStatsFactoryTest Change-Id: Icb7eaeef0eeb9fdffd32a90316c76ee05bafffbe --- .../internal/net/NetworkStatsFactory.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 814b811e64..41802cc606 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -54,8 +54,6 @@ public class NetworkStatsFactory { private static final boolean USE_NATIVE_PARSING = true; private static final boolean SANITY_CHECK_NATIVE = false; - /** Path to {@code /proc/net/dev}. */ - private final File mStatsIfaceDev; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ private final File mStatsXtIfaceAll; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */ @@ -131,51 +129,12 @@ public class NetworkStatsFactory { @VisibleForTesting public NetworkStatsFactory(File procRoot, boolean useBpfStats) { - mStatsIfaceDev = new File(procRoot, "net/dev"); mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; } - @VisibleForTesting - public NetworkStats readNetworkStatsIfaceDev() throws IOException { - final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); - - final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); - final NetworkStats.Entry entry = new NetworkStats.Entry(); - - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader(mStatsIfaceDev)); - - // skip first two header lines - reader.readLine(); - reader.readLine(); - - // parse remaining lines - String line; - while ((line = reader.readLine()) != null) { - String[] values = line.trim().split("\\:?\\s+"); - entry.iface = values[0]; - entry.uid = UID_ALL; - entry.set = SET_ALL; - entry.tag = TAG_NONE; - entry.rxBytes = Long.parseLong(values[1]); - entry.rxPackets = Long.parseLong(values[2]); - entry.txBytes = Long.parseLong(values[9]); - entry.txPackets = Long.parseLong(values[10]); - stats.addValues(entry); - } - } catch (NullPointerException|NumberFormatException e) { - throw new ProtocolException("problem parsing stats", e); - } finally { - IoUtils.closeQuietly(reader); - StrictMode.setThreadPolicy(savedPolicy); - } - return stats; - } - public NetworkStats readBpfNetworkStatsDev() throws IOException { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); if (nativeReadNetworkStatsDev(stats) != 0) { From 5497c0e3a3adf8e7d44a5ef1a21ea9324bcc57ad Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 18 Apr 2018 15:44:46 -0700 Subject: [PATCH 178/881] Use eBPF map data for per iface stats After adding the xt_bpf module and ifaceStatsMap, eBPF tool can now support reading per interface data. So networkStatsFactory should move away from parsing proc/net/dev and use the eBPF map stats instead. Bug: 72111305 Test: atest com.android.server.net.NetworkStatsServiceTest Change-Id: Ibcc6150d00835b3bd33af22a72e4a86e172581cf Merged-In: Ibcc6150d00835b3bd33af22a72e4a86e172581cf (cherry picked from aosp commit dd65497239c3e4a57d6e2c263b70142352089354) --- .../internal/net/NetworkStatsFactory.java | 19 ++++- ...droid_internal_net_NetworkStatsFactory.cpp | 81 +++++++++++-------- 2 files changed, 63 insertions(+), 37 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 98afebc51b..e5cbdde544 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -178,6 +178,14 @@ public class NetworkStatsFactory { return stats; } + public NetworkStats readBpfNetworkStatsDev() throws IOException { + final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); + if (nativeReadNetworkStatsDev(stats) != 0) { + throw new IOException("Failed to parse bpf iface stats"); + } + return stats; + } + /** * Parse and return interface-level summary {@link NetworkStats} measured * using {@code /proc/net/dev} style hooks, which may include non IP layer @@ -188,9 +196,9 @@ public class NetworkStatsFactory { */ public NetworkStats readNetworkStatsSummaryDev() throws IOException { - // Return the stats get from /proc/net/dev if switched to bpf module. + // Return xt_bpf stats if switched to bpf module. if (mUseBpfStats) - return readNetworkStatsIfaceDev(); + return readBpfNetworkStatsDev(); final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); @@ -244,9 +252,9 @@ public class NetworkStatsFactory { */ public NetworkStats readNetworkStatsSummaryXt() throws IOException { - // Return the stats get from /proc/net/dev if qtaguid module is replaced. + // Return xt_bpf stats if qtaguid module is replaced. if (mUseBpfStats) - return readNetworkStatsIfaceDev(); + return readBpfNetworkStatsDev(); final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); @@ -408,4 +416,7 @@ public class NetworkStatsFactory { @VisibleForTesting public static native int nativeReadNetworkStatsDetail(NetworkStats stats, String path, int limitUid, String[] limitIfaces, int limitTag, boolean useBpfStats); + + @VisibleForTesting + public static native int nativeReadNetworkStatsDev(NetworkStats stats); } diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 99d9839570..c15b7ee4fe 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -205,37 +205,8 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, return 0; } -static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path, - jint limitUid, jobjectArray limitIfacesObj, jint limitTag, - jboolean useBpfStats) { - ScopedUtfChars path8(env, path); - if (path8.c_str() == NULL) { - return -1; - } - - std::vector limitIfaces; - if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { - int num = env->GetArrayLength(limitIfacesObj); - for (int i = 0; i < num; i++) { - jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i); - ScopedUtfChars string8(env, string); - if (string8.c_str() != NULL) { - limitIfaces.push_back(std::string(string8.c_str())); - } - } - } - std::vector lines; - - - if (useBpfStats) { - if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0) - return -1; - } else { - if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag, - limitUid, path8.c_str()) < 0) - return -1; - } - +static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats, + std::vector& lines) { int size = lines.size(); bool grow = size > env->GetIntField(stats, gNetworkStatsClassInfo.capacity); @@ -308,14 +279,58 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstr env->SetObjectField(stats, gNetworkStatsClassInfo.txPackets, txPackets.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.operations, operations.getJavaArray()); } - return 0; } +static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path, + jint limitUid, jobjectArray limitIfacesObj, jint limitTag, + jboolean useBpfStats) { + ScopedUtfChars path8(env, path); + if (path8.c_str() == NULL) { + return -1; + } + + std::vector limitIfaces; + if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { + int num = env->GetArrayLength(limitIfacesObj); + for (int i = 0; i < num; i++) { + jstring string = (jstring)env->GetObjectArrayElement(limitIfacesObj, i); + ScopedUtfChars string8(env, string); + if (string8.c_str() != NULL) { + limitIfaces.push_back(std::string(string8.c_str())); + } + } + } + std::vector lines; + + + if (useBpfStats) { + if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0) + return -1; + } else { + if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag, + limitUid, path8.c_str()) < 0) + return -1; + } + + return statsLinesToNetworkStats(env, clazz, stats, lines); +} + +static int readNetworkStatsDev(JNIEnv* env, jclass clazz, jobject stats) { + std::vector lines; + + if (parseBpfNetworkStatsDev(&lines) < 0) + return -1; + + return statsLinesToNetworkStats(env, clazz, stats, lines); +} + static const JNINativeMethod gMethods[] = { { "nativeReadNetworkStatsDetail", "(Landroid/net/NetworkStats;Ljava/lang/String;I[Ljava/lang/String;IZ)I", - (void*) readNetworkStatsDetail } + (void*) readNetworkStatsDetail }, + { "nativeReadNetworkStatsDev", "(Landroid/net/NetworkStats;)I", + (void*) readNetworkStatsDev }, }; int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { From 030dfa0f74c1a58a275c054db827c950014558ae Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Tue, 1 May 2018 13:51:13 -0700 Subject: [PATCH 179/881] Remove the unused file parsing function With the new xt_bpf support for iface stats. We no longer need to parse the per interface stats from /proc/net/dev. And since the old xt_qtaguid code path also not depend on it, we can completly remove that helper function since no caller is depending on it now. Bug: 72111305 Test: runtest frameworks-net -c com.android.internal.net.NetworkStatsFactoryTest Change-Id: Icb7eaeef0eeb9fdffd32a90316c76ee05bafffbe Merged-In: Icb7eaeef0eeb9fdffd32a90316c76ee05bafffbe (cherry picked from aosp commit 1199060152d65d20104020dcfa9852fdec6be470) --- .../internal/net/NetworkStatsFactory.java | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index e5cbdde544..c4d08c7dc5 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -56,8 +56,6 @@ public class NetworkStatsFactory { private static final boolean USE_NATIVE_PARSING = true; private static final boolean SANITY_CHECK_NATIVE = false; - /** Path to {@code /proc/net/dev}. */ - private final File mStatsIfaceDev; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ private final File mStatsXtIfaceAll; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */ @@ -133,51 +131,12 @@ public class NetworkStatsFactory { @VisibleForTesting public NetworkStatsFactory(File procRoot, boolean useBpfStats) { - mStatsIfaceDev = new File(procRoot, "net/dev"); mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; } - @VisibleForTesting - public NetworkStats readNetworkStatsIfaceDev() throws IOException { - final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); - - final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); - final NetworkStats.Entry entry = new NetworkStats.Entry(); - - BufferedReader reader = null; - try { - reader = new BufferedReader(new FileReader(mStatsIfaceDev)); - - // skip first two header lines - reader.readLine(); - reader.readLine(); - - // parse remaining lines - String line; - while ((line = reader.readLine()) != null) { - String[] values = line.trim().split("\\:?\\s+"); - entry.iface = values[0]; - entry.uid = UID_ALL; - entry.set = SET_ALL; - entry.tag = TAG_NONE; - entry.rxBytes = Long.parseLong(values[1]); - entry.rxPackets = Long.parseLong(values[2]); - entry.txBytes = Long.parseLong(values[9]); - entry.txPackets = Long.parseLong(values[10]); - stats.addValues(entry); - } - } catch (NullPointerException|NumberFormatException e) { - throw new ProtocolException("problem parsing stats", e); - } finally { - IoUtils.closeQuietly(reader); - StrictMode.setThreadPolicy(savedPolicy); - } - return stats; - } - public NetworkStats readBpfNetworkStatsDev() throws IOException { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); if (nativeReadNetworkStatsDev(stats) != 0) { From 6437a339a194e35bd13386d86356278b67e252a8 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 2 May 2018 14:57:06 -0600 Subject: [PATCH 180/881] Ethernet should be NOT_CONGESTED by default. Bug: 79160437 Test: builds, boots Change-Id: Iff726805a3c6b7cf2a4b741dbba93552c378a6e1 --- service-t/src/com/android/server/ethernet/EthernetTracker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 7f893e0339..688d84a2d6 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -311,6 +311,7 @@ final class EthernetTracker { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); return nc; } From 073b7977c520e79c3c1dbcad618e0de3921fdda2 Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Sat, 28 Apr 2018 23:23:26 -0700 Subject: [PATCH 181/881] Fix NPE during dumpsys ethernet Handle the case when IpClient wasn't created for network interface which may happen for virtual device Bug: 78482534 Test: dumpsys ethernet Change-Id: I3405dd4f72d4a6444448f0d6ec0497aead07bade --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index f95500e6e8..de0a691c75 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -440,7 +440,12 @@ public class EthernetNetworkFactory extends NetworkFactory { NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface); pw.println(iface + ":" + ifaceState); pw.increaseIndent(); - ifaceState.mIpClient.dump(fd, pw, args); + final IpClient ipClient = ifaceState.mIpClient; + if (ipClient != null) { + ipClient.dump(fd, pw, args); + } else { + pw.println("IpClient is null"); + } pw.decreaseIndent(); } pw.decreaseIndent(); From af2c0754431b119d2b8dd660e268cf42a18cc419 Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Sat, 28 Apr 2018 23:23:26 -0700 Subject: [PATCH 182/881] Fix NPE during dumpsys ethernet Handle the case when IpClient wasn't created for network interface which may happen for virtual device Bug: 78482534 Test: dumpsys ethernet Merged-In: I374a91265660e814b4f0f033b3970fd98921ca84 Merged-In: Id4ab7c9a8a5238491c8405ae260862e76a7671c1 Change-Id: I3405dd4f72d4a6444448f0d6ec0497aead07bade (cherry picked from commit 073b7977c520e79c3c1dbcad618e0de3921fdda2) --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index f95500e6e8..de0a691c75 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -440,7 +440,12 @@ public class EthernetNetworkFactory extends NetworkFactory { NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface); pw.println(iface + ":" + ifaceState); pw.increaseIndent(); - ifaceState.mIpClient.dump(fd, pw, args); + final IpClient ipClient = ifaceState.mIpClient; + if (ipClient != null) { + ipClient.dump(fd, pw, args); + } else { + pw.println("IpClient is null"); + } pw.decreaseIndent(); } pw.decreaseIndent(); From e6f4604404b1f52cebe8207c7155234f729363f5 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 26 Apr 2018 11:47:14 -0700 Subject: [PATCH 183/881] [DO NOT MERGE] Use INetd Constant for IpSec Interface Prefix Convert to using a constant in INetd to ensure that there is a consistent tunnel prefix between Java and native code. Bug: 74560705 Test: atest FramworksNetTest; atest CtsNetTestCases Change-Id: Ida233aac2e6c6b26567463964e0ebac9d52eff1e --- services/core/java/com/android/server/IpSecService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 33ca02fecb..60f1877d37 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -107,7 +107,6 @@ public class IpSecService extends IIpSecService.Stub { static final int FREE_PORT_MIN = 1024; // ports 1-1023 are reserved static final int PORT_MAX = 0xFFFF; // ports are an unsigned 16-bit integer - static final String TUNNEL_INTERFACE_PREFIX = "ipsec"; /* Binder context for this service */ private final Context mContext; @@ -1270,7 +1269,7 @@ public class IpSecService extends IIpSecService.Stub { final int resourceId = mNextResourceId++; final int ikey = reserveNetId(); final int okey = reserveNetId(); - String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId); + String intfName = String.format("%s%d", INetd.IPSEC_INTERFACE_PREFIX, resourceId); try { // Calls to netd: From 58cb06b6c84b186ab37acb609a0900b077bf49fc Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Wed, 9 May 2018 14:49:33 -0700 Subject: [PATCH 184/881] Fix overriding ip configurtion with default one EthernetConfigStore should return 'null' for default interface if the default interface hasn't been configured otherwise it would be hard to distinguish not-configured vs configured with default values. Bug: 79415136 Test: verified w/o .xml overlay Ethernet continues to work Test: verified that ip config from overlay is not getting overriden Change-Id: I4eb914923f3664b12b6af0ae05f45b60c5312b02 --- .../src/com/android/server/ethernet/EthernetConfigStore.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java index 6445603b96..6b623f48ff 100644 --- a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java +++ b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java @@ -16,6 +16,7 @@ package com.android.server.ethernet; +import android.annotation.Nullable; import android.net.IpConfiguration; import android.os.Environment; import android.util.ArrayMap; @@ -77,9 +78,11 @@ public class EthernetConfigStore { } } + @Nullable public IpConfiguration getIpConfigurationForDefaultInterface() { synchronized (mSync) { - return new IpConfiguration(mIpConfigurationForDefaultInterface); + return mIpConfigurationForDefaultInterface == null + ? null : new IpConfiguration(mIpConfigurationForDefaultInterface); } } } From a43eb59a079fd340f032bedf96af7e1238af464a Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 26 Apr 2018 11:47:14 -0700 Subject: [PATCH 185/881] Use INetd Constant for IpSec Interface Prefix Convert to using a constant in INetd to ensure that there is a consistent tunnel prefix between Java and native code. Bug: 74560705 Test: atest FramworksNetTest; atest CtsNetTestCases Change-Id: Ida233aac2e6c6b26567463964e0ebac9d52eff1e (cherry picked from commit e6f4604404b1f52cebe8207c7155234f729363f5) --- services/core/java/com/android/server/IpSecService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index bde6bd8db6..35bde8e18d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -104,7 +104,6 @@ public class IpSecService extends IIpSecService.Stub { static final int FREE_PORT_MIN = 1024; // ports 1-1023 are reserved static final int PORT_MAX = 0xFFFF; // ports are an unsigned 16-bit integer - static final String TUNNEL_INTERFACE_PREFIX = "ipsec"; /* Binder context for this service */ private final Context mContext; @@ -1257,7 +1256,7 @@ public class IpSecService extends IIpSecService.Stub { final int resourceId = mNextResourceId++; final int ikey = reserveNetId(); final int okey = reserveNetId(); - String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId); + String intfName = String.format("%s%d", INetd.IPSEC_INTERFACE_PREFIX, resourceId); try { // Calls to netd: From ae2fabaae0d066183e74af5937daa7e9cf08d5dc Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 26 Apr 2018 11:47:14 -0700 Subject: [PATCH 186/881] Use INetd Constant for IpSec Interface Prefix Convert to using a constant in INetd to ensure that there is a consistent tunnel prefix between Java and native code. Bug: 74560705 Test: atest FramworksNetTest; atest CtsNetTestCases Change-Id: Ida233aac2e6c6b26567463964e0ebac9d52eff1e (cherry picked from commit e6f4604404b1f52cebe8207c7155234f729363f5) --- services/core/java/com/android/server/IpSecService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 33ca02fecb..60f1877d37 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -107,7 +107,6 @@ public class IpSecService extends IIpSecService.Stub { static final int FREE_PORT_MIN = 1024; // ports 1-1023 are reserved static final int PORT_MAX = 0xFFFF; // ports are an unsigned 16-bit integer - static final String TUNNEL_INTERFACE_PREFIX = "ipsec"; /* Binder context for this service */ private final Context mContext; @@ -1270,7 +1269,7 @@ public class IpSecService extends IIpSecService.Stub { final int resourceId = mNextResourceId++; final int ikey = reserveNetId(); final int okey = reserveNetId(); - String intfName = String.format("%s%d", TUNNEL_INTERFACE_PREFIX, resourceId); + String intfName = String.format("%s%d", INetd.IPSEC_INTERFACE_PREFIX, resourceId); try { // Calls to netd: From 519e1dcae5c6ca6821780667bbf52000eba30b51 Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Wed, 9 May 2018 14:49:33 -0700 Subject: [PATCH 187/881] Fix overriding ip configurtion with default one EthernetConfigStore should return 'null' for default interface if the default interface hasn't been configured otherwise it would be hard to distinguish not-configured vs configured with default values. Bug: 79415136 Test: verified w/o .xml overlay Ethernet continues to work Test: verified that ip config from overlay is not getting overriden Merged-In: I82933a83a7d13903bbce9a85d6e8dae1a492bf24 Merged-In: I98133ad41229b93f51ea3976d311f9896456a56c Change-Id: I4eb914923f3664b12b6af0ae05f45b60c5312b02 (cherry picked from commit 58cb06b6c84b186ab37acb609a0900b077bf49fc) --- .../src/com/android/server/ethernet/EthernetConfigStore.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java index 6445603b96..6b623f48ff 100644 --- a/service-t/src/com/android/server/ethernet/EthernetConfigStore.java +++ b/service-t/src/com/android/server/ethernet/EthernetConfigStore.java @@ -16,6 +16,7 @@ package com.android.server.ethernet; +import android.annotation.Nullable; import android.net.IpConfiguration; import android.os.Environment; import android.util.ArrayMap; @@ -77,9 +78,11 @@ public class EthernetConfigStore { } } + @Nullable public IpConfiguration getIpConfigurationForDefaultInterface() { synchronized (mSync) { - return new IpConfiguration(mIpConfigurationForDefaultInterface); + return mIpConfigurationForDefaultInterface == null + ? null : new IpConfiguration(mIpConfigurationForDefaultInterface); } } } From ca8601efd10d22eb1694e8708a9aa80764b23856 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Fri, 18 May 2018 17:10:07 -0700 Subject: [PATCH 188/881] Check for bpf support at NetworkStatsService start The current implementation check for bpf map existance whenever a NetworkStats request comes in. The check is not efficient and may require additional permission for threads. So a member variable is added to NetworkStatsService to store the bpf configuration status and is initialized when NetworkStatsService start. Test: -m CtsNetTestCases -t android.net.cts.TrafficStatsTest -m CtsUsageStatsTestCases -t android.app.usage.cts.NetworkUsageStatsTest Bug: 79994577 Change-Id: I872ae18fb3e9631a4e6c4d773fefbba32e60a03b --- .../java/com/android/server/net/NetworkStatsService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 9ef6c66b07..492c6d6d51 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -184,6 +184,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final PowerManager.WakeLock mWakeLock; + private final boolean mUseBpfTrafficStats; + private IConnectivityManager mConnManager; @VisibleForTesting @@ -347,6 +349,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers"); mSystemDir = checkNotNull(systemDir, "missing systemDir"); mBaseDir = checkNotNull(baseDir, "missing baseDir"); + mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); LocalServices.addService(NetworkStatsManagerInternal.class, new NetworkStatsManagerInternalImpl()); @@ -947,7 +950,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private boolean checkBpfStatsEnable() { - return new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); + return mUseBpfTrafficStats; } /** From 82739ed5848ca150737acc2bd16edc4066b227da Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 22 May 2018 11:35:29 -0600 Subject: [PATCH 189/881] Last-ditch clamping of negative NetworkStats. We've seen reports of negative values flowing through to attempt being recorded, which will outright crash. This change does one last-ditch check to see if we're about to work with negative values, reporting any trouble and clamping them to zero so we don't crash. This gives us the data we need to continue investigating without triggering runtime restarts in the field. Bug: 80057433 Test: atest android.net.NetworkStatsTest Change-Id: I8174391c6cf5dadc2c2c10a8d841ee07e1f7d934 --- core/java/android/net/NetworkStats.java | 2 ++ .../server/net/NetworkStatsRecorder.java | 14 +++++++++++++ .../server/net/NetworkStatsService.java | 20 +++++++++++++++---- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index f0dd2629f9..edf9bc1c6b 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1100,6 +1100,8 @@ public class NetworkStats implements Parcelable { public interface NonMonotonicObserver { public void foundNonMonotonic( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie); + public void foundNonMonotonic( + NetworkStats stats, int statsIndex, C cookie); } /** diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index 4bee55ef8b..a16dcf358d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -241,6 +241,20 @@ public class NetworkStatsRecorder { NetworkStats.Entry entry = null; for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); + + // As a last-ditch sanity check, report any negative values and + // clamp them so recording below doesn't croak. + if (entry.isNegative()) { + if (mObserver != null) { + mObserver.foundNonMonotonic(delta, i, mCookie); + } + entry.rxBytes = Math.max(entry.rxBytes, 0); + entry.rxPackets = Math.max(entry.rxPackets, 0); + entry.txBytes = Math.max(entry.txBytes, 0); + entry.txPackets = Math.max(entry.txPackets, 0); + entry.operations = Math.max(entry.operations, 0); + } + final NetworkIdentitySet ident = ifaceIdent.get(entry.iface); if (ident == null) { unknownIfaces.add(entry.iface); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 9ef6c66b07..3354525498 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1713,7 +1713,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, String cookie) { - Log.w(TAG, "found non-monotonic values; saving to dropbox"); + Log.w(TAG, "Found non-monotonic values; saving to dropbox"); // record error for debugging final StringBuilder builder = new StringBuilder(); @@ -1722,9 +1722,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { builder.append("left=").append(left).append('\n'); builder.append("right=").append(right).append('\n'); - final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService( - Context.DROPBOX_SERVICE); - dropBox.addText(TAG_NETSTATS_ERROR, builder.toString()); + mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR, + builder.toString()); + } + + @Override + public void foundNonMonotonic( + NetworkStats stats, int statsIndex, String cookie) { + Log.w(TAG, "Found non-monotonic values; saving to dropbox"); + + final StringBuilder builder = new StringBuilder(); + builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n"); + builder.append("stats=").append(stats).append('\n'); + + mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR, + builder.toString()); } } From 3fb56e2ff43ba23e4674a8c98abbe58d015b8934 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 26 Apr 2018 17:52:03 +0900 Subject: [PATCH 190/881] Fix testRegisterUsageCallback failure in setUp LocalServices.addService in NetworkStatsService is currently failing with IllegalStateException "Overriding service registration". Setting up LocalServices in the test to avoid this issue might be possible, but moving the registration to the only non-test caller of that constructor as done here solves the issue and avoids side-effects from a constructor. Test: this test passes in master through runtest frameworks-net Bug: b/78487385 Bug: b/80082746 Change-Id: I884a7a8bd7db3fcd220b785ba9914ac8c77720f0 --- .../java/com/android/server/net/NetworkStatsService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 31072415dc..2e8e4a9a29 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -324,6 +324,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { wakeLock, getDefaultClock(), TelephonyManager.getDefault(), new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); + service.registerLocalService(); HandlerThread handlerThread = new HandlerThread(TAG); Handler.Callback callback = new HandlerCallback(service); @@ -333,6 +334,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return service; } + // This must not be called outside of tests, even within the same package, as this constructor + // does not register the local service. Use the create() helper above. @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, @@ -349,7 +352,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSystemDir = checkNotNull(systemDir, "missing systemDir"); mBaseDir = checkNotNull(baseDir, "missing baseDir"); mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); + } + private void registerLocalService() { LocalServices.addService(NetworkStatsManagerInternal.class, new NetworkStatsManagerInternalImpl()); } From 9e316bdc17715754422ce87748a70dd507abec9d Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Fri, 18 May 2018 17:10:07 -0700 Subject: [PATCH 191/881] Check for bpf support at NetworkStatsService start The current implementation check for bpf map existance whenever a NetworkStats request comes in. The check is not efficient and may require additional permission for threads. So a member variable is added to NetworkStatsService to store the bpf configuration status and is initialized when NetworkStatsService start. Test: -m CtsNetTestCases -t android.net.cts.TrafficStatsTest -m CtsUsageStatsTestCases -t android.app.usage.cts.NetworkUsageStatsTest Bug: 79994577 Change-Id: I872ae18fb3e9631a4e6c4d773fefbba32e60a03b Merged-In: I872ae18fb3e9631a4e6c4d773fefbba32e60a03b --- .../java/com/android/server/net/NetworkStatsService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index da40692a43..e5cf394e5a 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -179,6 +179,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final PowerManager.WakeLock mWakeLock; + private final boolean mUseBpfTrafficStats; + private IConnectivityManager mConnManager; @VisibleForTesting @@ -328,6 +330,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers"); mSystemDir = checkNotNull(systemDir, "missing systemDir"); mBaseDir = checkNotNull(baseDir, "missing baseDir"); + mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); } @VisibleForTesting @@ -916,7 +919,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private boolean checkBpfStatsEnable() { - return new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); + return mUseBpfTrafficStats; } /** From 017039edafdfc57b880ac11717b538d43ee0385e Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Wed, 30 May 2018 11:20:46 -0700 Subject: [PATCH 192/881] Add missing features to static IP config In addition to IP address, OEMs should be able to set gateway, DNS and domains. Bug: 80090920 Test: runtest -x frameworks/opt/net/ethernet/tests Change-Id: I4e3d51a6955d7bfe5ca4e8079936ea10c28832e4 --- Android.mk | 2 + .../server/ethernet/EthernetTracker.java | 58 +++++++- tests/ethernet/Android.mk | 36 +++++ tests/ethernet/AndroidManifest.xml | 28 ++++ .../server/ethernet/EthernetTrackerTest.java | 126 ++++++++++++++++++ 5 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 tests/ethernet/Android.mk create mode 100644 tests/ethernet/AndroidManifest.xml create mode 100644 tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java diff --git a/Android.mk b/Android.mk index 99559ac686..952fa9d652 100644 --- a/Android.mk +++ b/Android.mk @@ -28,3 +28,5 @@ LOCAL_JAVA_LIBRARIES := services LOCAL_MODULE := ethernet-service include $(BUILD_JAVA_LIBRARY) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 688d84a2d6..00eedd502d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -36,10 +36,13 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; +import java.net.InetAddress; +import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; /** @@ -300,7 +303,7 @@ final class EthernetTracker { mNetworkCapabilities.put(name, nc); if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) { - IpConfiguration ipConfig = createStaticIpConfiguration(tokens[2]); + IpConfiguration ipConfig = parseStaticIpConfiguration(tokens[2]); mIpConfigurations.put(name, ipConfig); } } @@ -342,11 +345,54 @@ final class EthernetTracker { return nc; } - private static IpConfiguration createStaticIpConfiguration(String strIpAddress) { - StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); - staticIpConfiguration.ipAddress = new LinkAddress(strIpAddress); - return new IpConfiguration( - IpAssignment.STATIC, ProxySettings.NONE, staticIpConfiguration, null); + /** + * Parses static IP configuration. + * + * @param staticIpConfig represents static IP configuration in the following format: {@code + * ip= gateway= dns= + * domains=} + */ + @VisibleForTesting + static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) { + StaticIpConfiguration ipConfig = new StaticIpConfiguration(); + + for (String keyValueAsString : staticIpConfig.trim().split(" ")) { + if (TextUtils.isEmpty(keyValueAsString)) continue; + + String[] pair = keyValueAsString.split("="); + if (pair.length != 2) { + throw new IllegalArgumentException("Unexpected token: " + keyValueAsString + + " in " + staticIpConfig); + } + + String key = pair[0]; + String value = pair[1]; + + switch (key) { + case "ip": + ipConfig.ipAddress = new LinkAddress(value); + break; + case "domains": + ipConfig.domains = value; + break; + case "gateway": + ipConfig.gateway = InetAddress.parseNumericAddress(value); + break; + case "dns": { + ArrayList dnsAddresses = new ArrayList<>(); + for (String address: value.split(",")) { + dnsAddresses.add(InetAddress.parseNumericAddress(address)); + } + ipConfig.dnsServers.addAll(dnsAddresses); + break; + } + default : { + throw new IllegalArgumentException("Unexpected key: " + key + + " in " + staticIpConfig); + } + } + } + return new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, ipConfig, null); } private static IpConfiguration createDefaultIpConfiguration() { diff --git a/tests/ethernet/Android.mk b/tests/ethernet/Android.mk new file mode 100644 index 0000000000..6b2c103474 --- /dev/null +++ b/tests/ethernet/Android.mk @@ -0,0 +1,36 @@ +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, java) + +LOCAL_PACKAGE_NAME := EthernetServiceTests + +LOCAL_CERTIFICATE := platform +LOCAL_PRIVATE_PLATFORM_APIS := true + +LOCAL_MODULE_TAGS := tests + +LOCAL_JAVA_LIBRARIES := \ + android.test.runner \ + android.test.base + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-test \ + ethernet-service + +include $(BUILD_PACKAGE) diff --git a/tests/ethernet/AndroidManifest.xml b/tests/ethernet/AndroidManifest.xml new file mode 100644 index 0000000000..1bc0775310 --- /dev/null +++ b/tests/ethernet/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java new file mode 100644 index 0000000000..70d316dbff --- /dev/null +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.ethernet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.StaticIpConfiguration; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.InetAddress; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class EthernetTrackerTest { + + @Test + public void createStaticIpConfiguration() { + assertStaticConfiguration("", new StaticIpConfiguration()); + + assertStaticConfiguration( + "ip=192.0.2.10/24", + new StaticIpConfigBuilder().setIp("192.0.2.10/24").build()); + + assertStaticConfiguration( + "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android", + new StaticIpConfigBuilder() + .setIp("192.0.2.10/24") + .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) + .setGateway("192.0.2.1") + .setDomains("android") + .build()); + + // Verify order doesn't matter + assertStaticConfiguration( + "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 ", + new StaticIpConfigBuilder() + .setIp("192.0.2.10/24") + .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) + .setGateway("192.0.2.1") + .setDomains("android") + .build()); + } + + @Test + public void createStaticIpConfiguration_Bad() { + assertFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key + assertFails("ip=192.0.2.1"); // mask is missing + assertFails("ip=a.b.c"); // not a valid ip address + assertFails("dns=4.4.4.4,1.2.3.A"); // not valid ip address in dns + assertFails("="); // Key and value is empty + assertFails("ip="); // Value is empty + assertFails("ip=192.0.2.1/24 gateway="); // Gateway is empty + } + + private void assertFails(String config) { + try { + EthernetTracker.parseStaticIpConfiguration(config); + fail("Expected to fail: " + config); + } catch (IllegalArgumentException e) { + // expected + } + } + + private void assertStaticConfiguration(String configAsString, + StaticIpConfiguration expectedStaticIpConfig) { + IpConfiguration expectedIpConfiguration = new IpConfiguration(IpAssignment.STATIC, + ProxySettings.NONE, expectedStaticIpConfig, null); + + assertEquals(expectedIpConfiguration, + EthernetTracker.parseStaticIpConfiguration(configAsString)); + } + + private static class StaticIpConfigBuilder { + private final StaticIpConfiguration config = new StaticIpConfiguration(); + + StaticIpConfigBuilder setIp(String address) { + config.ipAddress = new LinkAddress(address); + return this; + } + + StaticIpConfigBuilder setDns(String[] dnsArray) { + for (String dns : dnsArray) { + config.dnsServers.add(InetAddress.parseNumericAddress(dns)); + } + return this; + } + + StaticIpConfigBuilder setGateway(String gateway) { + config.gateway = InetAddress.parseNumericAddress(gateway); + return this; + } + + StaticIpConfigBuilder setDomains(String domains) { + config.domains = domains; + return this; + } + + + StaticIpConfiguration build() { + return new StaticIpConfiguration(config); + } + } +} From d16e70e64501484221ac1d94b4b95a99781831b0 Mon Sep 17 00:00:00 2001 From: Pavel Maltsev Date: Wed, 30 May 2018 11:20:46 -0700 Subject: [PATCH 193/881] Add missing features to static IP config In addition to IP address, OEMs should be able to set gateway, DNS and domains. Bug: 80090920 Test: runtest -x frameworks/opt/net/ethernet/tests Cherry picked without conflicts. Merged-in: I4e3d51a6955d7bfe5ca4e8079936ea10c28832e4 (cherry picked from commit 017039edafdfc57b880ac11717b538d43ee0385e) Change-Id: Ia8f095fbbcd414c070be4d5ce79dbc70bb9b1937 --- Android.mk | 2 + .../server/ethernet/EthernetTracker.java | 58 +++++++- tests/ethernet/Android.mk | 36 +++++ tests/ethernet/AndroidManifest.xml | 28 ++++ .../server/ethernet/EthernetTrackerTest.java | 126 ++++++++++++++++++ 5 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 tests/ethernet/Android.mk create mode 100644 tests/ethernet/AndroidManifest.xml create mode 100644 tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java diff --git a/Android.mk b/Android.mk index 99559ac686..952fa9d652 100644 --- a/Android.mk +++ b/Android.mk @@ -28,3 +28,5 @@ LOCAL_JAVA_LIBRARIES := services LOCAL_MODULE := ethernet-service include $(BUILD_JAVA_LIBRARY) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 7f893e0339..034b15d55c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -36,10 +36,13 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; +import java.net.InetAddress; +import java.util.ArrayList; import java.util.concurrent.ConcurrentHashMap; /** @@ -300,7 +303,7 @@ final class EthernetTracker { mNetworkCapabilities.put(name, nc); if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) { - IpConfiguration ipConfig = createStaticIpConfiguration(tokens[2]); + IpConfiguration ipConfig = parseStaticIpConfiguration(tokens[2]); mIpConfigurations.put(name, ipConfig); } } @@ -341,11 +344,54 @@ final class EthernetTracker { return nc; } - private static IpConfiguration createStaticIpConfiguration(String strIpAddress) { - StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); - staticIpConfiguration.ipAddress = new LinkAddress(strIpAddress); - return new IpConfiguration( - IpAssignment.STATIC, ProxySettings.NONE, staticIpConfiguration, null); + /** + * Parses static IP configuration. + * + * @param staticIpConfig represents static IP configuration in the following format: {@code + * ip= gateway= dns= + * domains=} + */ + @VisibleForTesting + static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) { + StaticIpConfiguration ipConfig = new StaticIpConfiguration(); + + for (String keyValueAsString : staticIpConfig.trim().split(" ")) { + if (TextUtils.isEmpty(keyValueAsString)) continue; + + String[] pair = keyValueAsString.split("="); + if (pair.length != 2) { + throw new IllegalArgumentException("Unexpected token: " + keyValueAsString + + " in " + staticIpConfig); + } + + String key = pair[0]; + String value = pair[1]; + + switch (key) { + case "ip": + ipConfig.ipAddress = new LinkAddress(value); + break; + case "domains": + ipConfig.domains = value; + break; + case "gateway": + ipConfig.gateway = InetAddress.parseNumericAddress(value); + break; + case "dns": { + ArrayList dnsAddresses = new ArrayList<>(); + for (String address: value.split(",")) { + dnsAddresses.add(InetAddress.parseNumericAddress(address)); + } + ipConfig.dnsServers.addAll(dnsAddresses); + break; + } + default : { + throw new IllegalArgumentException("Unexpected key: " + key + + " in " + staticIpConfig); + } + } + } + return new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, ipConfig, null); } private static IpConfiguration createDefaultIpConfiguration() { diff --git a/tests/ethernet/Android.mk b/tests/ethernet/Android.mk new file mode 100644 index 0000000000..6b2c103474 --- /dev/null +++ b/tests/ethernet/Android.mk @@ -0,0 +1,36 @@ +# Copyright (C) 2018 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, java) + +LOCAL_PACKAGE_NAME := EthernetServiceTests + +LOCAL_CERTIFICATE := platform +LOCAL_PRIVATE_PLATFORM_APIS := true + +LOCAL_MODULE_TAGS := tests + +LOCAL_JAVA_LIBRARIES := \ + android.test.runner \ + android.test.base + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-test \ + ethernet-service + +include $(BUILD_PACKAGE) diff --git a/tests/ethernet/AndroidManifest.xml b/tests/ethernet/AndroidManifest.xml new file mode 100644 index 0000000000..1bc0775310 --- /dev/null +++ b/tests/ethernet/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java new file mode 100644 index 0000000000..70d316dbff --- /dev/null +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.ethernet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.net.IpConfiguration; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.StaticIpConfiguration; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.InetAddress; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class EthernetTrackerTest { + + @Test + public void createStaticIpConfiguration() { + assertStaticConfiguration("", new StaticIpConfiguration()); + + assertStaticConfiguration( + "ip=192.0.2.10/24", + new StaticIpConfigBuilder().setIp("192.0.2.10/24").build()); + + assertStaticConfiguration( + "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android", + new StaticIpConfigBuilder() + .setIp("192.0.2.10/24") + .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) + .setGateway("192.0.2.1") + .setDomains("android") + .build()); + + // Verify order doesn't matter + assertStaticConfiguration( + "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 ", + new StaticIpConfigBuilder() + .setIp("192.0.2.10/24") + .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) + .setGateway("192.0.2.1") + .setDomains("android") + .build()); + } + + @Test + public void createStaticIpConfiguration_Bad() { + assertFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key + assertFails("ip=192.0.2.1"); // mask is missing + assertFails("ip=a.b.c"); // not a valid ip address + assertFails("dns=4.4.4.4,1.2.3.A"); // not valid ip address in dns + assertFails("="); // Key and value is empty + assertFails("ip="); // Value is empty + assertFails("ip=192.0.2.1/24 gateway="); // Gateway is empty + } + + private void assertFails(String config) { + try { + EthernetTracker.parseStaticIpConfiguration(config); + fail("Expected to fail: " + config); + } catch (IllegalArgumentException e) { + // expected + } + } + + private void assertStaticConfiguration(String configAsString, + StaticIpConfiguration expectedStaticIpConfig) { + IpConfiguration expectedIpConfiguration = new IpConfiguration(IpAssignment.STATIC, + ProxySettings.NONE, expectedStaticIpConfig, null); + + assertEquals(expectedIpConfiguration, + EthernetTracker.parseStaticIpConfiguration(configAsString)); + } + + private static class StaticIpConfigBuilder { + private final StaticIpConfiguration config = new StaticIpConfiguration(); + + StaticIpConfigBuilder setIp(String address) { + config.ipAddress = new LinkAddress(address); + return this; + } + + StaticIpConfigBuilder setDns(String[] dnsArray) { + for (String dns : dnsArray) { + config.dnsServers.add(InetAddress.parseNumericAddress(dns)); + } + return this; + } + + StaticIpConfigBuilder setGateway(String gateway) { + config.gateway = InetAddress.parseNumericAddress(gateway); + return this; + } + + StaticIpConfigBuilder setDomains(String domains) { + config.domains = domains; + return this; + } + + + StaticIpConfiguration build() { + return new StaticIpConfiguration(config); + } + } +} From a9a8f0389b3d54d44633743a5ef3d2009437d4c5 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Wed, 21 Mar 2018 15:32:42 -0700 Subject: [PATCH 194/881] Add MANAGE_IPSEC_TUNNELS Permission Add a new MANAGE_IPSEC_TUNNELS permission and protect all IPsec Tunnel mode APIs with it. This permission is only granted to the system or through an AppOp. Bug: 66955045 Test: compilation Merged-In: I0f618373b500c493ef2211bece681f74652a1833 Change-Id: I0f618373b500c493ef2211bece681f74652a1833 (cherry picked from commit 9a713bd28ec77d361041025496d73a8935621f79) --- core/java/android/net/IpSecManager.java | 6 ++++-- core/java/android/net/IpSecTransform.java | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index cc227713cb..d2c83e2b5e 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -691,6 +691,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull LinkAddress address) throws IOException { try { mService.addAddressToTunnelInterface(mResourceId, address); @@ -708,6 +709,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull LinkAddress address) throws IOException { try { mService.removeAddressFromTunnelInterface(mResourceId, address); @@ -801,7 +803,7 @@ public final class IpSecManager { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { @@ -826,7 +828,7 @@ public final class IpSecManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { try { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index cf58647bbb..099fe02fdd 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -282,7 +282,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD }) public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback, @@ -325,7 +325,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @RequiresPermission(anyOf = { - android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD }) public void stopNattKeepalive() { @@ -478,7 +478,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @NonNull - @RequiresPermission(android.Manifest.permission.NETWORK_STACK) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, @NonNull IpSecManager.SecurityParameterIndex spi) From a78f084edb21acc55883903dac0a0911aed4e721 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 15 Mar 2018 18:06:06 -0700 Subject: [PATCH 195/881] Add AppOps Checks for MANAGE_IPSEC_TUNNELS Adds support for a new AppOp to permit services to use IpSec tunnel mode. The IpSecService now needs a context so change the service mode to a cached service rather than a static service. Bug: 66955045 Test: runtest frameworks-net Merged-In: I17a4a286225b432c3e15ea1587d946189931b4f4 Change-Id: I17a4a286225b432c3e15ea1587d946189931b4f4 (cherry picked from commit a10a7f99c4b3de81bbbd246eeecc95d77730aced) --- core/java/android/net/IIpSecService.aidl | 20 ++++--- core/java/android/net/IpSecManager.java | 25 +++++--- core/java/android/net/IpSecTransform.java | 3 +- .../java/com/android/server/IpSecService.java | 59 ++++++++++++++----- 4 files changed, 76 insertions(+), 31 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index 3a3ddcc483..d6774d47b4 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -45,25 +45,31 @@ interface IIpSecService in String localAddr, in String remoteAddr, in Network underlyingNetwork, - in IBinder binder); + in IBinder binder, + in String callingPackage); void addAddressToTunnelInterface( int tunnelResourceId, - in LinkAddress localAddr); + in LinkAddress localAddr, + in String callingPackage); void removeAddressFromTunnelInterface( int tunnelResourceId, - in LinkAddress localAddr); + in LinkAddress localAddr, + in String callingPackage); - void deleteTunnelInterface(int resourceId); + void deleteTunnelInterface(int resourceId, in String callingPackage); - IpSecTransformResponse createTransform(in IpSecConfig c, in IBinder binder); + IpSecTransformResponse createTransform( + in IpSecConfig c, in IBinder binder, in String callingPackage); void deleteTransform(int transformId); - void applyTransportModeTransform(in ParcelFileDescriptor socket, int direction, int transformId); + void applyTransportModeTransform( + in ParcelFileDescriptor socket, int direction, int transformId); - void applyTunnelModeTransform(int tunnelResourceId, int direction, int transformResourceId); + void applyTunnelModeTransform( + int tunnelResourceId, int direction, int transformResourceId, in String callingPackage); void removeTransportModeTransforms(in ParcelFileDescriptor socket); } diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index d2c83e2b5e..0d04fe5a91 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -140,6 +140,7 @@ public final class IpSecManager { } } + private final Context mContext; private final IIpSecService mService; /** @@ -667,6 +668,7 @@ public final class IpSecManager { */ @SystemApi public static final class IpSecTunnelInterface implements AutoCloseable { + private final String mOpPackageName; private final IIpSecService mService; private final InetAddress mRemoteAddress; private final InetAddress mLocalAddress; @@ -694,7 +696,8 @@ public final class IpSecManager { @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull LinkAddress address) throws IOException { try { - mService.addAddressToTunnelInterface(mResourceId, address); + mService.addAddressToTunnelInterface( + mResourceId, address, mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -712,16 +715,18 @@ public final class IpSecManager { @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull LinkAddress address) throws IOException { try { - mService.removeAddressFromTunnelInterface(mResourceId, address); + mService.removeAddressFromTunnelInterface( + mResourceId, address, mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } - private IpSecTunnelInterface(@NonNull IIpSecService service, + private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { + mOpPackageName = ctx.getOpPackageName(); mService = service; mLocalAddress = localAddress; mRemoteAddress = remoteAddress; @@ -733,7 +738,8 @@ public final class IpSecManager { localAddress.getHostAddress(), remoteAddress.getHostAddress(), underlyingNetwork, - new Binder()); + new Binder(), + mOpPackageName); switch (result.status) { case Status.OK: break; @@ -762,7 +768,7 @@ public final class IpSecManager { @Override public void close() { try { - mService.deleteTunnelInterface(mResourceId); + mService.deleteTunnelInterface(mResourceId, mOpPackageName); mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -807,7 +813,8 @@ public final class IpSecManager { public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { - return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork); + return new IpSecTunnelInterface( + mContext, mService, localAddress, remoteAddress, underlyingNetwork); } /** @@ -833,7 +840,8 @@ public final class IpSecManager { @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { try { mService.applyTunnelModeTransform( - tunnel.getResourceId(), direction, transform.getResourceId()); + tunnel.getResourceId(), direction, + transform.getResourceId(), mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -845,7 +853,8 @@ public final class IpSecManager { * @param context the application context for this manager * @hide */ - public IpSecManager(IIpSecService service) { + public IpSecManager(Context ctx, IIpSecService service) { + mContext = ctx; mService = checkNotNull(service, "missing service"); } } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 099fe02fdd..fb5f46c117 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -130,7 +130,8 @@ public final class IpSecTransform implements AutoCloseable { synchronized (this) { try { IIpSecService svc = getIpSecService(); - IpSecTransformResponse result = svc.createTransform(mConfig, new Binder()); + IpSecTransformResponse result = svc.createTransform( + mConfig, new Binder(), mContext.getOpPackageName()); int status = result.status; checkResultStatus(status); mResourceId = result.resourceId; diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 35bde8e18d..9709885887 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -24,6 +24,8 @@ import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; +import android.annotation.NonNull; +import android.app.AppOpsManager; import android.content.Context; import android.net.ConnectivityManager; import android.net.IIpSecService; @@ -42,6 +44,7 @@ import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; +import android.os.DeadSystemException; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -973,6 +976,13 @@ public class IpSecService extends IIpSecService.Stub { return service; } + @NonNull + private AppOpsManager getAppOpsManager() { + AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + if(appOps == null) throw new RuntimeException("System Server couldn't get AppOps"); + return appOps; + } + /** @hide */ @VisibleForTesting public IpSecService(Context context, IpSecServiceConfiguration config) { @@ -1239,7 +1249,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized IpSecTunnelInterfaceResponse createTunnelInterface( - String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder) { + String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, + String callingPackage) { + enforceTunnelPermissions(callingPackage); checkNotNull(binder, "Null Binder passed to createTunnelInterface"); checkNotNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); @@ -1319,8 +1331,8 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void addAddressToTunnelInterface( - int tunnelResourceId, LinkAddress localAddr) { - enforceNetworkStackPermission(); + int tunnelResourceId, LinkAddress localAddr, String callingPackage) { + enforceTunnelPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1351,10 +1363,10 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void removeAddressFromTunnelInterface( - int tunnelResourceId, LinkAddress localAddr) { - enforceNetworkStackPermission(); - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int tunnelResourceId, LinkAddress localAddr, String callingPackage) { + enforceTunnelPermissions(callingPackage); + UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw // IllegalArgumentException TunnelInterfaceRecord tunnelInterfaceInfo = @@ -1382,7 +1394,9 @@ public class IpSecService extends IIpSecService.Stub { * server */ @Override - public synchronized void deleteTunnelInterface(int resourceId) throws RemoteException { + public synchronized void deleteTunnelInterface( + int resourceId, String callingPackage) throws RemoteException { + enforceTunnelPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); releaseResource(userRecord.mTunnelInterfaceRecords, resourceId); } @@ -1468,7 +1482,6 @@ public class IpSecService extends IIpSecService.Stub { case IpSecTransform.MODE_TRANSPORT: break; case IpSecTransform.MODE_TUNNEL: - enforceNetworkStackPermission(); break; default: throw new IllegalArgumentException( @@ -1476,9 +1489,20 @@ public class IpSecService extends IIpSecService.Stub { } } - private void enforceNetworkStackPermission() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK, - "IpSecService"); + private void enforceTunnelPermissions(String callingPackage) { + checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); + switch (getAppOpsManager().noteOp( + AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, + Binder.getCallingUid(), callingPackage)) { + case AppOpsManager.MODE_DEFAULT: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); + break; + case AppOpsManager.MODE_ALLOWED: + return; + default: + throw new SecurityException("Request to ignore AppOps for non-legacy API"); + } } private void createOrUpdateTransform( @@ -1534,8 +1558,12 @@ public class IpSecService extends IIpSecService.Stub { * result in all of those sockets becoming unable to send or receive data. */ @Override - public synchronized IpSecTransformResponse createTransform(IpSecConfig c, IBinder binder) - throws RemoteException { + public synchronized IpSecTransformResponse createTransform( + IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { + checkNotNull(c); + if (c.getMode() == IpSecTransform.MODE_TUNNEL) { + enforceTunnelPermissions(callingPackage); + } checkIpSecConfig(c); checkNotNull(binder, "Null Binder passed to createTransform"); final int resourceId = mNextResourceId++; @@ -1656,8 +1684,9 @@ public class IpSecService extends IIpSecService.Stub { */ @Override public synchronized void applyTunnelModeTransform( - int tunnelResourceId, int direction, int transformResourceId) throws RemoteException { - enforceNetworkStackPermission(); + int tunnelResourceId, int direction, + int transformResourceId, String callingPackage) throws RemoteException { + enforceTunnelPermissions(callingPackage); checkDirection(direction); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); From ed6562e362d2e66867e4531ee957e7a85d5ab7b8 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 3 Apr 2018 20:30:54 -0700 Subject: [PATCH 196/881] Update IpSecManager to use InetAddress and prefixLen LinkAddress constructors are currently @hide; this change updates IpSecManager to use InetAddress and prefixLen, and then construct a LinkAddress internally. LinkAddress is used over the binder interface to IpSecService to ensure validity. Bug: 77528639 Test: CTS, Java unit tests ran on walleye Merged-In: I19e124adef6d9f4992d8293db3190bcf74c95848 Change-Id: I19e124adef6d9f4992d8293db3190bcf74c95848 (cherry picked from commit e84200fc5b1a7a469822fee2cceb2d469e8aeea2) --- core/java/android/net/IpSecManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 0d04fe5a91..87323755a9 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -690,14 +690,15 @@ public final class IpSecManager { * tunneled traffic. * * @param address the local address for traffic inside the tunnel + * @param prefixLen length of the InetAddress prefix * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) - public void addAddress(@NonNull LinkAddress address) throws IOException { + public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { mService.addAddressToTunnelInterface( - mResourceId, address, mOpPackageName); + mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -709,14 +710,15 @@ public final class IpSecManager { *

Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed + * @param prefixLen length of the InetAddress prefix * @hide */ @SystemApi @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) - public void removeAddress(@NonNull LinkAddress address) throws IOException { + public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { mService.removeAddressFromTunnelInterface( - mResourceId, address, mOpPackageName); + mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } From a6722e470f30801baaf7636a088bc8bea583bd7d Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 3 Apr 2018 16:13:19 -0700 Subject: [PATCH 197/881] Rework Exception Handling for IpSecManager In order to properly support EOPNOTSUPP this CL applies a consistent approach to handling Exceptions. Hereafter, all exceptions that aren't of a special method-specific type (such as SpiUnavailableException) will all be returned to the calling process unchanged. At the API call site, the ServiceSpecificException, which is really an Errno, will be inspected and either converted to an unchecked exception for types we know, or it will be converted to an IOException in cases where that method can return a checked exception. In cases where we do not expect an errno, we will simply throw a generic RuntimeException. This means all API calls will now properly throw UnsupportedOperationException and may be CTS tested accordingly. Bug: 72420898 Test: runtest frameworks-net Merged-In: I4a00e221618896223fcdb4b4279fb14cd14e34d8 Change-Id: I4a00e221618896223fcdb4b4279fb14cd14e34d8 (cherry picked from commit 21c4188a979c55f336728397e18273978d11f7f4) --- core/java/android/net/IpSecManager.java | 147 ++++++++++++++++-- core/java/android/net/IpSecTransform.java | 16 ++ .../java/com/android/server/IpSecService.java | 71 +++------ 3 files changed, 173 insertions(+), 61 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 87323755a9..1145d5bd4d 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -27,6 +27,9 @@ import android.content.Context; import android.os.Binder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.system.ErrnoException; +import android.system.OsConstants; import android.util.AndroidException; import android.util.Log; @@ -173,11 +176,16 @@ public final class IpSecManager { public void close() { try { mService.releaseSecurityParameterIndex(mResourceId); - mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } - mCloseGuard.close(); } /** Check that the SPI was closed properly. */ @@ -228,7 +236,6 @@ public final class IpSecManager { throw new RuntimeException( "Invalid Resource ID returned by IpSecService: " + status); } - } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -240,6 +247,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("SecurityParameterIndex{spi=") + .append(mSpi) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } /** @@ -262,7 +280,11 @@ public final class IpSecManager { mService, destinationAddress, IpSecManager.INVALID_SECURITY_PARAMETER_INDEX); + } catch (ServiceSpecificException e) { + throw rethrowUncheckedExceptionFromServiceSpecificException(e); } catch (SpiUnavailableException unlikely) { + // Because this function allocates a totally random SPI, it really shouldn't ever + // fail to allocate an SPI; we simply need this because the exception is checked. throw new ResourceUnavailableException("No SPIs available"); } } @@ -275,8 +297,8 @@ public final class IpSecManager { * * @param destinationAddress the destination address for traffic bearing the requested SPI. * For inbound traffic, the destination should be an address currently assigned on-device. - * @param requestedSpi the requested SPI, or '0' to allocate a random SPI. The range 1-255 is - * reserved and may not be used. See RFC 4303 Section 2.1. + * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See + * RFC 4303 Section 2.1. * @return the reserved SecurityParameterIndex * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are * currently allocated for this user @@ -290,7 +312,11 @@ public final class IpSecManager { if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) { throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI"); } - return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); + try { + return new SecurityParameterIndex(mService, destinationAddress, requestedSpi); + } catch (ServiceSpecificException e) { + throw rethrowUncheckedExceptionFromServiceSpecificException(e); + } } /** @@ -425,6 +451,8 @@ public final class IpSecManager { // constructor takes control and closes the user's FD when we exit the method. try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.applyTransportModeTransform(pfd, direction, transform.getResourceId()); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -483,6 +511,8 @@ public final class IpSecManager { public void removeTransportModeTransforms(@NonNull FileDescriptor socket) throws IOException { try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) { mService.removeTransportModeTransforms(pfd); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -576,6 +606,13 @@ public final class IpSecManager { mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } try { @@ -584,7 +621,6 @@ public final class IpSecManager { Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort); throw e; } - mCloseGuard.close(); } /** Check that the socket was closed properly. */ @@ -601,6 +637,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("UdpEncapsulationSocket{port=") + .append(mPort) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } }; /** @@ -628,7 +675,11 @@ public final class IpSecManager { if (port == 0) { throw new IllegalArgumentException("Specified port must be a valid port number!"); } - return new UdpEncapsulationSocket(mService, port); + try { + return new UdpEncapsulationSocket(mService, port); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -651,7 +702,11 @@ public final class IpSecManager { @NonNull public UdpEncapsulationSocket openUdpEncapsulationSocket() throws IOException, ResourceUnavailableException { - return new UdpEncapsulationSocket(mService, 0); + try { + return new UdpEncapsulationSocket(mService, 0); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -699,6 +754,8 @@ public final class IpSecManager { try { mService.addAddressToTunnelInterface( mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -719,6 +776,8 @@ public final class IpSecManager { try { mService.removeAddressFromTunnelInterface( mResourceId, new LinkAddress(address, prefixLen), mOpPackageName); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -771,11 +830,16 @@ public final class IpSecManager { public void close() { try { mService.deleteTunnelInterface(mResourceId, mOpPackageName); - mResourceId = INVALID_RESOURCE_ID; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); + } finally { + mResourceId = INVALID_RESOURCE_ID; + mCloseGuard.close(); } - mCloseGuard.close(); } /** Check that the Interface was closed properly. */ @@ -792,6 +856,17 @@ public final class IpSecManager { public int getResourceId() { return mResourceId; } + + @Override + public String toString() { + return new StringBuilder() + .append("IpSecTunnelInterface{ifname=") + .append(mInterfaceName) + .append(",resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } /** @@ -815,8 +890,12 @@ public final class IpSecManager { public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) throws ResourceUnavailableException, IOException { - return new IpSecTunnelInterface( - mContext, mService, localAddress, remoteAddress, underlyingNetwork); + try { + return new IpSecTunnelInterface( + mContext, mService, localAddress, remoteAddress, underlyingNetwork); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); + } } /** @@ -844,6 +923,8 @@ public final class IpSecManager { mService.applyTunnelModeTransform( tunnel.getResourceId(), direction, transform.getResourceId(), mContext.getOpPackageName()); + } catch (ServiceSpecificException e) { + throw rethrowCheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -859,4 +940,44 @@ public final class IpSecManager { mContext = ctx; mService = checkNotNull(service, "missing service"); } + + private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) { + // OsConstants are late binding, so switch statements can't be used. + if (sse.errorCode == OsConstants.EINVAL) { + throw new IllegalArgumentException(sse); + } else if (sse.errorCode == OsConstants.EAGAIN) { + throw new IllegalStateException(sse); + } else if (sse.errorCode == OsConstants.EOPNOTSUPP) { + throw new UnsupportedOperationException(sse); + } + } + + /** + * Convert an Errno SSE to the correct Unchecked exception type. + * + * This method never actually returns. + */ + // package + static RuntimeException + rethrowUncheckedExceptionFromServiceSpecificException(ServiceSpecificException sse) { + maybeHandleServiceSpecificException(sse); + throw new RuntimeException(sse); + } + + /** + * Convert an Errno SSE to the correct Checked or Unchecked exception type. + * + * This method may throw IOException, or it may throw an unchecked exception; it will never + * actually return. + */ + // package + static IOException rethrowCheckedExceptionFromServiceSpecificException( + ServiceSpecificException sse) throws IOException { + // First see if this is an unchecked exception of a type we know. + // If so, then we prefer the unchecked (specific) type of exception. + maybeHandleServiceSpecificException(sse); + // If not, then all we can do is provide the SSE in the form of an IOException. + throw new ErrnoException( + "IpSec encountered errno=" + sse.errorCode, sse.errorCode).rethrowAsIOException(); + } } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index fb5f46c117..23c8aa368d 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -29,6 +29,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -137,6 +138,8 @@ public final class IpSecTransform implements AutoCloseable { mResourceId = result.resourceId; Log.d(TAG, "Added Transform with Id " + mResourceId); mCloseGuard.open("build"); + } catch (ServiceSpecificException e) { + throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } @@ -181,6 +184,10 @@ public final class IpSecTransform implements AutoCloseable { stopNattKeepalive(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); + } catch (Exception e) { + // On close we swallow all random exceptions since failure to close is not + // actionable by the user. + Log.e(TAG, "Failed to close " + this + ", Exception=" + e); } finally { mResourceId = INVALID_RESOURCE_ID; mCloseGuard.close(); @@ -507,4 +514,13 @@ public final class IpSecTransform implements AutoCloseable { mConfig = new IpSecConfig(); } } + + @Override + public String toString() { + return new StringBuilder() + .append("IpSecTransform{resourceId=") + .append(mResourceId) + .append("}") + .toString(); + } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 9709885887..60f1877d37 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1100,9 +1100,11 @@ public class IpSecService extends IIpSecService.Stub { new RefcountedResource( new SpiRecord(resourceId, "", destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { - // TODO: Add appropriate checks when other ServiceSpecificException types are supported - return new IpSecSpiResponse( - IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi); + if (e.errorCode == OsConstants.ENOENT) { + return new IpSecSpiResponse( + IpSecManager.Status.SPI_UNAVAILABLE, INVALID_RESOURCE_ID, spi); + } + throw e; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1114,7 +1116,6 @@ public class IpSecService extends IIpSecService.Stub { */ private void releaseResource(RefcountedResourceArray resArray, int resourceId) throws RemoteException { - resArray.getRefcountedResourceOrThrow(resourceId).userRelease(); } @@ -1314,15 +1315,12 @@ public class IpSecService extends IIpSecService.Stub { releaseNetId(ikey); releaseNetId(okey); throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception + } catch (Throwable t) { + // Release keys if we got an error. + releaseNetId(ikey); + releaseNetId(okey); + throw t; } - - // If we make it to here, then something has gone wrong and we couldn't create a VTI. - // Release the keys that we reserved, and return an error status. - releaseNetId(ikey); - releaseNetId(okey); - return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } /** @@ -1351,9 +1349,6 @@ public class IpSecService extends IIpSecService.Stub { localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. - throw new IllegalArgumentException(e); } } @@ -1383,9 +1378,6 @@ public class IpSecService extends IIpSecService.Stub { localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); - } catch (ServiceSpecificException e) { - // If we get here, one of the arguments provided was invalid. Wrap the SSE, and throw. - throw new IllegalArgumentException(e); } } @@ -1589,12 +1581,7 @@ public class IpSecService extends IIpSecService.Stub { dependencies.add(refcountedSpiRecord); SpiRecord spiRecord = refcountedSpiRecord.getResource(); - try { - createOrUpdateTransform(c, resourceId, spiRecord, socketRecord); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - return new IpSecTransformResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); - } + createOrUpdateTransform(c, resourceId, spiRecord, socketRecord); // SA was created successfully, time to construct a record and lock it away userRecord.mTransformRecords.put( @@ -1641,23 +1628,15 @@ public class IpSecService extends IIpSecService.Stub { c.getMode() == IpSecTransform.MODE_TRANSPORT, "Transform mode was not Transport mode; cannot be applied to a socket"); - try { - mSrvConfig - .getNetdInstance() - .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), - resourceId, - direction, - c.getSourceAddress(), - c.getDestinationAddress(), - info.getSpiRecord().getSpi()); - } catch (ServiceSpecificException e) { - if (e.errorCode == EINVAL) { - throw new IllegalArgumentException(e.toString()); - } else { - throw e; - } - } + mSrvConfig + .getNetdInstance() + .ipSecApplyTransportModeTransform( + socket.getFileDescriptor(), + resourceId, + direction, + c.getSourceAddress(), + c.getDestinationAddress(), + info.getSpiRecord().getSpi()); } /** @@ -1669,13 +1648,9 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) throws RemoteException { - try { - mSrvConfig - .getNetdInstance() - .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); - } catch (ServiceSpecificException e) { - // FIXME: get the error code and throw is at an IOException from Errno Exception - } + mSrvConfig + .getNetdInstance() + .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); } /** From c80723f01be2642eddb5c85dedd82c0c2eedb684 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 15 May 2018 19:18:38 -0700 Subject: [PATCH 198/881] Disable the AppOp Restriction for IpSec Tunnels This CL temporarily removes the AppOp restriction that disallows creation of IpSec tunnels due to the lack of the appropriate AppOp in AOSP/master. When the relevant framework merges out to master, this CL should be reverted. Bug: none Test: compilation Change-Id: Ic06c193f85f6bcdd0ead4238825c1add78703cde --- .../java/com/android/server/IpSecService.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 60f1877d37..744ed25f16 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1481,19 +1481,23 @@ public class IpSecService extends IIpSecService.Stub { } } + private static final String TUNNEL_OP = "STOPSHIP"; // = AppOpsManager.OP_MANAGE_IPSEC_TUNNELS; + private void enforceTunnelPermissions(String callingPackage) { checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); - switch (getAppOpsManager().noteOp( - AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, - Binder.getCallingUid(), callingPackage)) { - case AppOpsManager.MODE_DEFAULT: - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); - break; - case AppOpsManager.MODE_ALLOWED: - return; - default: - throw new SecurityException("Request to ignore AppOps for non-legacy API"); + if (false) { // STOPSHIP if this line is present + switch (getAppOpsManager().noteOp( + TUNNEL_OP, + Binder.getCallingUid(), callingPackage)) { + case AppOpsManager.MODE_DEFAULT: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); + break; + case AppOpsManager.MODE_ALLOWED: + return; + default: + throw new SecurityException("Request to ignore AppOps for non-legacy API"); + } } } From 4300caf11631f9f9470752ffc3cfa4fc014c6a37 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 15 May 2018 19:18:38 -0700 Subject: [PATCH 199/881] Disable the AppOp Restriction for IpSec Tunnels This CL temporarily removes the AppOp restriction that disallows creation of IpSec tunnels due to the lack of the appropriate AppOp in AOSP/master. When the relevant framework merges out to master, this CL should be reverted. Manually merging this due to skipping a merge conflict at ef9f2740a790feceaa47a24b1a179e93c4ffb5e6 Bug: none Test: compilation Change-Id: Ic06c193f85f6bcdd0ead4238825c1add78703cde --- .../java/com/android/server/IpSecService.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 60f1877d37..744ed25f16 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1481,19 +1481,23 @@ public class IpSecService extends IIpSecService.Stub { } } + private static final String TUNNEL_OP = "STOPSHIP"; // = AppOpsManager.OP_MANAGE_IPSEC_TUNNELS; + private void enforceTunnelPermissions(String callingPackage) { checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); - switch (getAppOpsManager().noteOp( - AppOpsManager.OP_MANAGE_IPSEC_TUNNELS, - Binder.getCallingUid(), callingPackage)) { - case AppOpsManager.MODE_DEFAULT: - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); - break; - case AppOpsManager.MODE_ALLOWED: - return; - default: - throw new SecurityException("Request to ignore AppOps for non-legacy API"); + if (false) { // STOPSHIP if this line is present + switch (getAppOpsManager().noteOp( + TUNNEL_OP, + Binder.getCallingUid(), callingPackage)) { + case AppOpsManager.MODE_DEFAULT: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); + break; + case AppOpsManager.MODE_ALLOWED: + return; + default: + throw new SecurityException("Request to ignore AppOps for non-legacy API"); + } } } From 334a7559650b4d630e18b405d0744c9e0254f0cd Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 25 Jun 2018 21:51:14 +0800 Subject: [PATCH 200/881] DO NOT MERGE: use legacy way to get tcp packet count The current networkStats getIfaceStats implementation check if bpf is enabled, and use bpf to get all traffic stats. However, the bpf implementation did not contain tcp packet counts. So data stall detection in DcTracker could not get the packet count to trigger data stall. Hence the data stall never triggers for device that enables bpf. This solution is for short term solution that rollback the design to use xt_qtaguid for bpf enabled device. Bug: 110443385 Test: 1. fake data stall to trigger data stall recovery 2. enable debug log to make sure tcp packet count is correct 3. runtest frameworks-net 4. run cts -m CtsUsageStatsTestCases Change-Id: I1ce9e92fe194da2ea0a3eec014fd50bb50cdd44a --- .../java/com/android/server/net/NetworkStatsService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index addc479404..fec510f28a 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -941,7 +941,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getIfaceStats(String iface, int type) { - return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + // eBPF code doesn't provide per-interface TCP counters. Use xt_qtaguid for now. + // TODO: delete getMobileTcp(Rx|Tx)Packets entirely. See b/110443385 . + if (type == TYPE_TCP_TX_PACKETS || type == TYPE_TCP_RX_PACKETS) { + return nativeGetIfaceStat(iface, type, false); + } else { + return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + } } @Override From 8352975df0299fd9c8a3e1bc056321750915c435 Mon Sep 17 00:00:00 2001 From: Neil Fuller Date: Tue, 3 Jul 2018 19:22:45 +0100 Subject: [PATCH 201/881] Track constructor changes in libcore/ The 2-arg constructor is being removed. Test: build / boot Bug: 111055375 Change-Id: I72413a8c7885f9514a88f59deb649fa755deff92 --- .../android/internal/net/NetworkStatsFactory.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 41802cc606..fb54e69400 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -192,7 +192,7 @@ public class NetworkStatsFactory { reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { - throw new ProtocolException("problem parsing stats", e); + throw protocolExceptionWithCause("problem parsing stats", e); } finally { IoUtils.closeQuietly(reader); StrictMode.setThreadPolicy(savedPolicy); @@ -242,7 +242,7 @@ public class NetworkStatsFactory { reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { - throw new ProtocolException("problem parsing stats", e); + throw protocolExceptionWithCause("problem parsing stats", e); } finally { IoUtils.closeQuietly(reader); StrictMode.setThreadPolicy(savedPolicy); @@ -339,7 +339,7 @@ public class NetworkStatsFactory { reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { - throw new ProtocolException("problem parsing idx " + idx, e); + throw protocolExceptionWithCause("problem parsing idx " + idx, e); } finally { IoUtils.closeQuietly(reader); StrictMode.setThreadPolicy(savedPolicy); @@ -376,4 +376,10 @@ public class NetworkStatsFactory { @VisibleForTesting public static native int nativeReadNetworkStatsDev(NetworkStats stats); + + private static ProtocolException protocolExceptionWithCause(String message, Throwable cause) { + ProtocolException pe = new ProtocolException(message); + pe.initCause(cause); + return pe; + } } From b02b6403f967af2d8f26d3025b291f4d9a9170ce Mon Sep 17 00:00:00 2001 From: kopriva Date: Mon, 23 Jul 2018 18:19:39 -0700 Subject: [PATCH 202/881] docs: added Android P behavior change note to untagSocket reference staged here: https://android-dot-devsite.googleplex.com/reference/android/net/TrafficStats#untagSocket(java.net.Socket) Test: make ds-docs Exempt-From-Owner-Approval: Docs-only change Bug: 110484513 Change-Id: I24575e6f4451a019b60c5bf60e17e14a928c6cc3 --- core/java/android/net/TrafficStats.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 40d53b741d..f033268698 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -329,6 +329,14 @@ public class TrafficStats { /** * Remove any statistics parameters from the given {@link Socket}. + *

+ * In Android 8.1 (API level 27) and lower, a socket is automatically + * untagged when it's sent to another process using binder IPC with a + * {@code ParcelFileDescriptor} container. In Android 9.0 (API level 28) + * and higher, the socket tag is kept when the socket is sent to another + * process using binder IPC. You can mimic the previous behavior by + * calling {@code untagSocket()} before sending the socket to another + * process. */ public static void untagSocket(Socket socket) throws SocketException { SocketTagger.get().untag(socket); From c84693ee4e1a045b027020cd0b0c2608f77a7c47 Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Mon, 23 Jul 2018 13:08:30 -0700 Subject: [PATCH 203/881] Migrate frameworks/base/services/tests/servicestests to androidx.test See go/jetpack-test-android-migration cherrypicked from ag/4608401 Test: atest FrameworksServicesTests Change-Id: I2d9641c681489135aa3167bb4c9b1296a1a6a4f7 --- .../src/com/android/server/net/IpConfigStoreTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java index 9f4b754621..7767a2810a 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -27,9 +27,10 @@ import android.net.LinkAddress; import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; -import android.support.test.runner.AndroidJUnit4; import android.util.ArrayMap; +import androidx.test.runner.AndroidJUnit4; + import org.junit.Test; import org.junit.runner.RunWith; From d5f95cda0740599f474b22460573dcd9bc054b8c Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 26 Apr 2018 17:52:03 +0900 Subject: [PATCH 204/881] Fix testRegisterUsageCallback failure in setUp LocalServices.addService in NetworkStatsService is currently failing with IllegalStateException "Overriding service registration". Setting up LocalServices in the test to avoid this issue might be possible, but moving the registration to the only non-test caller of that constructor as done here solves the issue and avoids side-effects from a constructor. Test: atest FrameworksNetTests does not choke on this test Bug: b/78487385 Bug: b/80082746 Change-Id: I5dba98fc79aec0800c8b71e6c7e23d1cfbcae852 Merged-In: I884a7a8bd7db3fcd220b785ba9914ac8c77720f0 (Clean cherry-pick of go/ag/4061255) --- .../java/com/android/server/net/NetworkStatsService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index aba75ddb45..60e9eaab57 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -324,6 +324,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { wakeLock, getDefaultClock(), TelephonyManager.getDefault(), new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); + service.registerLocalService(); HandlerThread handlerThread = new HandlerThread(TAG); Handler.Callback callback = new HandlerCallback(service); @@ -333,6 +334,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return service; } + // This must not be called outside of tests, even within the same package, as this constructor + // does not register the local service. Use the create() helper above. @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, @@ -349,7 +352,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSystemDir = checkNotNull(systemDir, "missing systemDir"); mBaseDir = checkNotNull(baseDir, "missing baseDir"); mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); + } + private void registerLocalService() { LocalServices.addService(NetworkStatsManagerInternal.class, new NetworkStatsManagerInternalImpl()); } From af185b2266f5506ab8dcd5545cb252c25687dc47 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 14 Aug 2018 14:17:44 +0100 Subject: [PATCH 205/881] Add @UnsupportedAppUsage annotations For packages: android.app.usage android.app.trust android.app.timezonedetector android.app.timezone android.app.timedetector android.app.job android.app.backup android.app.assist android.app.admin android.app This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: I618c5dc4462ae990d9df45c3e9ed3f092cc5138c --- core/java/android/app/usage/NetworkStatsManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 9f46f207d6..59ae3347f4 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; import android.annotation.SystemService; import android.annotation.TestApi; +import android.annotation.UnsupportedAppUsage; import android.app.usage.NetworkStats.Bucket; import android.content.Context; import android.net.ConnectivityManager; @@ -121,6 +122,7 @@ public class NetworkStatsManager { /** * {@hide} */ + @UnsupportedAppUsage public NetworkStatsManager(Context context) throws ServiceNotFoundException { this(context, INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); From 3e0fe9f02ee99ac85e4fd8f386a6b7564fdd66bf Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 14 Aug 2018 14:25:44 +0100 Subject: [PATCH 206/881] Add @UnsupportedAppUsage annotations For packages: android.app.usage android.app.trust android.app.timezonedetector android.app.timezone android.app.timedetector android.app.job android.app.backup android.app.assist android.app.admin android.app This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: I5d15d50344d7178617418846917f693cfabf006b Merged-In: I618c5dc4462ae990d9df45c3e9ed3f092cc5138c --- core/java/android/app/usage/NetworkStatsManager.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 9f46f207d6..59ae3347f4 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; import android.annotation.SystemService; import android.annotation.TestApi; +import android.annotation.UnsupportedAppUsage; import android.app.usage.NetworkStats.Bucket; import android.content.Context; import android.net.ConnectivityManager; @@ -121,6 +122,7 @@ public class NetworkStatsManager { /** * {@hide} */ + @UnsupportedAppUsage public NetworkStatsManager(Context context) throws ServiceNotFoundException { this(context, INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); From e93928d758dd3c347c429ee9330e2ec1eb23fade Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Wed, 8 Aug 2018 14:44:44 +0100 Subject: [PATCH 207/881] Add @UnsupportedAppUsage annotations For packages: android.net.wimax android.net.wifi.p2p.nsd android.net.wifi.p2p android.net.wifi.hotspot2.pps android.net.wifi.hotspot2.omadm android.net.wifi.hotspot2 android.net.wifi.aware android.net.wifi android.net.util android.net.sip android.net.rtp android.net.nsd android.net.metrics android.net.lowpan android.net.http android.net.captiveportal android.net This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: I520be7a4c79e68310c12e4f55bf66acaa94145a1 --- core/java/android/net/EthernetManager.java | 9 +++++ core/java/android/net/NetworkStats.java | 36 +++++++++++++++++++ .../java/android/net/NetworkStatsHistory.java | 18 ++++++++++ core/java/android/net/NetworkTemplate.java | 11 ++++++ core/java/android/net/TrafficStats.java | 7 ++++ core/java/android/net/nsd/NsdServiceInfo.java | 2 ++ 6 files changed, 83 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index ecccda588a..72565024d3 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.SystemService; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Handler; import android.os.Message; @@ -66,6 +67,7 @@ public class EthernetManager { * @param iface Ethernet interface name * @param isAvailable {@code true} if Ethernet port exists. */ + @UnsupportedAppUsage void onAvailabilityChanged(String iface, boolean isAvailable); } @@ -84,6 +86,7 @@ public class EthernetManager { * Get Ethernet configuration. * @return the Ethernet Configuration, contained in {@link IpConfiguration}. */ + @UnsupportedAppUsage public IpConfiguration getConfiguration(String iface) { try { return mService.getConfiguration(iface); @@ -95,6 +98,7 @@ public class EthernetManager { /** * Set Ethernet configuration. */ + @UnsupportedAppUsage public void setConfiguration(String iface, IpConfiguration config) { try { mService.setConfiguration(iface, config); @@ -106,6 +110,7 @@ public class EthernetManager { /** * Indicates whether the system currently has one or more Ethernet interfaces. */ + @UnsupportedAppUsage public boolean isAvailable() { return getAvailableInterfaces().length > 0; } @@ -115,6 +120,7 @@ public class EthernetManager { * * @param iface Ethernet interface name */ + @UnsupportedAppUsage public boolean isAvailable(String iface) { try { return mService.isAvailable(iface); @@ -128,6 +134,7 @@ public class EthernetManager { * @param listener A {@link Listener} to add. * @throws IllegalArgumentException If the listener is null. */ + @UnsupportedAppUsage public void addListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); @@ -145,6 +152,7 @@ public class EthernetManager { /** * Returns an array of available Ethernet interface names. */ + @UnsupportedAppUsage public String[] getAvailableInterfaces() { try { return mService.getAvailableInterfaces(); @@ -158,6 +166,7 @@ public class EthernetManager { * @param listener A {@link Listener} to remove. * @throws IllegalArgumentException If the listener is null. */ + @UnsupportedAppUsage public void removeListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index edf9bc1c6b..e270fc2e39 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -110,25 +111,43 @@ public class NetworkStats implements Parcelable { * generated. */ private long elapsedRealtime; + @UnsupportedAppUsage private int size; + @UnsupportedAppUsage private int capacity; + @UnsupportedAppUsage private String[] iface; + @UnsupportedAppUsage private int[] uid; + @UnsupportedAppUsage private int[] set; + @UnsupportedAppUsage private int[] tag; + @UnsupportedAppUsage private int[] metered; + @UnsupportedAppUsage private int[] roaming; + @UnsupportedAppUsage private int[] defaultNetwork; + @UnsupportedAppUsage private long[] rxBytes; + @UnsupportedAppUsage private long[] rxPackets; + @UnsupportedAppUsage private long[] txBytes; + @UnsupportedAppUsage private long[] txPackets; + @UnsupportedAppUsage private long[] operations; public static class Entry { + @UnsupportedAppUsage public String iface; + @UnsupportedAppUsage public int uid; + @UnsupportedAppUsage public int set; + @UnsupportedAppUsage public int tag; /** * Note that this is only populated w/ the default value when read from /proc or written @@ -148,12 +167,17 @@ public class NetworkStats implements Parcelable { * getSummary(). */ public int defaultNetwork; + @UnsupportedAppUsage public long rxBytes; + @UnsupportedAppUsage public long rxPackets; + @UnsupportedAppUsage public long txBytes; + @UnsupportedAppUsage public long txPackets; public long operations; + @UnsupportedAppUsage public Entry() { this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); } @@ -240,6 +264,7 @@ public class NetworkStats implements Parcelable { } } + @UnsupportedAppUsage public NetworkStats(long elapsedRealtime, int initialSize) { this.elapsedRealtime = elapsedRealtime; this.size = 0; @@ -263,6 +288,7 @@ public class NetworkStats implements Parcelable { } } + @UnsupportedAppUsage public NetworkStats(Parcel parcel) { elapsedRealtime = parcel.readLong(); size = parcel.readInt(); @@ -399,6 +425,7 @@ public class NetworkStats implements Parcelable { /** * Return specific stats entry. */ + @UnsupportedAppUsage public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.iface = iface[i]; @@ -432,6 +459,7 @@ public class NetworkStats implements Parcelable { return SystemClock.elapsedRealtime() - elapsedRealtime; } + @UnsupportedAppUsage public int size() { return size; } @@ -460,6 +488,7 @@ public class NetworkStats implements Parcelable { * {@link #findIndex(String, int, int, int, int)} is unable to find match. Can * also be used to subtract values from existing rows. */ + @UnsupportedAppUsage public NetworkStats combineValues(Entry entry) { final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, entry.roaming, entry.defaultNetwork); @@ -479,6 +508,7 @@ public class NetworkStats implements Parcelable { /** * Combine all values from another {@link NetworkStats} into this object. */ + @UnsupportedAppUsage public void combineAllValues(NetworkStats another) { NetworkStats.Entry entry = null; for (int i = 0; i < another.size; i++) { @@ -564,6 +594,7 @@ public class NetworkStats implements Parcelable { /** * Return list of unique UIDs known by this data structure. */ + @UnsupportedAppUsage public int[] getUniqueUids() { final SparseBooleanArray uids = new SparseBooleanArray(); for (int uid : this.uid) { @@ -582,6 +613,7 @@ public class NetworkStats implements Parcelable { * Return total bytes represented by this snapshot object, usually used when * checking if a {@link #subtract(NetworkStats)} delta passes a threshold. */ + @UnsupportedAppUsage public long getTotalBytes() { final Entry entry = getTotal(null); return entry.rxBytes + entry.txBytes; @@ -590,6 +622,7 @@ public class NetworkStats implements Parcelable { /** * Return total of all fields represented by this snapshot object. */ + @UnsupportedAppUsage public Entry getTotal(Entry recycle) { return getTotal(recycle, null, UID_ALL, false); } @@ -598,6 +631,7 @@ public class NetworkStats implements Parcelable { * Return total of all fields represented by this snapshot object matching * the requested {@link #uid}. */ + @UnsupportedAppUsage public Entry getTotal(Entry recycle, int limitUid) { return getTotal(recycle, null, limitUid, false); } @@ -610,6 +644,7 @@ public class NetworkStats implements Parcelable { return getTotal(recycle, limitIface, UID_ALL, false); } + @UnsupportedAppUsage public Entry getTotalIncludingTags(Entry recycle) { return getTotal(recycle, null, UID_ALL, true); } @@ -1085,6 +1120,7 @@ public class NetworkStats implements Parcelable { return 0; } + @UnsupportedAppUsage public static final Creator CREATOR = new Creator() { @Override public NetworkStats createFromParcel(Parcel in) { diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index a13ad659e7..d53e0326ae 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -30,6 +30,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; @@ -89,16 +90,23 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; + @UnsupportedAppUsage public long bucketDuration; + @UnsupportedAppUsage public long bucketStart; public long activeTime; + @UnsupportedAppUsage public long rxBytes; + @UnsupportedAppUsage public long rxPackets; + @UnsupportedAppUsage public long txBytes; + @UnsupportedAppUsage public long txPackets; public long operations; } + @UnsupportedAppUsage public NetworkStatsHistory(long bucketDuration) { this(bucketDuration, 10, FIELD_ALL); } @@ -125,6 +133,7 @@ public class NetworkStatsHistory implements Parcelable { recordEntireHistory(existing); } + @UnsupportedAppUsage public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); @@ -210,6 +219,7 @@ public class NetworkStatsHistory implements Parcelable { return 0; } + @UnsupportedAppUsage public int size() { return bucketCount; } @@ -218,6 +228,7 @@ public class NetworkStatsHistory implements Parcelable { return bucketDuration; } + @UnsupportedAppUsage public long getStart() { if (bucketCount > 0) { return bucketStart[0]; @@ -226,6 +237,7 @@ public class NetworkStatsHistory implements Parcelable { } } + @UnsupportedAppUsage public long getEnd() { if (bucketCount > 0) { return bucketStart[bucketCount - 1] + bucketDuration; @@ -245,6 +257,7 @@ public class NetworkStatsHistory implements Parcelable { * Return index of bucket that contains or is immediately before the * requested time. */ + @UnsupportedAppUsage public int getIndexBefore(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); if (index < 0) { @@ -272,6 +285,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. */ + @UnsupportedAppUsage public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; @@ -373,6 +387,7 @@ public class NetworkStatsHistory implements Parcelable { * Record an entire {@link NetworkStatsHistory} into this history. Usually * for combining together stats for external reporting. */ + @UnsupportedAppUsage public void recordEntireHistory(NetworkStatsHistory input) { recordHistory(input, Long.MIN_VALUE, Long.MAX_VALUE); } @@ -509,6 +524,7 @@ public class NetworkStatsHistory implements Parcelable { * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. */ + @UnsupportedAppUsage public Entry getValues(long start, long end, Entry recycle) { return getValues(start, end, Long.MAX_VALUE, recycle); } @@ -517,6 +533,7 @@ public class NetworkStatsHistory implements Parcelable { * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. */ + @UnsupportedAppUsage public Entry getValues(long start, long end, long now, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketDuration = end - start; @@ -701,6 +718,7 @@ public class NetworkStatsHistory implements Parcelable { return writer.toString(); } + @UnsupportedAppUsage public static final Creator CREATOR = new Creator() { @Override public NetworkStatsHistory createFromParcel(Parcel in) { diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 74233fd990..bb75c63436 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,6 +34,7 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.removeDoubleQuotes; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.util.BackupUtils; @@ -96,6 +97,7 @@ public class NetworkTemplate implements Parcelable { * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with * the given IMSI. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateMobileAll(String subscriberId) { return new NetworkTemplate(MATCH_MOBILE, subscriberId, null); } @@ -104,6 +106,7 @@ public class NetworkTemplate implements Parcelable { * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateMobileWildcard() { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); } @@ -112,11 +115,13 @@ public class NetworkTemplate implements Parcelable { * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks, * regardless of SSID. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateWifiWildcard() { return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null); } @Deprecated + @UnsupportedAppUsage public static NetworkTemplate buildTemplateWifi() { return buildTemplateWifiWildcard(); } @@ -133,6 +138,7 @@ public class NetworkTemplate implements Parcelable { * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style * networks together. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateEthernet() { return new NetworkTemplate(MATCH_ETHERNET, null, null); } @@ -173,6 +179,7 @@ public class NetworkTemplate implements Parcelable { private final int mRoaming; private final int mDefaultNetwork; + @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); } @@ -293,10 +300,12 @@ public class NetworkTemplate implements Parcelable { } } + @UnsupportedAppUsage public int getMatchRule() { return mMatchRule; } + @UnsupportedAppUsage public String getSubscriberId() { return mSubscriberId; } @@ -460,6 +469,7 @@ public class NetworkTemplate implements Parcelable { * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. */ + @UnsupportedAppUsage public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) { // Requested template subscriber is part of the merge group; return @@ -471,6 +481,7 @@ public class NetworkTemplate implements Parcelable { } } + @UnsupportedAppUsage public static final Creator CREATOR = new Creator() { @Override public NetworkTemplate createFromParcel(Parcel in) { diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index f033268698..a463afa2e1 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -19,6 +19,7 @@ package android.net; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; +import android.annotation.UnsupportedAppUsage; import android.app.DownloadManager; import android.app.backup.BackupManager; import android.app.usage.NetworkStatsManager; @@ -141,6 +142,7 @@ public class TrafficStats { private static INetworkStatsService sStatsService; + @UnsupportedAppUsage private synchronized static INetworkStatsService getStatsService() { if (sStatsService == null) { sStatsService = INetworkStatsService.Stub.asInterface( @@ -536,6 +538,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -551,6 +554,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -584,6 +588,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getTxBytes(String iface) { try { return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES); @@ -593,6 +598,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getRxBytes(String iface) { try { return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES); @@ -948,6 +954,7 @@ public class TrafficStats { * Interfaces are never removed from this list, so counters should always be * monotonic. */ + @UnsupportedAppUsage private static String[] getMobileIfaces() { try { return getStatsService().getMobileIfaces(); diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java index bccaf60e69..9ba17edfb9 100644 --- a/core/java/android/net/nsd/NsdServiceInfo.java +++ b/core/java/android/net/nsd/NsdServiceInfo.java @@ -17,6 +17,7 @@ package android.net.nsd; import android.annotation.NonNull; +import android.annotation.UnsupportedAppUsage; import android.os.Parcelable; import android.os.Parcel; import android.text.TextUtils; @@ -185,6 +186,7 @@ public final class NsdServiceInfo implements Parcelable { } /** @hide */ + @UnsupportedAppUsage public void setAttribute(String key, byte[] value) { if (TextUtils.isEmpty(key)) { throw new IllegalArgumentException("Key cannot be empty"); From 05f61129dc8b28288e3b5404964d6e36315333a9 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Wed, 8 Aug 2018 14:52:47 +0100 Subject: [PATCH 208/881] Add @UnsupportedAppUsage annotations For packages: android.net.wimax android.net.wifi.p2p.nsd android.net.wifi.p2p android.net.wifi.hotspot2.pps android.net.wifi.hotspot2.omadm android.net.wifi.hotspot2 android.net.wifi.aware android.net.wifi android.net.util android.net.sip android.net.rtp android.net.nsd android.net.metrics android.net.lowpan android.net.http android.net.captiveportal android.net This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: Ie25423113ee1a8071cd5039382c00de6ce0af7fd Merged-In: I520be7a4c79e68310c12e4f55bf66acaa94145a1 --- core/java/android/net/EthernetManager.java | 9 +++++ core/java/android/net/NetworkStats.java | 36 +++++++++++++++++++ .../java/android/net/NetworkStatsHistory.java | 18 ++++++++++ core/java/android/net/NetworkTemplate.java | 11 ++++++ core/java/android/net/TrafficStats.java | 7 ++++ core/java/android/net/nsd/NsdServiceInfo.java | 2 ++ 6 files changed, 83 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index ecccda588a..72565024d3 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.SystemService; +import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Handler; import android.os.Message; @@ -66,6 +67,7 @@ public class EthernetManager { * @param iface Ethernet interface name * @param isAvailable {@code true} if Ethernet port exists. */ + @UnsupportedAppUsage void onAvailabilityChanged(String iface, boolean isAvailable); } @@ -84,6 +86,7 @@ public class EthernetManager { * Get Ethernet configuration. * @return the Ethernet Configuration, contained in {@link IpConfiguration}. */ + @UnsupportedAppUsage public IpConfiguration getConfiguration(String iface) { try { return mService.getConfiguration(iface); @@ -95,6 +98,7 @@ public class EthernetManager { /** * Set Ethernet configuration. */ + @UnsupportedAppUsage public void setConfiguration(String iface, IpConfiguration config) { try { mService.setConfiguration(iface, config); @@ -106,6 +110,7 @@ public class EthernetManager { /** * Indicates whether the system currently has one or more Ethernet interfaces. */ + @UnsupportedAppUsage public boolean isAvailable() { return getAvailableInterfaces().length > 0; } @@ -115,6 +120,7 @@ public class EthernetManager { * * @param iface Ethernet interface name */ + @UnsupportedAppUsage public boolean isAvailable(String iface) { try { return mService.isAvailable(iface); @@ -128,6 +134,7 @@ public class EthernetManager { * @param listener A {@link Listener} to add. * @throws IllegalArgumentException If the listener is null. */ + @UnsupportedAppUsage public void addListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); @@ -145,6 +152,7 @@ public class EthernetManager { /** * Returns an array of available Ethernet interface names. */ + @UnsupportedAppUsage public String[] getAvailableInterfaces() { try { return mService.getAvailableInterfaces(); @@ -158,6 +166,7 @@ public class EthernetManager { * @param listener A {@link Listener} to remove. * @throws IllegalArgumentException If the listener is null. */ + @UnsupportedAppUsage public void removeListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index edf9bc1c6b..e270fc2e39 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -110,25 +111,43 @@ public class NetworkStats implements Parcelable { * generated. */ private long elapsedRealtime; + @UnsupportedAppUsage private int size; + @UnsupportedAppUsage private int capacity; + @UnsupportedAppUsage private String[] iface; + @UnsupportedAppUsage private int[] uid; + @UnsupportedAppUsage private int[] set; + @UnsupportedAppUsage private int[] tag; + @UnsupportedAppUsage private int[] metered; + @UnsupportedAppUsage private int[] roaming; + @UnsupportedAppUsage private int[] defaultNetwork; + @UnsupportedAppUsage private long[] rxBytes; + @UnsupportedAppUsage private long[] rxPackets; + @UnsupportedAppUsage private long[] txBytes; + @UnsupportedAppUsage private long[] txPackets; + @UnsupportedAppUsage private long[] operations; public static class Entry { + @UnsupportedAppUsage public String iface; + @UnsupportedAppUsage public int uid; + @UnsupportedAppUsage public int set; + @UnsupportedAppUsage public int tag; /** * Note that this is only populated w/ the default value when read from /proc or written @@ -148,12 +167,17 @@ public class NetworkStats implements Parcelable { * getSummary(). */ public int defaultNetwork; + @UnsupportedAppUsage public long rxBytes; + @UnsupportedAppUsage public long rxPackets; + @UnsupportedAppUsage public long txBytes; + @UnsupportedAppUsage public long txPackets; public long operations; + @UnsupportedAppUsage public Entry() { this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); } @@ -240,6 +264,7 @@ public class NetworkStats implements Parcelable { } } + @UnsupportedAppUsage public NetworkStats(long elapsedRealtime, int initialSize) { this.elapsedRealtime = elapsedRealtime; this.size = 0; @@ -263,6 +288,7 @@ public class NetworkStats implements Parcelable { } } + @UnsupportedAppUsage public NetworkStats(Parcel parcel) { elapsedRealtime = parcel.readLong(); size = parcel.readInt(); @@ -399,6 +425,7 @@ public class NetworkStats implements Parcelable { /** * Return specific stats entry. */ + @UnsupportedAppUsage public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.iface = iface[i]; @@ -432,6 +459,7 @@ public class NetworkStats implements Parcelable { return SystemClock.elapsedRealtime() - elapsedRealtime; } + @UnsupportedAppUsage public int size() { return size; } @@ -460,6 +488,7 @@ public class NetworkStats implements Parcelable { * {@link #findIndex(String, int, int, int, int)} is unable to find match. Can * also be used to subtract values from existing rows. */ + @UnsupportedAppUsage public NetworkStats combineValues(Entry entry) { final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, entry.roaming, entry.defaultNetwork); @@ -479,6 +508,7 @@ public class NetworkStats implements Parcelable { /** * Combine all values from another {@link NetworkStats} into this object. */ + @UnsupportedAppUsage public void combineAllValues(NetworkStats another) { NetworkStats.Entry entry = null; for (int i = 0; i < another.size; i++) { @@ -564,6 +594,7 @@ public class NetworkStats implements Parcelable { /** * Return list of unique UIDs known by this data structure. */ + @UnsupportedAppUsage public int[] getUniqueUids() { final SparseBooleanArray uids = new SparseBooleanArray(); for (int uid : this.uid) { @@ -582,6 +613,7 @@ public class NetworkStats implements Parcelable { * Return total bytes represented by this snapshot object, usually used when * checking if a {@link #subtract(NetworkStats)} delta passes a threshold. */ + @UnsupportedAppUsage public long getTotalBytes() { final Entry entry = getTotal(null); return entry.rxBytes + entry.txBytes; @@ -590,6 +622,7 @@ public class NetworkStats implements Parcelable { /** * Return total of all fields represented by this snapshot object. */ + @UnsupportedAppUsage public Entry getTotal(Entry recycle) { return getTotal(recycle, null, UID_ALL, false); } @@ -598,6 +631,7 @@ public class NetworkStats implements Parcelable { * Return total of all fields represented by this snapshot object matching * the requested {@link #uid}. */ + @UnsupportedAppUsage public Entry getTotal(Entry recycle, int limitUid) { return getTotal(recycle, null, limitUid, false); } @@ -610,6 +644,7 @@ public class NetworkStats implements Parcelable { return getTotal(recycle, limitIface, UID_ALL, false); } + @UnsupportedAppUsage public Entry getTotalIncludingTags(Entry recycle) { return getTotal(recycle, null, UID_ALL, true); } @@ -1085,6 +1120,7 @@ public class NetworkStats implements Parcelable { return 0; } + @UnsupportedAppUsage public static final Creator CREATOR = new Creator() { @Override public NetworkStats createFromParcel(Parcel in) { diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index a13ad659e7..d53e0326ae 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -30,6 +30,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; @@ -89,16 +90,23 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; + @UnsupportedAppUsage public long bucketDuration; + @UnsupportedAppUsage public long bucketStart; public long activeTime; + @UnsupportedAppUsage public long rxBytes; + @UnsupportedAppUsage public long rxPackets; + @UnsupportedAppUsage public long txBytes; + @UnsupportedAppUsage public long txPackets; public long operations; } + @UnsupportedAppUsage public NetworkStatsHistory(long bucketDuration) { this(bucketDuration, 10, FIELD_ALL); } @@ -125,6 +133,7 @@ public class NetworkStatsHistory implements Parcelable { recordEntireHistory(existing); } + @UnsupportedAppUsage public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); @@ -210,6 +219,7 @@ public class NetworkStatsHistory implements Parcelable { return 0; } + @UnsupportedAppUsage public int size() { return bucketCount; } @@ -218,6 +228,7 @@ public class NetworkStatsHistory implements Parcelable { return bucketDuration; } + @UnsupportedAppUsage public long getStart() { if (bucketCount > 0) { return bucketStart[0]; @@ -226,6 +237,7 @@ public class NetworkStatsHistory implements Parcelable { } } + @UnsupportedAppUsage public long getEnd() { if (bucketCount > 0) { return bucketStart[bucketCount - 1] + bucketDuration; @@ -245,6 +257,7 @@ public class NetworkStatsHistory implements Parcelable { * Return index of bucket that contains or is immediately before the * requested time. */ + @UnsupportedAppUsage public int getIndexBefore(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); if (index < 0) { @@ -272,6 +285,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. */ + @UnsupportedAppUsage public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; @@ -373,6 +387,7 @@ public class NetworkStatsHistory implements Parcelable { * Record an entire {@link NetworkStatsHistory} into this history. Usually * for combining together stats for external reporting. */ + @UnsupportedAppUsage public void recordEntireHistory(NetworkStatsHistory input) { recordHistory(input, Long.MIN_VALUE, Long.MAX_VALUE); } @@ -509,6 +524,7 @@ public class NetworkStatsHistory implements Parcelable { * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. */ + @UnsupportedAppUsage public Entry getValues(long start, long end, Entry recycle) { return getValues(start, end, Long.MAX_VALUE, recycle); } @@ -517,6 +533,7 @@ public class NetworkStatsHistory implements Parcelable { * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. */ + @UnsupportedAppUsage public Entry getValues(long start, long end, long now, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketDuration = end - start; @@ -701,6 +718,7 @@ public class NetworkStatsHistory implements Parcelable { return writer.toString(); } + @UnsupportedAppUsage public static final Creator CREATOR = new Creator() { @Override public NetworkStatsHistory createFromParcel(Parcel in) { diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 74233fd990..bb75c63436 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,6 +34,7 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.removeDoubleQuotes; +import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.util.BackupUtils; @@ -96,6 +97,7 @@ public class NetworkTemplate implements Parcelable { * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with * the given IMSI. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateMobileAll(String subscriberId) { return new NetworkTemplate(MATCH_MOBILE, subscriberId, null); } @@ -104,6 +106,7 @@ public class NetworkTemplate implements Parcelable { * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateMobileWildcard() { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); } @@ -112,11 +115,13 @@ public class NetworkTemplate implements Parcelable { * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks, * regardless of SSID. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateWifiWildcard() { return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null); } @Deprecated + @UnsupportedAppUsage public static NetworkTemplate buildTemplateWifi() { return buildTemplateWifiWildcard(); } @@ -133,6 +138,7 @@ public class NetworkTemplate implements Parcelable { * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style * networks together. */ + @UnsupportedAppUsage public static NetworkTemplate buildTemplateEthernet() { return new NetworkTemplate(MATCH_ETHERNET, null, null); } @@ -173,6 +179,7 @@ public class NetworkTemplate implements Parcelable { private final int mRoaming; private final int mDefaultNetwork; + @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); } @@ -293,10 +300,12 @@ public class NetworkTemplate implements Parcelable { } } + @UnsupportedAppUsage public int getMatchRule() { return mMatchRule; } + @UnsupportedAppUsage public String getSubscriberId() { return mSubscriberId; } @@ -460,6 +469,7 @@ public class NetworkTemplate implements Parcelable { * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. */ + @UnsupportedAppUsage public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) { // Requested template subscriber is part of the merge group; return @@ -471,6 +481,7 @@ public class NetworkTemplate implements Parcelable { } } + @UnsupportedAppUsage public static final Creator CREATOR = new Creator() { @Override public NetworkTemplate createFromParcel(Parcel in) { diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 40d53b741d..44f7e48eda 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -19,6 +19,7 @@ package android.net; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; +import android.annotation.UnsupportedAppUsage; import android.app.DownloadManager; import android.app.backup.BackupManager; import android.app.usage.NetworkStatsManager; @@ -141,6 +142,7 @@ public class TrafficStats { private static INetworkStatsService sStatsService; + @UnsupportedAppUsage private synchronized static INetworkStatsService getStatsService() { if (sStatsService == null) { sStatsService = INetworkStatsService.Stub.asInterface( @@ -528,6 +530,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -543,6 +546,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -576,6 +580,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getTxBytes(String iface) { try { return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES); @@ -585,6 +590,7 @@ public class TrafficStats { } /** {@hide} */ + @UnsupportedAppUsage public static long getRxBytes(String iface) { try { return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES); @@ -940,6 +946,7 @@ public class TrafficStats { * Interfaces are never removed from this list, so counters should always be * monotonic. */ + @UnsupportedAppUsage private static String[] getMobileIfaces() { try { return getStatsService().getMobileIfaces(); diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java index bccaf60e69..9ba17edfb9 100644 --- a/core/java/android/net/nsd/NsdServiceInfo.java +++ b/core/java/android/net/nsd/NsdServiceInfo.java @@ -17,6 +17,7 @@ package android.net.nsd; import android.annotation.NonNull; +import android.annotation.UnsupportedAppUsage; import android.os.Parcelable; import android.os.Parcel; import android.text.TextUtils; @@ -185,6 +186,7 @@ public final class NsdServiceInfo implements Parcelable { } /** @hide */ + @UnsupportedAppUsage public void setAttribute(String key, byte[] value) { if (TextUtils.isEmpty(key)) { throw new IllegalArgumentException("Key cannot be empty"); From 07be1cb5692019b0fbcb01084d1083e47087b2d1 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 16 Aug 2018 21:47:56 -0700 Subject: [PATCH 209/881] Convert frameworks/opt/net/ethernet to Android.bp See build/soong/README.md for more information. Test: m checkbuild Test: atest EthernetServiceTests Change-Id: Ic9243ae7719a25a8749d63a5dcac7ec5adffe303 --- Android.mk | 32 -------------------------------- tests/ethernet/Android.bp | 33 +++++++++++++++++++++++++++++++++ tests/ethernet/Android.mk | 36 ------------------------------------ 3 files changed, 33 insertions(+), 68 deletions(-) delete mode 100644 Android.mk create mode 100644 tests/ethernet/Android.bp delete mode 100644 tests/ethernet/Android.mk diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 952fa9d652..0000000000 --- a/Android.mk +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright (C) 2014 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) - -# Build the java code -# ============================================================ - -include $(CLEAR_VARS) - -LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/java -LOCAL_SRC_FILES := $(call all-java-files-under, java) \ - $(call all-Iaidl-files-under, java) \ - $(call all-logtags-files-under, java) - -LOCAL_JAVA_LIBRARIES := services -LOCAL_MODULE := ethernet-service - -include $(BUILD_JAVA_LIBRARY) - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp new file mode 100644 index 0000000000..8c5df21dae --- /dev/null +++ b/tests/ethernet/Android.bp @@ -0,0 +1,33 @@ +// Copyright (C) 2018 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +android_test { + name: "EthernetServiceTests", + + srcs: ["java/**/*.java"], + + certificate: "platform", + platform_apis: true, + + libs: [ + "android.test.runner", + "android.test.base", + ], + + static_libs: [ + "android-support-test", + "ethernet-service", + ], +} diff --git a/tests/ethernet/Android.mk b/tests/ethernet/Android.mk deleted file mode 100644 index 6b2c103474..0000000000 --- a/tests/ethernet/Android.mk +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright (C) 2018 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES := $(call all-java-files-under, java) - -LOCAL_PACKAGE_NAME := EthernetServiceTests - -LOCAL_CERTIFICATE := platform -LOCAL_PRIVATE_PLATFORM_APIS := true - -LOCAL_MODULE_TAGS := tests - -LOCAL_JAVA_LIBRARIES := \ - android.test.runner \ - android.test.base - -LOCAL_STATIC_JAVA_LIBRARIES := \ - android-support-test \ - ethernet-service - -include $(BUILD_PACKAGE) From bca6efabbad5c9f648c443b5115e678499d4d82d Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 21 Aug 2018 18:18:41 +0900 Subject: [PATCH 210/881] Tiny tiny style fix Test: none needed Change-Id: Ic6cfedf9cfe60984ce7fbd59bdaec55b0bba3001 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index de0a691c75..dc42d4b0f7 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -267,7 +267,6 @@ public class EthernetNetworkFactory extends NetworkFactory { } void setIpConfig(IpConfiguration ipConfig) { - this.mIpConfig = ipConfig; } From a9d0a4a5f6bac64481240971d25776eaf8855d7b Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 17 Aug 2018 13:21:25 +0900 Subject: [PATCH 211/881] Strategic fix for infinite loop Bug: 111326363 Test: Manual + atest frameworks-net Change-Id: Id262df4e41de5c74784637ae4a5459c3fab9fb74 --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index dc42d4b0f7..dc94482bfd 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -33,6 +33,7 @@ import android.net.NetworkSpecifier; import android.net.StringNetworkSpecifier; import android.net.ip.IpClient; import android.net.ip.IpClient.ProvisioningConfiguration; +import android.net.util.InterfaceParams; import android.os.Handler; import android.text.TextUtils; import android.util.Log; @@ -328,7 +329,11 @@ public class EthernetNetworkFactory extends NetworkFactory { // This cannot happen due to provisioning timeout, because our timeout is 0. It can only // happen if we're provisioned and we lose provisioning. stop(); - start(); + // If the interface has disappeared provisioning will fail over and over again, so + // there is no point in starting again + if (null != InterfaceParams.getByName(name)) { + start(); + } } void updateLinkProperties(LinkProperties linkProperties) { From c9a8b526ed40e76649da3ccbf339c2e0009589ea Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 17 Aug 2018 13:21:25 +0900 Subject: [PATCH 212/881] Strategic fix for infinite loop Bug: 111326363 Test: Manual + atest frameworks-net + atest frameworks/opt/net/ethernet/tests/java/com/android/server Change-Id: Id262df4e41de5c74784637ae4a5459c3fab9fb74 --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index de0a691c75..b35e3cf132 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -33,6 +33,7 @@ import android.net.NetworkSpecifier; import android.net.StringNetworkSpecifier; import android.net.ip.IpClient; import android.net.ip.IpClient.ProvisioningConfiguration; +import android.net.util.InterfaceParams; import android.os.Handler; import android.text.TextUtils; import android.util.Log; @@ -329,7 +330,11 @@ public class EthernetNetworkFactory extends NetworkFactory { // This cannot happen due to provisioning timeout, because our timeout is 0. It can only // happen if we're provisioned and we lose provisioning. stop(); - start(); + // If the interface has disappeared provisioning will fail over and over again, so + // there is no point in starting again + if (null != InterfaceParams.getByName(name)) { + start(); + } } void updateLinkProperties(LinkProperties linkProperties) { From 1f7f52b16ec7c65c5ebd36450f9a36b45a0a0e1d Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 13 Aug 2018 15:54:27 +0900 Subject: [PATCH 213/881] Add DhcpServer This first version can serve discover/request/release, although there are some small behavior changes with current implementation which will be addressed later. Also removes final modifiers on start() and stop() in FdEventsReader, to allow mocking the methods in tests with the current mockito lib. Test: Added tests pass, manual: flashed a device using the server Change-Id: I025366ff7d51c4ba31152af50f3dd2b5e280a54d --- core/java/android/net/TrafficStats.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 44f7e48eda..1b22911f0c 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -139,6 +139,8 @@ public class TrafficStats { public static final int TAG_SYSTEM_GPS = 0xFFFFFF44; /** @hide */ public static final int TAG_SYSTEM_PAC = 0xFFFFFF45; + /** @hide */ + public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46; private static INetworkStatsService sStatsService; From 780297fa130217ca9023a1e085079fe278717ddf Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 7 May 2018 20:06:44 -0700 Subject: [PATCH 214/881] Use tunnel local/remote addresses in security policies This patch changes tunnel mode security policies to use the actual tunnel's local and remote addresses to select the SA. This prevents the kernel from calling xfrm_get_saddr(), which does a route lookup, potentially resolving an incorrect saddr. Bug: 79384676 Test: CTS, IpSecService* tests passing Change-Id: I8223225e2363a79591a0bb0040aa8619cf84c184 --- .../java/com/android/server/IpSecService.java | 84 ++++++++++--------- 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 744ed25f16..01e81525d5 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -27,7 +27,6 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; -import android.net.ConnectivityManager; import android.net.IIpSecService; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -44,7 +43,6 @@ import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; -import android.os.DeadSystemException; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -89,9 +87,8 @@ public class IpSecService extends IIpSecService.Stub { private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final String NETD_SERVICE_NAME = "netd"; - private static final int[] DIRECTIONS = - new int[] {IpSecManager.DIRECTION_OUT, IpSecManager.DIRECTION_IN}; - private static final String[] WILDCARD_ADDRESSES = new String[]{"0.0.0.0", "::"}; + private static final int[] ADDRESS_FAMILIES = + new int[] {OsConstants.AF_INET, OsConstants.AF_INET6}; private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms private static final int MAX_PORT_BIND_ATTEMPTS = 10; @@ -819,16 +816,22 @@ public class IpSecService extends IIpSecService.Stub { // Teardown VTI // Delete global policies try { - mSrvConfig.getNetdInstance().removeVirtualTunnelInterface(mInterfaceName); + final INetd netd = mSrvConfig.getNetdInstance(); + netd.removeVirtualTunnelInterface(mInterfaceName); - for(String wildcardAddr : WILDCARD_ADDRESSES) { - for (int direction : DIRECTIONS) { - int mark = (direction == IpSecManager.DIRECTION_IN) ? mIkey : mOkey; - mSrvConfig - .getNetdInstance() - .ipSecDeleteSecurityPolicy( - 0, direction, wildcardAddr, wildcardAddr, mark, 0xffffffff); - } + for (int selAddrFamily : ADDRESS_FAMILIES) { + netd.ipSecDeleteSecurityPolicy( + 0, + selAddrFamily, + IpSecManager.DIRECTION_OUT, + mOkey, + 0xffffffff); + netd.ipSecDeleteSecurityPolicy( + 0, + selAddrFamily, + IpSecManager.DIRECTION_IN, + mIkey, + 0xffffffff); } } catch (ServiceSpecificException | RemoteException e) { Log.e( @@ -1276,25 +1279,29 @@ public class IpSecService extends IIpSecService.Stub { // Create VTI // Add inbound/outbound global policies // (use reqid = 0) - mSrvConfig - .getNetdInstance() - .addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey); + final INetd netd = mSrvConfig.getNetdInstance(); + netd.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey); - for(String wildcardAddr : WILDCARD_ADDRESSES) { - for (int direction : DIRECTIONS) { - int mark = (direction == IpSecManager.DIRECTION_OUT) ? okey : ikey; - - mSrvConfig - .getNetdInstance() - .ipSecAddSecurityPolicy( - 0, // Use 0 for reqId - direction, - wildcardAddr, - wildcardAddr, - 0, - mark, - 0xffffffff); - } + for (int selAddrFamily : ADDRESS_FAMILIES) { + // Always send down correct local/remote addresses for template. + netd.ipSecAddSecurityPolicy( + 0, // Use 0 for reqId + selAddrFamily, + IpSecManager.DIRECTION_OUT, + localAddr, + remoteAddr, + 0, + okey, + 0xffffffff); + netd.ipSecAddSecurityPolicy( + 0, // Use 0 for reqId + selAddrFamily, + IpSecManager.DIRECTION_IN, + remoteAddr, + localAddr, + 0, + ikey, + 0xffffffff); } userRecord.mTunnelInterfaceRecords.put( @@ -1693,9 +1700,9 @@ public class IpSecService extends IIpSecService.Stub { SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId()); int mark = - (direction == IpSecManager.DIRECTION_IN) - ? tunnelInterfaceInfo.getIkey() - : tunnelInterfaceInfo.getOkey(); + (direction == IpSecManager.DIRECTION_OUT) + ? tunnelInterfaceInfo.getOkey() + : tunnelInterfaceInfo.getIkey(); try { c.setMarkValue(mark); @@ -1706,14 +1713,15 @@ public class IpSecService extends IIpSecService.Stub { c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork()); // If outbound, also add SPI to the policy. - for(String wildcardAddr : WILDCARD_ADDRESSES) { + for (int selAddrFamily : ADDRESS_FAMILIES) { mSrvConfig .getNetdInstance() .ipSecUpdateSecurityPolicy( 0, // Use 0 for reqId + selAddrFamily, direction, - wildcardAddr, - wildcardAddr, + tunnelInterfaceInfo.getLocalAddress(), + tunnelInterfaceInfo.getRemoteAddress(), transformInfo.getSpiRecord().getSpi(), mark, 0xffffffff); From 0df4ff77dba0407775ac764924f84c386471c44e Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 25 Jul 2018 13:06:29 -0700 Subject: [PATCH 215/881] Use UID as requestID This change makes all requestIDs use the UID of the creator, ensuring that rekeys always use the same requestID. This also has the nice property of separating app's resources from each other, and allowing for identification of which app/UID allocated the resources from command-line dumps (eg ip xfrm state show) Bug: 111841561 Test: Updated tests & passing taimen Change-Id: I4f1eadcdb795766ae4682b15e41727359c52fa38 --- .../java/com/android/server/IpSecService.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 01e81525d5..380f6a7e58 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -612,7 +612,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - mResourceId, + uid, mConfig.getSourceAddress(), mConfig.getDestinationAddress(), spi, @@ -679,7 +679,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - mResourceId, mSourceAddress, mDestinationAddress, mSpi, 0, 0); + uid, mSourceAddress, mDestinationAddress, mSpi, 0, 0); } } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); @@ -821,13 +821,13 @@ public class IpSecService extends IIpSecService.Stub { for (int selAddrFamily : ADDRESS_FAMILIES) { netd.ipSecDeleteSecurityPolicy( - 0, + uid, selAddrFamily, IpSecManager.DIRECTION_OUT, mOkey, 0xffffffff); netd.ipSecDeleteSecurityPolicy( - 0, + uid, selAddrFamily, IpSecManager.DIRECTION_IN, mIkey, @@ -1083,7 +1083,8 @@ public class IpSecService extends IIpSecService.Stub { } checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int callingUid = Binder.getCallingUid(); + UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); final int resourceId = mNextResourceId++; int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; @@ -1096,7 +1097,7 @@ public class IpSecService extends IIpSecService.Stub { spi = mSrvConfig .getNetdInstance() - .ipSecAllocateSpi(resourceId, "", destinationAddress, requestedSpi); + .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi); Log.d(TAG, "Allocated SPI " + spi); userRecord.mSpiRecords.put( resourceId, @@ -1264,7 +1265,8 @@ public class IpSecService extends IIpSecService.Stub { // TODO: Check that underlying network exists, and IP addresses not assigned to a different // network (b/72316676). - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int callerUid = Binder.getCallingUid(); + UserRecord userRecord = mUserResourceTracker.getUserRecord(callerUid); if (!userRecord.mTunnelQuotaTracker.isAvailable()) { return new IpSecTunnelInterfaceResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } @@ -1285,7 +1287,7 @@ public class IpSecService extends IIpSecService.Stub { for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. netd.ipSecAddSecurityPolicy( - 0, // Use 0 for reqId + callerUid, selAddrFamily, IpSecManager.DIRECTION_OUT, localAddr, @@ -1294,7 +1296,7 @@ public class IpSecService extends IIpSecService.Stub { okey, 0xffffffff); netd.ipSecAddSecurityPolicy( - 0, // Use 0 for reqId + callerUid, selAddrFamily, IpSecManager.DIRECTION_IN, remoteAddr, @@ -1532,7 +1534,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecAddSecurityAssociation( - resourceId, + Binder.getCallingUid(), c.getMode(), c.getSourceAddress(), c.getDestinationAddress(), @@ -1623,13 +1625,14 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void applyTransportModeTransform( ParcelFileDescriptor socket, int direction, int resourceId) throws RemoteException { - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int callingUid = Binder.getCallingUid(); + UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); checkDirection(direction); // Get transform record; if no transform is found, will throw IllegalArgumentException TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId); // TODO: make this a function. - if (info.pid != getCallingPid() || info.uid != getCallingUid()) { + if (info.pid != getCallingPid() || info.uid != callingUid) { throw new SecurityException("Only the owner of an IpSec Transform may apply it!"); } @@ -1643,7 +1646,7 @@ public class IpSecService extends IIpSecService.Stub { .getNetdInstance() .ipSecApplyTransportModeTransform( socket.getFileDescriptor(), - resourceId, + callingUid, direction, c.getSourceAddress(), c.getDestinationAddress(), @@ -1675,7 +1678,8 @@ public class IpSecService extends IIpSecService.Stub { enforceTunnelPermissions(callingPackage); checkDirection(direction); - UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + int callingUid = Binder.getCallingUid(); + UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); // Get transform record; if no transform is found, will throw IllegalArgumentException TransformRecord transformInfo = @@ -1717,7 +1721,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecUpdateSecurityPolicy( - 0, // Use 0 for reqId + callingUid, selAddrFamily, direction, tunnelInterfaceInfo.getLocalAddress(), From c61623c4a1fddc9ed9104df29dd3bae9c26e0893 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 13 Sep 2018 16:45:12 -0700 Subject: [PATCH 216/881] Re-enable checks for MANAGE_IPSEC_TUNNELS This patch ensures that creation and modification of IPsec tunnels requires the MANAGE_IPSEC_TUNNELS appop. Bug: 115685048 Test: IpSecManagerTunnelTest fails without appops set Change-Id: I6c60a2573ca521717877f36e28a392b0d3b62754 --- .../java/com/android/server/IpSecService.java | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 01e81525d5..8c5187e41e 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1488,23 +1488,19 @@ public class IpSecService extends IIpSecService.Stub { } } - private static final String TUNNEL_OP = "STOPSHIP"; // = AppOpsManager.OP_MANAGE_IPSEC_TUNNELS; + private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS; private void enforceTunnelPermissions(String callingPackage) { checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); - if (false) { // STOPSHIP if this line is present - switch (getAppOpsManager().noteOp( - TUNNEL_OP, - Binder.getCallingUid(), callingPackage)) { - case AppOpsManager.MODE_DEFAULT: - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); - break; - case AppOpsManager.MODE_ALLOWED: - return; - default: - throw new SecurityException("Request to ignore AppOps for non-legacy API"); - } + switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) { + case AppOpsManager.MODE_DEFAULT: + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); + break; + case AppOpsManager.MODE_ALLOWED: + return; + default: + throw new SecurityException("Request to ignore AppOps for non-legacy API"); } } From f10b7f4730d12ca55a750e084ac5d163ec1ce70b Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Fri, 14 Sep 2018 15:16:48 -0700 Subject: [PATCH 217/881] Don't check qtaguid file unless using them The proc file of xt_qtaguid module is not necessarily exist on future devices. We should only check it if the device need to read the stats file for network usage information. Bug: 79938294 Test: NetworkUsageStatsTest TrafficStatsTest Change-Id: I5ac6feef8b9a26daa68b381a985925e24b0d80af --- .../jni/com_android_internal_net_NetworkStatsFactory.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index c15b7ee4fe..109e65c4a1 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -285,10 +285,6 @@ static int statsLinesToNetworkStats(JNIEnv* env, jclass clazz, jobject stats, static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstring path, jint limitUid, jobjectArray limitIfacesObj, jint limitTag, jboolean useBpfStats) { - ScopedUtfChars path8(env, path); - if (path8.c_str() == NULL) { - return -1; - } std::vector limitIfaces; if (limitIfacesObj != NULL && env->GetArrayLength(limitIfacesObj) > 0) { @@ -308,6 +304,11 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, jstr if (parseBpfNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid) < 0) return -1; } else { + ScopedUtfChars path8(env, path); + if (path8.c_str() == NULL) { + ALOGE("the qtaguid legacy path is invalid: %s", path8.c_str()); + return -1; + } if (legacyReadNetworkStatsDetail(&lines, limitIfaces, limitTag, limitUid, path8.c_str()) < 0) return -1; From 1d13372c11749ad43e33fb35922ace60a4a95b39 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 22 Aug 2018 10:21:26 +0900 Subject: [PATCH 218/881] Delay global alerts by 1s for high thresholds By skipping updates if an alert is already scheduled, this avoids firing the global alert too often on devices with high transfer speeds and high quota. Test: with tethering watching videos. Also runtest frameworks-net Bug: 117243748 Change-Id: Idce6059832db7a0e4a7117bbb3e424ec62ae3b21 --- .../server/net/NetworkStatsService.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 60e9eaab57..3f031699bd 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -159,8 +159,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE); + // Perform polling and persist all (FLAG_PERSIST_ALL). private static final int MSG_PERFORM_POLL = 1; - private static final int MSG_REGISTER_GLOBAL_ALERT = 2; + // Perform polling, persist network, and register the global alert again. + private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -168,6 +170,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; private static final int FLAG_PERSIST_FORCE = 0x100; + /** + * When global alert quota is high, wait for this delay before processing each polling, + * and do not schedule further polls once there is already one queued. + * This avoids firing the global alert too often on devices with high transfer speeds and + * high quota. + */ + private static final int PERFORM_POLL_DELAY_MS = 1000; + private static final String TAG_NETSTATS_ERROR = "netstats_error"; private final Context mContext; @@ -920,7 +930,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // Create baseline stats - mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL, FLAG_PERSIST_ALL)); + mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL)); return normalizedRequest; } @@ -1055,13 +1065,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); if (LIMIT_GLOBAL_ALERT.equals(limitName)) { - // kick off background poll to collect network stats; UID stats - // are handled during normal polling interval. - final int flags = FLAG_PERSIST_NETWORK; - mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget(); - - // re-arm global alert for next update - mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget(); + // kick off background poll to collect network stats unless there is already + // such a call pending; UID stats are handled during normal polling interval. + if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) { + mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT, + PERFORM_POLL_DELAY_MS); + } } } }; @@ -1673,11 +1682,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_PERFORM_POLL: { - final int flags = msg.arg1; - mService.performPoll(flags); + mService.performPoll(FLAG_PERSIST_ALL); return true; } - case MSG_REGISTER_GLOBAL_ALERT: { + case MSG_PERFORM_POLL_REGISTER_ALERT: { + mService.performPoll(FLAG_PERSIST_NETWORK); mService.registerGlobalAlert(); return true; } From 9105f824286dd3526c6746041d820b1a440dac8f Mon Sep 17 00:00:00 2001 From: evitayan Date: Thu, 22 Mar 2018 17:53:08 -0700 Subject: [PATCH 219/881] Check to ensure UDP-encap is used only for IPv4 This commit checks if UDP-encapsulation is used for unsupported address family and throws IllegalArgumentException when it happens. Bug: 74213459 Test: Tests added in testCreateTransportModeTransformWithEncap and testCreateTunnelModeTransformWithEncap. Command: runtest frameworks-net Verified on taimen. Change-Id: I10c01f2bad6aca23430849ea9ef6c1eb157ae131 --- .../java/com/android/server/IpSecService.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index a69d41683c..8c25917c74 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -19,6 +19,8 @@ package com.android.server; import static android.Manifest.permission.DUMP; import static android.net.IpSecManager.INVALID_RESOURCE_ID; import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; +import static android.system.OsConstants.AF_UNSPEC; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; @@ -63,6 +65,8 @@ import com.android.internal.util.Preconditions; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; @@ -1426,6 +1430,17 @@ public class IpSecService extends IIpSecService.Stub { + "or Encryption algorithms"); } + private int getFamily(String inetAddress) { + int family = AF_UNSPEC; + InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress); + if (checkAddress instanceof Inet4Address) { + family = AF_INET; + } else if (checkAddress instanceof Inet6Address) { + family = AF_INET6; + } + return family; + } + /** * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an * IllegalArgumentException if they are not. @@ -1479,6 +1494,26 @@ public class IpSecService extends IIpSecService.Stub { // Require a valid source address for all transforms. checkInetAddress(config.getSourceAddress()); + // Check to ensure source and destination have the same address family. + String sourceAddress = config.getSourceAddress(); + String destinationAddress = config.getDestinationAddress(); + int sourceFamily = getFamily(sourceAddress); + int destinationFamily = getFamily(destinationAddress); + if (sourceFamily != destinationFamily) { + throw new IllegalArgumentException( + "Source address (" + + sourceAddress + + ") and destination address (" + + destinationAddress + + ") have different address families."); + } + + // Throw an error if UDP Encapsulation is not used in IPv4. + if (config.getEncapType() != IpSecTransform.ENCAP_NONE && sourceFamily != AF_INET) { + throw new IllegalArgumentException( + "UDP Encapsulation is not supported for this address family"); + } + switch (config.getMode()) { case IpSecTransform.MODE_TRANSPORT: break; From 739cb3df8b5bb1fc6bb053366fe49cf24138ddf7 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 16 Oct 2018 17:36:40 +0900 Subject: [PATCH 220/881] Don't consider TRACK_DEFAULT requests in EthernetNetworkFactory. These should not affect network refcount and thus should not be passed to the network transport. Bug: 116034205 Test: successfully established a VPN when connected to USB ethernet Change-Id: I66517d86f35b8cfc1e211cb189127187d2744b60 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index dc94482bfd..54bcdc3b35 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -72,6 +72,10 @@ public class EthernetNetworkFactory extends NetworkFactory { @Override public boolean acceptRequest(NetworkRequest request, int score) { + if (request.type == NetworkRequest.Type.TRACK_DEFAULT) { + return false; + } + if (DBG) { Log.d(TAG, "acceptRequest, request: " + request + ", score: " + score); } @@ -424,6 +428,7 @@ public class EthernetNetworkFactory extends NetworkFactory { @Override public String toString() { return getClass().getSimpleName() + "{ " + + "refCount: " + refCount + ", " + "iface: " + name + ", " + "up: " + mLinkUp + ", " + "hwAddress: " + mHwAddress + ", " From aeaeaefcef78d9d2bdcf8df3dc58b6a810b0cf0b Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 22 Aug 2018 10:21:26 +0900 Subject: [PATCH 221/881] Delay global alerts by 1s for high thresholds This is a cherry-pick of aosp/735725 with a minor conflict. By skipping updates if an alert is already scheduled, this avoids firing the global alert too often on devices with high transfer speeds and high quota. Test: with tethering watching videos. Also runtest frameworks-net Bug: 117243748 Change-Id: Ia0ed76141dfb33546529786eb0118138ef3708c2 Merged-In: Ie0ba5c1d1a2139606e63fcfe46ec77a89accd8d9 Merged-In: Iaabb31586e9e747871a526dc7ebb7deeb65d8f83 --- .../server/net/NetworkStatsService.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index fec510f28a..9bf3874088 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -159,9 +159,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE); + // Perform polling and persist all (FLAG_PERSIST_ALL). private static final int MSG_PERFORM_POLL = 1; private static final int MSG_UPDATE_IFACES = 2; - private static final int MSG_REGISTER_GLOBAL_ALERT = 3; + // Perform polling, persist network, and register the global alert again. + private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 3; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -169,6 +171,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; private static final int FLAG_PERSIST_FORCE = 0x100; + /** + * When global alert quota is high, wait for this delay before processing each polling, + * and do not schedule further polls once there is already one queued. + * This avoids firing the global alert too often on devices with high transfer speeds and + * high quota. + */ + private static final int PERFORM_POLL_DELAY_MS = 1000; + private static final String TAG_NETSTATS_ERROR = "netstats_error"; private final Context mContext; @@ -916,7 +926,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // Create baseline stats - mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL, FLAG_PERSIST_ALL)); + mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL)); return normalizedRequest; } @@ -1057,13 +1067,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); if (LIMIT_GLOBAL_ALERT.equals(limitName)) { - // kick off background poll to collect network stats; UID stats - // are handled during normal polling interval. - final int flags = FLAG_PERSIST_NETWORK; - mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget(); - - // re-arm global alert for next update - mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget(); + // kick off background poll to collect network stats unless there is already + // such a call pending; UID stats are handled during normal polling interval. + if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) { + mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT, + PERFORM_POLL_DELAY_MS); + } } } }; @@ -1675,15 +1684,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public boolean handleMessage(Message msg) { switch (msg.what) { case MSG_PERFORM_POLL: { - final int flags = msg.arg1; - mService.performPoll(flags); + mService.performPoll(FLAG_PERSIST_ALL); return true; } case MSG_UPDATE_IFACES: { mService.updateIfaces(null); return true; } - case MSG_REGISTER_GLOBAL_ALERT: { + case MSG_PERFORM_POLL_REGISTER_ALERT: { + mService.performPoll(FLAG_PERSIST_NETWORK); mService.registerGlobalAlert(); return true; } From fe39697d034bfce99000ac2b4a419dfa2c91300a Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Mon, 15 Oct 2018 17:31:43 -0700 Subject: [PATCH 222/881] Move bpf project to system/bpf The bpf project now have a new project directory in system/bpf instead of inside netd. The network related bpf library is renamed to libnetdbpf. Fix the dependency issue in framework to make sure no regression. Test: -m CtsNetTestCases -t android.net.cts.TrafficStatsTest Bug: 112334572 Change-Id: Ibd477bf17d18d516aa520fb1569f4a395ef9abf0 --- core/jni/com_android_internal_net_NetworkStatsFactory.cpp | 2 +- .../core/jni/com_android_server_net_NetworkStatsService.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 109e65c4a1..b3ff4dbf8b 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -32,8 +32,8 @@ #include #include "android-base/unique_fd.h" -#include "bpf/BpfNetworkStats.h" #include "bpf/BpfUtils.h" +#include "netdbpf/BpfNetworkStats.h" using android::bpf::hasBpfSupport; using android::bpf::parseBpfNetworkStatsDetail; diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 3302dea535..649f1a56f0 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -30,8 +30,8 @@ #include #include "android-base/unique_fd.h" -#include "bpf/BpfNetworkStats.h" #include "bpf/BpfUtils.h" +#include "netdbpf/BpfNetworkStats.h" using android::bpf::Stats; using android::bpf::hasBpfSupport; From fe47da6786e7814b62fa8bf4643a476f78c70d43 Mon Sep 17 00:00:00 2001 From: Olivier Gaillard Date: Mon, 10 Sep 2018 15:35:58 +0100 Subject: [PATCH 223/881] Update a few runnable/handler to use a static class instead of a runnable. It will help collecting better data for handler stats (we can get a fully qualified class name). Test: tested manually Change-Id: I674cf03909153fd87d97f600e246e04800cbb624 --- .../java/com/android/server/net/NetworkStatsService.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3f031699bd..6d3a3b69bc 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -105,6 +105,7 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkManagementService; +import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; @@ -323,6 +324,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Clock.systemUTC()); } + private static final class NetworkStatsHandler extends Handler { + NetworkStatsHandler(Looper looper, Handler.Callback callback) { + super(looper, callback); + } + } + public static NetworkStatsService create(Context context, INetworkManagementService networkManager) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); @@ -339,7 +346,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { HandlerThread handlerThread = new HandlerThread(TAG); Handler.Callback callback = new HandlerCallback(service); handlerThread.start(); - Handler handler = new Handler(handlerThread.getLooper(), callback); + Handler handler = new NetworkStatsHandler(handlerThread.getLooper(), callback); service.setHandler(handler, callback); return service; } From 74c19b8e92970d123ddc80312bd5c74222348525 Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Fri, 19 Oct 2018 15:57:05 +0900 Subject: [PATCH 224/881] Refactor UidRange by using stable aidl structure Use stable aidl generated structure instead of UidRange Test: runtest frameworks-net passes Test: manual testing of UidRange related function works Change-Id: Iaf1c10777dc1e71df2be2a57533a10257b12626b --- core/java/android/net/UidRange.aidl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 core/java/android/net/UidRange.aidl diff --git a/core/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl new file mode 100644 index 0000000000..f70fc8e2fe --- /dev/null +++ b/core/java/android/net/UidRange.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * An inclusive range of UIDs. + * + * {@hide} + */ +parcelable UidRange; \ No newline at end of file From f1307561ad5ac6861229f5d1b26601af8a365d01 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 19 Oct 2018 21:14:30 +0800 Subject: [PATCH 225/881] Fix negative uid stats caused by 464xlat adjust when eBPF is on. When using xt_qtaguid to count per uid stats, NetworkStatsService needs to adjust the 464xlat traffic since iptables module would double count for ipv4 and ipv6 packet. But for eBPF, the per uid stats is collected in a different hook, so the adjustment on root uid would only be needed in tx direction. Bug: 112226716 Test: 1. Make ipv4 traffic in ipv6-only network and check data usage. 2. Make ipv4 traffic in a client which connect to ipv6-only hotspot. 3. runtest frameworks-net 4. cts-tradefed run cts -m CtsNetTestCases -t \ android.net.cts.TrafficStatsTest 5. cts-tradefed run cts -m CtsUsageStatsTestCases Change-Id: Ic9a84f5446eddc943c255d5f3b89dad171f53cac --- core/java/android/net/NetworkStats.java | 24 +++++++++++++------ .../internal/net/NetworkStatsFactory.java | 9 +++---- .../server/net/NetworkStatsService.java | 6 +++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index e270fc2e39..5447f595ca 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -811,14 +811,19 @@ public class NetworkStats implements Parcelable { * packet needs to be subtracted from the root UID on the base interface both for tx * and rx traffic (http://b/12249687, http:/b/33681750). * + * As for eBPF, the per uid stats is collected by different hook, the rx packets on base + * interface will not be counted. Thus, the adjustment on root uid is only needed in tx + * direction. + * *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only * {@code ConcurrentHashMap} * @param baseTraffic Traffic on the base interfaces. Will be mutated. * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + * @param useBpfStats True if eBPF is in use. */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic, Map stackedIfaces) { + NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { // Total 464xlat traffic to subtract from uid 0 on all base interfaces. // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); @@ -837,15 +842,20 @@ public class NetworkStats implements Parcelable { continue; } // Subtract any 464lat traffic seen for the root UID on the current base interface. + // However, for eBPF, the per uid stats is collected by different hook, the rx packets + // on base interface will not be counted. Thus, the adjustment on root uid is only + // needed in tx direction. adjust.iface = baseIface; - adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + if (!useBpfStats) { + adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + adjust.rxPackets = -entry.rxPackets; + } adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets = -entry.rxPackets; adjust.txPackets = -entry.txPackets; adjustments.combineValues(adjust); - // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent - // on the stacked interface with prefix "v4-" and drops the IPv6 header size after + // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet + // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes // difference for all packets (http://b/12249687, http:/b/33681750). entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA; @@ -864,8 +874,8 @@ public class NetworkStats implements Parcelable { * base and stacked traffic. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. */ - public void apply464xlatAdjustments(Map stackedIfaces) { - apply464xlatAdjustments(this, this, stackedIfaces); + public void apply464xlatAdjustments(Map stackedIfaces, boolean useBpfStats) { + apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats); } /** diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index d1c279918b..0a7cff6856 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -113,11 +113,12 @@ public class NetworkStatsFactory { /** * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. - * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map) + * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic) { - NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces); + NetworkStats stackedTraffic, boolean useBpfStats) { + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces, + useBpfStats); } @VisibleForTesting @@ -263,7 +264,7 @@ public class NetworkStatsFactory { // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. // TODO: remove this and only apply adjustments in NetworkStatsService. - stats.apply464xlatAdjustments(sStackedIfaces); + stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); return stats; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3f031699bd..383e1e0288 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1620,7 +1620,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, + mUseBpfTrafficStats); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1630,7 +1631,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, + mUseBpfTrafficStats); uidSnapshot.combineAllValues(vtStats); } From a5dc562cf860e903dbd08bbc40baf88485547820 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 19 Oct 2018 21:14:30 +0800 Subject: [PATCH 226/881] Fix negative uid stats caused by 464xlat adjust when eBPF is on. When using xt_qtaguid to count per uid stats, NetworkStatsService needs to adjust the 464xlat traffic since iptables module would double count for ipv4 and ipv6 packet. But for eBPF, the per uid stats is collected in a different hook, so the adjustment on root uid would only be needed in tx direction. Bug: 112226716 Test: 1. Make ipv4 traffic in ipv6-only network and check data usage. 2. Make ipv4 traffic in a client which connect to ipv6-only hotspot. 3. runtest frameworks-net 4. cts-tradefed run cts -m CtsNetTestCases -t \ android.net.cts.TrafficStatsTest 5. cts-tradefed run cts -m CtsUsageStatsTestCases Change-Id: Ic9a84f5446eddc943c255d5f3b89dad171f53cac Merged-In: Ic9a84f5446eddc943c255d5f3b89dad171f53cac (cherry picked from commit f1307561ad5ac6861229f5d1b26601af8a365d01) --- core/java/android/net/NetworkStats.java | 24 +++++++++++++------ .../internal/net/NetworkStatsFactory.java | 9 +++---- .../server/net/NetworkStatsService.java | 6 +++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index edf9bc1c6b..4bcc245368 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -776,14 +776,19 @@ public class NetworkStats implements Parcelable { * packet needs to be subtracted from the root UID on the base interface both for tx * and rx traffic (http://b/12249687, http:/b/33681750). * + * As for eBPF, the per uid stats is collected by different hook, the rx packets on base + * interface will not be counted. Thus, the adjustment on root uid is only needed in tx + * direction. + * *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only * {@code ConcurrentHashMap} * @param baseTraffic Traffic on the base interfaces. Will be mutated. * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + * @param useBpfStats True if eBPF is in use. */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic, Map stackedIfaces) { + NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { // Total 464xlat traffic to subtract from uid 0 on all base interfaces. // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); @@ -802,15 +807,20 @@ public class NetworkStats implements Parcelable { continue; } // Subtract any 464lat traffic seen for the root UID on the current base interface. + // However, for eBPF, the per uid stats is collected by different hook, the rx packets + // on base interface will not be counted. Thus, the adjustment on root uid is only + // needed in tx direction. adjust.iface = baseIface; - adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + if (!useBpfStats) { + adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + adjust.rxPackets = -entry.rxPackets; + } adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets = -entry.rxPackets; adjust.txPackets = -entry.txPackets; adjustments.combineValues(adjust); - // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent - // on the stacked interface with prefix "v4-" and drops the IPv6 header size after + // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet + // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes // difference for all packets (http://b/12249687, http:/b/33681750). entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA; @@ -829,8 +839,8 @@ public class NetworkStats implements Parcelable { * base and stacked traffic. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. */ - public void apply464xlatAdjustments(Map stackedIfaces) { - apply464xlatAdjustments(this, this, stackedIfaces); + public void apply464xlatAdjustments(Map stackedIfaces, boolean useBpfStats) { + apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats); } /** diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index c4d08c7dc5..b3cf389c1b 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -113,11 +113,12 @@ public class NetworkStatsFactory { /** * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. - * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map) + * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic) { - NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces); + NetworkStats stackedTraffic, boolean useBpfStats) { + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces, + useBpfStats); } @VisibleForTesting @@ -263,7 +264,7 @@ public class NetworkStatsFactory { // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. // TODO: remove this and only apply adjustments in NetworkStatsService. - stats.apply464xlatAdjustments(sStackedIfaces); + stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); return stats; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 9bf3874088..17ab29d747 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1622,7 +1622,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, + mUseBpfTrafficStats); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1632,7 +1633,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, + mUseBpfTrafficStats); uidSnapshot.combineAllValues(vtStats); } From 99d13c33776db3e1102985d9b73071acca1d29b8 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 8 Nov 2018 22:33:09 +0800 Subject: [PATCH 227/881] Change types of fields of network stats reported to framework. Currently, NetworkStats use int to handle uid, set and tag, while native side using unsigned int mixing with signed int with that. This commit make necessary changes in JNI part while libnetdbpf unifying the types of fields. Bug: 112226716 Test: 1. manually reconnect vpn 2. update apps from playstore 3. atest libnetdbpf_test 4. runtest frameworks-net 5. cts-tradefed run cts -m CtsUsageStatsTestCases -t \ android.app.usage.cts.NetworkUsageStatsTest Change-Id: I6c27124db8292e2825fba51b8994f013897cb566 --- core/jni/com_android_internal_net_NetworkStatsFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index b3ff4dbf8b..b708735616 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -175,7 +175,7 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, } } s.tag = rawTag >> 32; - if (limitTag != -1 && s.tag != limitTag) { + if (limitTag != -1 && s.tag != static_cast(limitTag)) { //ALOGI("skipping due to tag: %s", buffer); continue; } @@ -188,7 +188,7 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &s.uid, &s.set, &s.rxBytes, &s.rxPackets, &s.txBytes, &s.txPackets) == 6) { - if (limitUid != -1 && limitUid != s.uid) { + if (limitUid != -1 && static_cast(limitUid) != s.uid) { //ALOGI("skipping due to uid: %s", buffer); continue; } From a6c3c7e35d01949bdd56a3941beb9935ed5e46cb Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 8 Nov 2018 22:33:09 +0800 Subject: [PATCH 228/881] Change types of fields of network stats reported to framework. Currently, NetworkStats use int to handle uid, set and tag, while native side using unsigned int mixing with signed int with that. This commit make necessary changes in JNI part while libnetdbpf unifying the types of fields. Bug: 112226716 Bug: 119193941 Test: 1. manually reconnect vpn 2. update apps from playstore 3. atest libnetdbpf_test 4. runtest frameworks-net 5. cts-tradefed run cts -m CtsUsageStatsTestCases -t \ android.app.usage.cts.NetworkUsageStatsTest Change-Id: I6c27124db8292e2825fba51b8994f013897cb566 Merged-In: I6c27124db8292e2825fba51b8994f013897cb566 (cherry picked from commit bf7803eed8283d5a1caa2efe90aa449590ddb94f) --- core/jni/com_android_internal_net_NetworkStatsFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index c15b7ee4fe..de3a78a61a 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -175,7 +175,7 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, } } s.tag = rawTag >> 32; - if (limitTag != -1 && s.tag != limitTag) { + if (limitTag != -1 && s.tag != static_cast(limitTag)) { //ALOGI("skipping due to tag: %s", buffer); continue; } @@ -188,7 +188,7 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &s.uid, &s.set, &s.rxBytes, &s.rxPackets, &s.txBytes, &s.txPackets) == 6) { - if (limitUid != -1 && limitUid != s.uid) { + if (limitUid != -1 && static_cast(limitUid) != s.uid) { //ALOGI("skipping due to uid: %s", buffer); continue; } From 8e262d068af1d1aeae524a8128db98b1ae28bba4 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 25 Jul 2018 18:46:19 -0700 Subject: [PATCH 229/881] Disable attempted updating of SA marks SA marks are never updated during the UPDSA call. This change disables the attempts to update the specified SAs, ensuring that the config stored in IpSecService matches that of the allocated kernel resources. Bug: 111854872 Test: Unit, CTS tests passing Change-Id: Ic1fb862c8021ffa260c3e262ec698d8af0a826d9 --- core/java/android/net/IpSecConfig.java | 14 ++++++++++++- .../java/com/android/server/IpSecService.java | 20 ++++++++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 8599f47c62..c7eb2dd7a3 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -65,7 +65,7 @@ public final class IpSecConfig implements Parcelable { // An interval, in seconds between the NattKeepalive packets private int mNattKeepaliveInterval; - // XFRM mark and mask + // XFRM mark and mask; defaults to 0 (no mark/mask) private int mMarkValue; private int mMarkMask; @@ -125,10 +125,22 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = interval; } + /** + * Sets the mark value + * + *

Internal (System server) use only. Marks passed in by users will be overwritten or + * ignored. + */ public void setMarkValue(int mark) { mMarkValue = mark; } + /** + * Sets the mark mask + * + *

Internal (System server) use only. Marks passed in by users will be overwritten or + * ignored. + */ public void setMarkMask(int mask) { mMarkMask = mask; } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 8c25917c74..c4b749011a 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -24,6 +24,7 @@ import static android.system.OsConstants.AF_UNSPEC; import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -62,6 +63,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import libcore.io.IoUtils; + import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -73,8 +76,6 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; -import libcore.io.IoUtils; - /** * A service to manage multiple clients that want to access the IpSec API. The service is * responsible for maintaining a list of clients and managing the resources (and related quotas) @@ -1523,6 +1524,9 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException( "Invalid IpSecTransform.mode: " + config.getMode()); } + + config.setMarkValue(0); + config.setMarkMask(0); } private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS; @@ -1740,8 +1744,14 @@ public class IpSecService extends IIpSecService.Stub { : tunnelInterfaceInfo.getIkey(); try { - c.setMarkValue(mark); - c.setMarkMask(0xffffffff); + // TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream + // (and backporting) would allow us to narrow the mark space, and ensure that the SA + // and SPs have matching marks (as VTI are meant to be built). + // Currently update does nothing with marks. Leave empty (defaulting to 0) to ensure the + // config matches the actual allocated resources in the kernel. + // + // c.setMarkValue(mark); + // c.setMarkMask(0xffffffff); if (direction == IpSecManager.DIRECTION_OUT) { // Set output mark via underlying network (output only) @@ -1758,7 +1768,7 @@ public class IpSecService extends IIpSecService.Stub { tunnelInterfaceInfo.getLocalAddress(), tunnelInterfaceInfo.getRemoteAddress(), transformInfo.getSpiRecord().getSpi(), - mark, + mark, // Must always set policy mark; ikey/okey for VTIs 0xffffffff); } } From 823266818fe54179d8c5429ad1159027050405b7 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 6 Sep 2018 11:31:25 -0700 Subject: [PATCH 230/881] Add XFRM-I support to IpSecService This change adds support for XFRM-I to all IpSecService netd calls. Fallback logic is in netd, and thus both VTI and XFRM-I parameters are always passed down to IpSecService. Bug: 78589502 Test: All java, CTS tests passing Change-Id: Ie4186f0ad7e50763b21831f6fa411b5ee436de78 --- core/java/android/net/IpSecConfig.java | 22 +++++- .../java/com/android/server/IpSecService.java | 76 +++++++++++++------ 2 files changed, 70 insertions(+), 28 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index c7eb2dd7a3..3552655983 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -69,6 +69,9 @@ public final class IpSecConfig implements Parcelable { private int mMarkValue; private int mMarkMask; + // XFRM interface id + private int mXfrmInterfaceId; + /** Set the mode for this IPsec transform */ public void setMode(int mode) { mMode = mode; @@ -145,6 +148,10 @@ public final class IpSecConfig implements Parcelable { mMarkMask = mask; } + public void setXfrmInterfaceId(int xfrmInterfaceId) { + mXfrmInterfaceId = xfrmInterfaceId; + } + // Transport or Tunnel public int getMode() { return mMode; @@ -202,6 +209,10 @@ public final class IpSecConfig implements Parcelable { return mMarkMask; } + public int getXfrmInterfaceId() { + return mXfrmInterfaceId; + } + // Parcelable Methods @Override @@ -225,6 +236,7 @@ public final class IpSecConfig implements Parcelable { out.writeInt(mNattKeepaliveInterval); out.writeInt(mMarkValue); out.writeInt(mMarkMask); + out.writeInt(mXfrmInterfaceId); } @VisibleForTesting @@ -247,6 +259,7 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = c.mNattKeepaliveInterval; mMarkValue = c.mMarkValue; mMarkMask = c.mMarkMask; + mXfrmInterfaceId = c.mXfrmInterfaceId; } private IpSecConfig(Parcel in) { @@ -267,6 +280,7 @@ public final class IpSecConfig implements Parcelable { mNattKeepaliveInterval = in.readInt(); mMarkValue = in.readInt(); mMarkMask = in.readInt(); + mXfrmInterfaceId = in.readInt(); } @Override @@ -301,6 +315,8 @@ public final class IpSecConfig implements Parcelable { .append(mMarkValue) .append(", mMarkMask=") .append(mMarkMask) + .append(", mXfrmInterfaceId=") + .append(mXfrmInterfaceId) .append("}"); return strBuilder.toString(); @@ -332,10 +348,10 @@ public final class IpSecConfig implements Parcelable { && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval && lhs.mSpiResourceId == rhs.mSpiResourceId && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) - && IpSecAlgorithm.equals( - lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) + && IpSecAlgorithm.equals(lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication) && lhs.mMarkValue == rhs.mMarkValue - && lhs.mMarkMask == rhs.mMarkMask); + && lhs.mMarkMask == rhs.mMarkMask + && lhs.mXfrmInterfaceId == rhs.mXfrmInterfaceId); } } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index c4b749011a..71a7a2b5ab 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -622,7 +622,8 @@ public class IpSecService extends IIpSecService.Stub { mConfig.getDestinationAddress(), spi, mConfig.getMarkValue(), - mConfig.getMarkMask()); + mConfig.getMarkMask(), + mConfig.getXfrmInterfaceId()); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } @@ -684,7 +685,8 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - uid, mSourceAddress, mDestinationAddress, mSpi, 0, 0); + uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, + 0 /* mask */, 0 /* if_id */); } } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); @@ -796,6 +798,8 @@ public class IpSecService extends IIpSecService.Stub { private final int mIkey; private final int mOkey; + private final int mIfId; + TunnelInterfaceRecord( int resourceId, String interfaceName, @@ -803,7 +807,8 @@ public class IpSecService extends IIpSecService.Stub { String localAddr, String remoteAddr, int ikey, - int okey) { + int okey, + int intfId) { super(resourceId); mInterfaceName = interfaceName; @@ -812,6 +817,7 @@ public class IpSecService extends IIpSecService.Stub { mRemoteAddress = remoteAddr; mIkey = ikey; mOkey = okey; + mIfId = intfId; } /** always guarded by IpSecService#this */ @@ -822,7 +828,7 @@ public class IpSecService extends IIpSecService.Stub { // Delete global policies try { final INetd netd = mSrvConfig.getNetdInstance(); - netd.removeVirtualTunnelInterface(mInterfaceName); + netd.ipSecRemoveTunnelInterface(mInterfaceName); for (int selAddrFamily : ADDRESS_FAMILIES) { netd.ipSecDeleteSecurityPolicy( @@ -830,13 +836,15 @@ public class IpSecService extends IIpSecService.Stub { selAddrFamily, IpSecManager.DIRECTION_OUT, mOkey, - 0xffffffff); + 0xffffffff, + mIfId); netd.ipSecDeleteSecurityPolicy( uid, selAddrFamily, IpSecManager.DIRECTION_IN, mIkey, - 0xffffffff); + 0xffffffff, + mIfId); } } catch (ServiceSpecificException | RemoteException e) { Log.e( @@ -878,6 +886,10 @@ public class IpSecService extends IIpSecService.Stub { return mOkey; } + public int getIfId() { + return mIfId; + } + @Override protected ResourceTracker getResourceTracker() { return getUserRecord().mTunnelQuotaTracker; @@ -1287,7 +1299,7 @@ public class IpSecService extends IIpSecService.Stub { // Add inbound/outbound global policies // (use reqid = 0) final INetd netd = mSrvConfig.getNetdInstance(); - netd.addVirtualTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey); + netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. @@ -1299,7 +1311,8 @@ public class IpSecService extends IIpSecService.Stub { remoteAddr, 0, okey, - 0xffffffff); + 0xffffffff, + resourceId); netd.ipSecAddSecurityPolicy( callerUid, selAddrFamily, @@ -1308,7 +1321,8 @@ public class IpSecService extends IIpSecService.Stub { localAddr, 0, ikey, - 0xffffffff); + 0xffffffff, + resourceId); } userRecord.mTunnelInterfaceRecords.put( @@ -1321,7 +1335,8 @@ public class IpSecService extends IIpSecService.Stub { localAddr, remoteAddr, ikey, - okey), + okey, + resourceId), binder)); return new IpSecTunnelInterfaceResponse(IpSecManager.Status.OK, resourceId, intfName); } catch (RemoteException e) { @@ -1588,7 +1603,8 @@ public class IpSecService extends IIpSecService.Stub { (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, encapType, encapLocalPort, - encapRemotePort); + encapRemotePort, + c.getXfrmInterfaceId()); } /** @@ -1744,6 +1760,11 @@ public class IpSecService extends IIpSecService.Stub { : tunnelInterfaceInfo.getIkey(); try { + // Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip + // SPI matching as part of the template resolution. + int spi = IpSecManager.INVALID_SECURITY_PARAMETER_INDEX; + c.setXfrmInterfaceId(tunnelInterfaceInfo.getIfId()); + // TODO: enable this when UPDSA supports updating marks. Adding kernel support upstream // (and backporting) would allow us to narrow the mark space, and ensure that the SA // and SPs have matching marks (as VTI are meant to be built). @@ -1757,20 +1778,25 @@ public class IpSecService extends IIpSecService.Stub { // Set output mark via underlying network (output only) c.setNetwork(tunnelInterfaceInfo.getUnderlyingNetwork()); - // If outbound, also add SPI to the policy. - for (int selAddrFamily : ADDRESS_FAMILIES) { - mSrvConfig - .getNetdInstance() - .ipSecUpdateSecurityPolicy( - callingUid, - selAddrFamily, - direction, - tunnelInterfaceInfo.getLocalAddress(), - tunnelInterfaceInfo.getRemoteAddress(), - transformInfo.getSpiRecord().getSpi(), - mark, // Must always set policy mark; ikey/okey for VTIs - 0xffffffff); - } + // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys, + // but want to guarantee outbound packets are sent over the new SA. + spi = transformInfo.getSpiRecord().getSpi(); + } + + // Always update the policy with the relevant XFRM_IF_ID + for (int selAddrFamily : ADDRESS_FAMILIES) { + mSrvConfig + .getNetdInstance() + .ipSecUpdateSecurityPolicy( + callingUid, + selAddrFamily, + direction, + transformInfo.getConfig().getSourceAddress(), + transformInfo.getConfig().getDestinationAddress(), + spi, // If outbound, also add SPI to the policy. + mark, // Must always set policy mark; ikey/okey for VTIs + 0xffffffff, + c.getXfrmInterfaceId()); } // Update SA with tunnel mark (ikey or okey based on direction) From e6bc8317f94e8b6b52271055a3c1129638019b07 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 21 Nov 2018 21:24:55 -0800 Subject: [PATCH 231/881] Cleanup and update comments SA mark disabling comments This commit cleans up and upates comments with regard to changes in aosp/721999, clarifying the restrictions and potential pitfalls we would see with regards to IPsec tunnel mode without updatable SAs. Bug: 111854872 Test: Compiles, comment-only change Change-Id: I07b0063987463c1a3cf42e112839a31739947c80 --- services/core/java/com/android/server/IpSecService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 71a7a2b5ab..7ee3d3b3bd 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1770,6 +1770,11 @@ public class IpSecService extends IIpSecService.Stub { // and SPs have matching marks (as VTI are meant to be built). // Currently update does nothing with marks. Leave empty (defaulting to 0) to ensure the // config matches the actual allocated resources in the kernel. + // All SAs will have zero marks (from creation time), and any policy that matches the + // same src/dst could match these SAs. Non-IpSecService governed processes that + // establish floating policies with the same src/dst may result in undefined + // behavior. This is generally limited to vendor code due to the permissions + // (CAP_NET_ADMIN) required. // // c.setMarkValue(mark); // c.setMarkMask(0xffffffff); From 724ed1b9218abd8a62f28f18f09fdf53cd74efc2 Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Fri, 23 Nov 2018 12:01:41 +0800 Subject: [PATCH 232/881] Use ParcelFileDescriptor instead of FileDescriptor in INetd.aidl Stable aidl won't support FileDescriptor but ParcelFileDescriptor. In order to migrate to stable aidl, replace all FileDescriptor in INdetd.aidl. Test: runtest frameworks-net passes Change-Id: Icdf37aed0e0cce0352070a437066e77c0f2fd85a --- services/core/java/com/android/server/IpSecService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 7ee3d3b3bd..126bf65565 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1236,7 +1236,8 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner(sockFd, callingUid); + mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner( + new ParcelFileDescriptor(sockFd), callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); Os.bind(sockFd, INADDR_ANY, port); @@ -1696,7 +1697,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecApplyTransportModeTransform( - socket.getFileDescriptor(), + socket, callingUid, direction, c.getSourceAddress(), @@ -1715,7 +1716,7 @@ public class IpSecService extends IIpSecService.Stub { throws RemoteException { mSrvConfig .getNetdInstance() - .ipSecRemoveTransportModeTransform(socket.getFileDescriptor()); + .ipSecRemoveTransportModeTransform(socket); } /** From b8d6e6fb4cfad501b0d781244cdd7f0c9115a095 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 19 Oct 2018 21:14:30 +0800 Subject: [PATCH 233/881] Fix negative uid stats caused by 464xlat adjust when eBPF is on. When using xt_qtaguid to count per uid stats, NetworkStatsService needs to adjust the 464xlat traffic since iptables module would double count for ipv4 and ipv6 packet. But for eBPF, the per uid stats is collected in a different hook, so the adjustment on root uid would only be needed in tx direction. Bug: 112226716 Test: 1. Make ipv4 traffic in ipv6-only network and check data usage. 2. Make ipv4 traffic in a client which connect to ipv6-only hotspot. 3. runtest frameworks-net 4. cts-tradefed run cts -m CtsNetTestCases -t \ android.net.cts.TrafficStatsTest 5. cts-tradefed run cts -m CtsUsageStatsTestCases Change-Id: Ic9a84f5446eddc943c255d5f3b89dad171f53cac Merged-In: Ic9a84f5446eddc943c255d5f3b89dad171f53cac (cherry picked from commit f1307561ad5ac6861229f5d1b26601af8a365d01) (cherry picked from commit a5dc562cf860e903dbd08bbc40baf88485547820) --- core/java/android/net/NetworkStats.java | 24 +++++++++++++------ .../internal/net/NetworkStatsFactory.java | 9 +++---- .../server/net/NetworkStatsService.java | 6 +++-- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index edf9bc1c6b..4bcc245368 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -776,14 +776,19 @@ public class NetworkStats implements Parcelable { * packet needs to be subtracted from the root UID on the base interface both for tx * and rx traffic (http://b/12249687, http:/b/33681750). * + * As for eBPF, the per uid stats is collected by different hook, the rx packets on base + * interface will not be counted. Thus, the adjustment on root uid is only needed in tx + * direction. + * *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only * {@code ConcurrentHashMap} * @param baseTraffic Traffic on the base interfaces. Will be mutated. * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + * @param useBpfStats True if eBPF is in use. */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic, Map stackedIfaces) { + NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { // Total 464xlat traffic to subtract from uid 0 on all base interfaces. // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); @@ -802,15 +807,20 @@ public class NetworkStats implements Parcelable { continue; } // Subtract any 464lat traffic seen for the root UID on the current base interface. + // However, for eBPF, the per uid stats is collected by different hook, the rx packets + // on base interface will not be counted. Thus, the adjustment on root uid is only + // needed in tx direction. adjust.iface = baseIface; - adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + if (!useBpfStats) { + adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); + adjust.rxPackets = -entry.rxPackets; + } adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets = -entry.rxPackets; adjust.txPackets = -entry.txPackets; adjustments.combineValues(adjust); - // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent - // on the stacked interface with prefix "v4-" and drops the IPv6 header size after + // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet + // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes // difference for all packets (http://b/12249687, http:/b/33681750). entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA; @@ -829,8 +839,8 @@ public class NetworkStats implements Parcelable { * base and stacked traffic. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. */ - public void apply464xlatAdjustments(Map stackedIfaces) { - apply464xlatAdjustments(this, this, stackedIfaces); + public void apply464xlatAdjustments(Map stackedIfaces, boolean useBpfStats) { + apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats); } /** diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index c4d08c7dc5..b3cf389c1b 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -113,11 +113,12 @@ public class NetworkStatsFactory { /** * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. - * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map) + * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic) { - NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces); + NetworkStats stackedTraffic, boolean useBpfStats) { + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces, + useBpfStats); } @VisibleForTesting @@ -263,7 +264,7 @@ public class NetworkStatsFactory { // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. // TODO: remove this and only apply adjustments in NetworkStatsService. - stats.apply464xlatAdjustments(sStackedIfaces); + stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); return stats; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 9bf3874088..17ab29d747 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1622,7 +1622,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, + mUseBpfTrafficStats); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( @@ -1632,7 +1633,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats); + NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, + mUseBpfTrafficStats); uidSnapshot.combineAllValues(vtStats); } From 4dfcd506751d80f80ed513f76ebd67818e9d128c Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 8 Nov 2018 22:33:09 +0800 Subject: [PATCH 234/881] Change types of fields of network stats reported to framework. Currently, NetworkStats use int to handle uid, set and tag, while native side using unsigned int mixing with signed int with that. This commit make necessary changes in JNI part while libnetdbpf unifying the types of fields. Bug: 112226716 Bug: 119193941 Test: 1. manually reconnect vpn 2. update apps from playstore 3. atest libnetdbpf_test 4. runtest frameworks-net 5. cts-tradefed run cts -m CtsUsageStatsTestCases -t \ android.app.usage.cts.NetworkUsageStatsTest Change-Id: I6c27124db8292e2825fba51b8994f013897cb566 Merged-In: I6c27124db8292e2825fba51b8994f013897cb566 (cherry picked from commit bf7803eed8283d5a1caa2efe90aa449590ddb94f) (cherry picked from commit a6c3c7e35d01949bdd56a3941beb9935ed5e46cb) --- core/jni/com_android_internal_net_NetworkStatsFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index c15b7ee4fe..de3a78a61a 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -175,7 +175,7 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, } } s.tag = rawTag >> 32; - if (limitTag != -1 && s.tag != limitTag) { + if (limitTag != -1 && s.tag != static_cast(limitTag)) { //ALOGI("skipping due to tag: %s", buffer); continue; } @@ -188,7 +188,7 @@ static int legacyReadNetworkStatsDetail(std::vector* lines, if (sscanf(pos, "%u %u %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, &s.uid, &s.set, &s.rxBytes, &s.rxPackets, &s.txBytes, &s.txPackets) == 6) { - if (limitUid != -1 && limitUid != s.uid) { + if (limitUid != -1 && static_cast(limitUid) != s.uid) { //ALOGI("skipping due to uid: %s", buffer); continue; } From a62125fd557d7e135fcf358cde58878e9b888432 Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 29 Oct 2018 22:26:22 +0800 Subject: [PATCH 235/881] Refactoring of deleting stats in NetworkStats based on uids. In follow-up commits, current API would create new NetworkStats every time when 464xlatAdjustment wants to filtered out some uids. This commit refactors it to delete stats in-place to get better performance. Bug: 118602783 Test: atest FrameworksNetTests Change-Id: I858f95d1fa7733111786243b4e261ce8a70a068d --- core/java/android/net/NetworkStats.java | 38 ++++++++++++++----- .../server/net/NetworkStatsRecorder.java | 2 +- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 5447f595ca..a00b9a3cae 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -44,6 +44,7 @@ import java.util.Objects; * * @hide */ +// @NotThreadSafe public class NetworkStats implements Parcelable { private static final String TAG = "NetworkStats"; /** {@link #iface} value when interface details unavailable. */ @@ -443,6 +444,26 @@ public class NetworkStats implements Parcelable { return entry; } + /** + * If @{code dest} is not equal to @{code src}, copy entry from index @{code src} to index + * @{code dest}. + */ + private void maybeCopyEntry(int dest, int src) { + if (dest == src) return; + iface[dest] = iface[src]; + uid[dest] = uid[src]; + set[dest] = set[src]; + tag[dest] = tag[src]; + metered[dest] = metered[src]; + roaming[dest] = roaming[src]; + defaultNetwork[dest] = defaultNetwork[src]; + rxBytes[dest] = rxBytes[src]; + rxPackets[dest] = rxPackets[src]; + txBytes[dest] = txBytes[src]; + txPackets[dest] = txPackets[src]; + operations[dest] = operations[src]; + } + public long getElapsedRealtime() { return elapsedRealtime; } @@ -941,21 +962,18 @@ public class NetworkStats implements Parcelable { } /** - * Return all rows except those attributed to the requested UID; doesn't - * mutate the original structure. + * Remove all rows that match one of specified UIDs. */ - public NetworkStats withoutUids(int[] uids) { - final NetworkStats stats = new NetworkStats(elapsedRealtime, 10); - - Entry entry = new Entry(); + public void removeUids(int[] uids) { + int nextOutputEntry = 0; for (int i = 0; i < size; i++) { - entry = getValues(i, entry); - if (!ArrayUtils.contains(uids, entry.uid)) { - stats.addValues(entry); + if (!ArrayUtils.contains(uids, uid[i])) { + maybeCopyEntry(nextOutputEntry, i); + nextOutputEntry++; } } - return stats; + size = nextOutputEntry; } /** diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a16dcf358d..a2e7e0cae9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -352,7 +352,7 @@ public class NetworkStatsRecorder { // Clear UID from current stats snapshot if (mLastSnapshot != null) { - mLastSnapshot = mLastSnapshot.withoutUids(uids); + mLastSnapshot.removeUids(uids); } final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; From 3b51392d2cc6dd05e6582bd2ae03ff0b15e53701 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 30 Oct 2018 21:49:38 +0800 Subject: [PATCH 236/881] Ignore ipv6 tx traffic on clat uid. Currently, 464xlat counts its ipv6 tx traffic into root uid. When user is making ipv4 upload over ipv6-only network, ipv4 tx traffic may sometimes be counted faster then ipv6 tx traffic. Thus, NetworkStatsService may detect non-monotonic values due to 464xlat adjustment. So the solution is that: for clatd, make ipv6 tx traffic counts into clat uid, and then ignore it in the framework side. Bug: 118602783 Test: 1. manually verify clatd traffic on clat uid. 2. runtest frameworks-net Change-Id: Ifb478b79e3e281918c70e16d1f90682c78f33db1 --- core/java/android/net/NetworkStats.java | 26 ++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index a00b9a3cae..9cf582bef1 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -16,6 +16,8 @@ package android.net; +import static android.os.Process.CLAT_UID; + import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -828,13 +830,15 @@ public class NetworkStats implements Parcelable { * *

For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 * packet on the stacked interface, and once as translated to an IPv6 packet on the - * base interface. For correct stats accounting on the base interface, every 464xlat - * packet needs to be subtracted from the root UID on the base interface both for tx - * and rx traffic (http://b/12249687, http:/b/33681750). + * base interface. For correct stats accounting on the base interface, if using xt_qtaguid, + * every rx 464xlat packet needs to be subtracted from the root UID on the base interface + * (http://b/12249687, http:/b/33681750), and every tx 464xlat packet which was counted onto + * clat uid should be ignored. * * As for eBPF, the per uid stats is collected by different hook, the rx packets on base - * interface will not be counted. Thus, the adjustment on root uid is only needed in tx - * direction. + * interface will not be counted. Thus, the adjustment on root uid is not needed. However, the + * tx traffic counted in the same way xt_qtaguid does, so the traffic on clat uid still + * needs to be ignored. * *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only * {@code ConcurrentHashMap} @@ -862,17 +866,14 @@ public class NetworkStats implements Parcelable { if (baseIface == null) { continue; } - // Subtract any 464lat traffic seen for the root UID on the current base interface. - // However, for eBPF, the per uid stats is collected by different hook, the rx packets - // on base interface will not be counted. Thus, the adjustment on root uid is only - // needed in tx direction. + // Subtract xt_qtaguid 464lat rx traffic seen for the root UID on the current base + // interface. As for eBPF, the per uid stats is collected by different hook, the rx + // packets on base interface will not be counted. adjust.iface = baseIface; if (!useBpfStats) { adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); adjust.rxPackets = -entry.rxPackets; } - adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); - adjust.txPackets = -entry.txPackets; adjustments.combineValues(adjust); // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet @@ -884,6 +885,9 @@ public class NetworkStats implements Parcelable { stackedTraffic.setValues(i, entry); } + // Traffic on clat uid is v6 tx traffic that is already counted with app uid on the stacked + // v4 interface, so it needs to be removed to avoid double-counting. + baseTraffic.removeUids(new int[] {CLAT_UID}); baseTraffic.combineAllValues(adjustments); } From 1b6c2ed876565ae87a5f102d9555b54c943353c1 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Tue, 11 Dec 2018 19:47:33 +0100 Subject: [PATCH 237/881] API: Clean up redundant and ineffective usages of SystemApi and TestApi Everything that is marked SystemApi or TestApi, but not @hide is still part of the public SDK, it is therefore not sound to have that combination. In the future, specifing such a combination will be considered an error to prevent inadvertently exposing SystemApi and TestApi as public API. Bug: 115333477 Change-Id: Ibd5d6a22862fdbc1e20a1cb3925280f5a682edea Test: METALAVA_PREPEND_ARGS="--error UnhiddenSystemApi" m checkapi Exempt-From-Owner-Approval: API cleanup --- core/java/android/net/TrafficStats.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 22dd4fc362..bbf8f97c88 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -274,7 +274,6 @@ public class TrafficStats { * Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. */ - @SystemApi @SuppressLint("Doclava125") public static void setThreadStatsUid(int uid) { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); @@ -313,7 +312,6 @@ public class TrafficStats { * * @see #setThreadStatsUid(int) */ - @SystemApi @SuppressLint("Doclava125") public static void clearThreadStatsUid() { NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); From 770dbc40656c38fee9d7480cdec9c9b1e75dc3df Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Tue, 11 Dec 2018 19:47:33 +0100 Subject: [PATCH 238/881] API: Clean up redundant and ineffective usages of SystemApi and TestApi Everything that is marked SystemApi or TestApi, but not @hide is still part of the public SDK, it is therefore not sound to have that combination. In the future, specifing such a combination will be considered an error to prevent inadvertently exposing SystemApi and TestApi as public API. Bug: 115333477 Change-Id: Ibd5d6a22862fdbc1e20a1cb3925280f5a682edea Merged-In: Ibd5d6a22862fdbc1e20a1cb3925280f5a682edea Test: METALAVA_PREPEND_ARGS="--error UnhiddenSystemApi" m checkapi Exempt-From-Owner-Approval: API cleanup --- core/java/android/net/TrafficStats.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 1b22911f0c..bbb809d528 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -274,7 +274,6 @@ public class TrafficStats { * Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. */ - @SystemApi @SuppressLint("Doclava125") public static void setThreadStatsUid(int uid) { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); @@ -313,7 +312,6 @@ public class TrafficStats { * * @see #setThreadStatsUid(int) */ - @SystemApi @SuppressLint("Doclava125") public static void clearThreadStatsUid() { NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); From c14b217455d60f2ecdd8d9c2d49a2440e23412be Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Tue, 11 Dec 2018 14:15:57 -0800 Subject: [PATCH 239/881] Delete unused import The hasBpfSupport() check from BpfUtils is not used by the native helper in framework. Remove them. Bug: 111441138 Test: Build without failure. Change-Id: Icdd01bf1a03efd7883e4939d0d730303ec1004e7 --- core/jni/com_android_internal_net_NetworkStatsFactory.cpp | 1 - services/core/jni/com_android_server_net_NetworkStatsService.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index b708735616..24bafca9c3 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -35,7 +35,6 @@ #include "bpf/BpfUtils.h" #include "netdbpf/BpfNetworkStats.h" -using android::bpf::hasBpfSupport; using android::bpf::parseBpfNetworkStatsDetail; using android::bpf::stats_line; diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 649f1a56f0..4d4a7b4164 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -34,7 +34,6 @@ #include "netdbpf/BpfNetworkStats.h" using android::bpf::Stats; -using android::bpf::hasBpfSupport; using android::bpf::bpfGetUidStats; using android::bpf::bpfGetIfaceStats; From 6e17032ff625891e8fcb6b228440aeaf4da9c025 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Sat, 22 Dec 2018 13:20:31 -0800 Subject: [PATCH 240/881] Adjust map names due to new bpfloader With the new loader support added. The bpf map format is defined by bpf kernel program as well. Change the netd bpf program to the new format. Test: CtsUsageStatsTestCases Bug: 112334572 Change-Id: I34e38e0a8cf0cca54dc52ec897771452f9d90525 --- core/java/com/android/internal/net/NetworkStatsFactory.java | 5 ++--- .../java/com/android/server/net/NetworkStatsService.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 0a7cff6856..9bacf9b6c2 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -20,6 +20,7 @@ import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; + import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.annotation.Nullable; @@ -33,10 +34,8 @@ import com.android.internal.util.ProcFileReader; import libcore.io.IoUtils; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileReader; import java.io.IOException; import java.net.ProtocolException; import java.util.Arrays; @@ -127,7 +126,7 @@ public class NetworkStatsFactory { } public NetworkStatsFactory() { - this(new File("/proc/"), new File("/sys/fs/bpf/traffic_uid_stats_map").exists()); + this(new File("/proc/"), new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists()); } @VisibleForTesting diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 82371855bd..538326bcae 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -361,7 +361,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers"); mSystemDir = checkNotNull(systemDir, "missing systemDir"); mBaseDir = checkNotNull(baseDir, "missing baseDir"); - mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists(); + mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists(); } private void registerLocalService() { From 77f9cd1aa62506f38f9fef8ea99942a193880881 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 9 Jan 2019 10:23:20 +0800 Subject: [PATCH 241/881] DO NOT MERGE: Revert: use legacy way to get tcp packet count In Q, legacy way to get tcp packet count is not planned to be supported. Users who use this unsupported API e.g., data stall detection are also planned to be removed. Thus, this change reverts 334a7559650b4 which is the short term solution in P. Bug: 110443385 Test: atest FrameworksNetTests Change-Id: Ia09f908edbf194b9aa873a3bdd5aee7b6fcb16bc --- .../java/com/android/server/net/NetworkStatsService.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 82371855bd..383e1e0288 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -955,13 +955,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getIfaceStats(String iface, int type) { - // eBPF code doesn't provide per-interface TCP counters. Use xt_qtaguid for now. - // TODO: delete getMobileTcp(Rx|Tx)Packets entirely. See b/110443385 . - if (type == TYPE_TCP_TX_PACKETS || type == TYPE_TCP_RX_PACKETS) { - return nativeGetIfaceStat(iface, type, false); - } else { - return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); - } + return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); } @Override From 1915400dd1aed77187c912cc7a1a7897bd7bba4b Mon Sep 17 00:00:00 2001 From: Mike SU Date: Mon, 26 Nov 2018 15:05:13 +0800 Subject: [PATCH 242/881] fix getIfaceStats and getTotalStats bug root cause: getIfaceStats and getTotalStats is directly reading iface_stat_fmt or eBPF, not include tether stats. solution: add tether stats to getIfaceStats and getTotalStats. Bug: 120039819 Test case1: 1. tether offload is enabled on phone, enable MHS on phone. 2. Use test app to check getMobileRxBytes->getIfaceStats 3. Download 10M file on MHS client 4. Use test app to check getMobileRxBytes->getIfaceStats again result: getMobileRxBytes increased around 10M Test case2: 1. tether offload is disabled on phone, enable MHS on phone. repeat above step 2~4 result: getMobileRxBytes increased around 10M Following CTS cases passed run cts -m CtsNetTestCases --test android.net.cts.TrafficStatsTest run cts -m CtsUsageStatsTestCases --test android.app.usage.cts.NetworkUsageStatsTest Change-Id: I3d94acb71c142ec38b750e58822881ff383341cc --- .../server/net/NetworkStatsService.java | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index b0adf954ca..2e7cbc684c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -955,12 +955,64 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getIfaceStats(String iface, int type) { - return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + if (nativeIfaceStats == -1) { + return nativeIfaceStats; + } else { + // When tethering offload is in use, nativeIfaceStats does not contain usage from + // offload, add it back here. + // When tethering offload is not in use, nativeIfaceStats contains tethering usage. + // this does not cause double-counting of tethering traffic, because + // NetdTetheringStatsProvider returns zero NetworkStats + // when called with STATS_PER_IFACE. + return nativeIfaceStats + getTetherStats(iface, type); + } } @Override public long getTotalStats(int type) { - return nativeGetTotalStat(type, checkBpfStatsEnable()); + long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable()); + if (nativeTotalStats == -1) { + return nativeTotalStats; + } else { + // Refer to comment in getIfaceStats + return nativeTotalStats + getTetherStats(IFACE_ALL, type); + } + } + + private long getTetherStats(String iface, int type) { + final NetworkStats tetherSnapshot; + final long token = Binder.clearCallingIdentity(); + try { + tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); + } catch (RemoteException e) { + Slog.w(TAG, "Error get TetherStats: " + e); + return 0; + } finally { + Binder.restoreCallingIdentity(token); + } + HashSet limitIfaces; + if (iface == IFACE_ALL) { + limitIfaces = null; + } else { + limitIfaces = new HashSet(); + limitIfaces.add(iface); + } + NetworkStats.Entry entry = tetherSnapshot.getTotal(null, limitIfaces); + if (LOGD) Slog.d(TAG, "TetherStats: iface=" + iface + " type=" + type + + " entry=" + entry); + switch (type) { + case 0: // TYPE_RX_BYTES + return entry.rxBytes; + case 1: // TYPE_RX_PACKETS + return entry.rxPackets; + case 2: // TYPE_TX_BYTES + return entry.txBytes; + case 3: // TYPE_TX_PACKETS + return entry.txPackets; + default: + return 0; + } } private boolean checkBpfStatsEnable() { From 545110b5bc0451aaaa90d6cd12337676a39424de Mon Sep 17 00:00:00 2001 From: Sal Savage Date: Wed, 9 Jan 2019 15:46:08 -0800 Subject: [PATCH 243/881] Allow network transport type override Bug: b/112588045 Test: atest EthernetServiceTests --verbose Test: kitchensink with RPi devices connected by USB -> Ethernet adapters. Edit config.xml to try different tranport overrides manually. Use dumpsys ethernet to show final final network scores. Change-Id: I482e78a76d06c9c090aa6816db14bb346eb6528b --- .../ethernet/EthernetNetworkFactory.java | 119 +++++++++- .../server/ethernet/EthernetTracker.java | 76 +++++- .../server/ethernet/EthernetTrackerTest.java | 216 ++++++++++++++++-- 3 files changed, 377 insertions(+), 34 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 54bcdc3b35..1f4f7fac90 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,9 +16,11 @@ package com.android.server.ethernet; -import static android.net.ConnectivityManager.TYPE_ETHERNET; +import static com.android.internal.util.Preconditions.checkNotNull; +import android.annotation.NonNull; import android.content.Context; +import android.net.ConnectivityManager; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -37,10 +39,12 @@ import android.net.util.InterfaceParams; import android.os.Handler; import android.text.TextUtils; import android.util.Log; +import android.util.SparseArray; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; +import java.lang.Math; import java.util.concurrent.ConcurrentHashMap; /** @@ -239,6 +243,52 @@ public class EthernetNetworkFactory extends NetworkFactory { private NetworkAgent mNetworkAgent; private IpConfiguration mIpConfig; + /** + * An object to contain all transport type information, including base network score and + * the legacy transport type it maps to (if any) + */ + private static class TransportInfo { + final int mLegacyType; + final int mScore; + + private TransportInfo(int legacyType, int score) { + mLegacyType = legacyType; + mScore = score; + } + } + + /** + * A map of TRANSPORT_* types to TransportInfo, making scoring and legacy type information + * available for each type an ethernet interface could propagate. + * + * Unfortunately, base scores for the various transports are not yet centrally located. + * They've been lifted from the corresponding NetworkFactory files in the meantime. + * + * Additionally, there are no legacy type equivalents to LOWPAN or WIFI_AWARE. These types + * are set to TYPE_NONE to match the behavior of their own network factories. + */ + private static final SparseArray sTransports = new SparseArray(); + static { + // LowpanInterfaceTracker.NETWORK_SCORE + sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN, + new TransportInfo(ConnectivityManager.TYPE_NONE, 30)); + // WifiAwareDataPathStateManager.NETWORK_FACTORY_SCORE_AVAIL + sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE, + new TransportInfo(ConnectivityManager.TYPE_NONE, 1)); + // EthernetNetworkFactory.NETWORK_SCORE + sTransports.put(NetworkCapabilities.TRANSPORT_ETHERNET, + new TransportInfo(ConnectivityManager.TYPE_ETHERNET, 70)); + // BluetoothTetheringNetworkFactory.NETWORK_SCORE + sTransports.put(NetworkCapabilities.TRANSPORT_BLUETOOTH, + new TransportInfo(ConnectivityManager.TYPE_BLUETOOTH, 69)); + // WifiNetworkFactory.SCORE_FILTER / NetworkAgent.WIFI_BASE_SCORE + sTransports.put(NetworkCapabilities.TRANSPORT_WIFI, + new TransportInfo(ConnectivityManager.TYPE_WIFI, 60)); + // TelephonyNetworkFactory.TELEPHONY_NETWORK_SCORE + sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR, + new TransportInfo(ConnectivityManager.TYPE_MOBILE, 50)); + } + long refCount = 0; private final IpClient.Callback mIpClientCallback = new IpClient.Callback() { @@ -259,14 +309,23 @@ public class EthernetNetworkFactory extends NetworkFactory { }; NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, - NetworkCapabilities capabilities) { + @NonNull NetworkCapabilities capabilities) { name = ifaceName; - mCapabilities = capabilities; + mCapabilities = checkNotNull(capabilities); mHandler = handler; mContext = context; + int legacyType = ConnectivityManager.TYPE_NONE; + int[] transportTypes = mCapabilities.getTransportTypes(); + if (transportTypes.length > 0) { + legacyType = getLegacyType(transportTypes[0]); + } else { + // Should never happen as transport is always one of ETHERNET or a valid override + Log.w(TAG, "There is no transport type associated with network interface '" + + mLinkProperties.getInterfaceName() + "' -- Legacy type set to TYPE_NONE"); + } mHwAddress = hwAddress; - mNetworkInfo = new NetworkInfo(TYPE_ETHERNET, 0, NETWORK_TYPE, ""); + mNetworkInfo = new NetworkInfo(legacyType, 0, NETWORK_TYPE, ""); mNetworkInfo.setExtraInfo(mHwAddress); mNetworkInfo.setIsAvailable(true); } @@ -283,6 +342,47 @@ public class EthernetNetworkFactory extends NetworkFactory { return mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } + /** + * Determines the legacy transport type from a NetworkCapabilities transport type. Defaults + * to legacy TYPE_NONE if there is no known conversion + */ + private static int getLegacyType(int transport) { + TransportInfo transportInfo = sTransports.get(transport, /* if dne */ null); + if (transportInfo != null) { + return transportInfo.mLegacyType; + } + return ConnectivityManager.TYPE_NONE; + } + + /** + * Determines the network score based on the transport associated with the interface. + * Ethernet interfaces could propagate a transport types forward. Since we can't + * get more information about the statuses of the interfaces on the other end of the local + * interface, we'll best-effort assign the score as the base score of the assigned transport + * when the link is up. When the link is down, the score is set to zero. + * + * This function is called with the purpose of assigning and updating the network score of + * the member NetworkAgent. + */ + private int getNetworkScore() { + // never set the network score below 0. + if (!mLinkUp) { + return 0; + } + + int[] transportTypes = mCapabilities.getTransportTypes(); + if (transportTypes.length < 1) { + Log.w(TAG, "There is no transport type associated with network interface '" + + mLinkProperties.getInterfaceName() + "' -- Score set to zero"); + return 0; + } + TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null); + if (transportInfo != null) { + return transportInfo.mScore; + } + return 0; + } + private void start() { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); @@ -317,7 +417,7 @@ public class EthernetNetworkFactory extends NetworkFactory { // Create our NetworkAgent. mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties, - NETWORK_SCORE) { + getNetworkScore()) { public void unwanted() { if (this == mNetworkAgent) { stop(); @@ -390,8 +490,11 @@ public class EthernetNetworkFactory extends NetworkFactory { mNetworkAgent.sendNetworkCapabilities(mCapabilities); mNetworkAgent.sendNetworkInfo(mNetworkInfo); mNetworkAgent.sendLinkProperties(mLinkProperties); - // never set the network score below 0. - mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0); + + // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now + // since the agent isn't update frequently. Consider caching the score in the future if + // agent updating is required more often + mNetworkAgent.sendNetworkScore(getNetworkScore()); } private void clear() { @@ -433,7 +536,9 @@ public class EthernetNetworkFactory extends NetworkFactory { + "up: " + mLinkUp + ", " + "hwAddress: " + mHwAddress + ", " + "networkInfo: " + mNetworkInfo + ", " + + "networkCapabilities: " + mCapabilities + ", " + "networkAgent: " + mNetworkAgent + ", " + + "score: " + getNetworkScore() + ", " + "ipClient: " + mIpClient + "," + "linkProperties: " + mLinkProperties + "}"; diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 00eedd502d..099e05414c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -294,12 +294,20 @@ final class EthernetTracker { } } + /** + * Parses an Ethernet interface configuration + * + * @param configString represents an Ethernet configuration in the following format: {@code + * ;[Network Capabilities];[IP config];[Override Transport]} + */ private void parseEthernetConfig(String configString) { - String[] tokens = configString.split(";"); + String[] tokens = configString.split(";", /* limit of tokens */ 4); String name = tokens[0]; String capabilities = tokens.length > 1 ? tokens[1] : null; + String transport = tokens.length > 3 ? tokens[3] : null; NetworkCapabilities nc = createNetworkCapabilities( - !TextUtils.isEmpty(capabilities) /* clear default capabilities */, capabilities); + !TextUtils.isEmpty(capabilities) /* clear default capabilities */, capabilities, + transport); mNetworkCapabilities.put(name, nc); if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) { @@ -320,24 +328,76 @@ final class EthernetTracker { } private static NetworkCapabilities createNetworkCapabilities(boolean clearDefaultCapabilities) { - return createNetworkCapabilities(clearDefaultCapabilities, null); + return createNetworkCapabilities(clearDefaultCapabilities, null, null); } - private static NetworkCapabilities createNetworkCapabilities( - boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities) { + /** + * Parses a static list of network capabilities + * + * @param clearDefaultCapabilities Indicates whether or not to clear any default capabilities + * @param commaSeparatedCapabilities A comma separated string list of integer encoded + * NetworkCapability.NET_CAPABILITY_* values + * @param overrideTransport A string representing a single override transport type, must be one + * of the NetworkCapability.TRANSPORT_* values. TRANSPORT_VPN is + * not supported. Errors with input will cause the override to + * be ignored. + */ + @VisibleForTesting + static NetworkCapabilities createNetworkCapabilities( + boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities, + @Nullable String overrideTransport) { NetworkCapabilities nc = new NetworkCapabilities(); if (clearDefaultCapabilities) { - nc.clearAll(); // Remove default capabilities. + nc.clearAll(); // Remove default capabilities and transports } - nc.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); + + // Determine the transport type. If someone has tried to define an override transport then + // attempt to add it. Since we can only have one override, all errors with it will + // gracefully default back to TRANSPORT_ETHERNET and warn the user. VPN is not allowed as an + // override type. Wifi Aware and LoWPAN are currently unsupported as well. + int transport = NetworkCapabilities.TRANSPORT_ETHERNET; + if (!TextUtils.isEmpty(overrideTransport)) { + try { + int parsedTransport = Integer.valueOf(overrideTransport); + if (parsedTransport == NetworkCapabilities.TRANSPORT_VPN + || parsedTransport == NetworkCapabilities.TRANSPORT_WIFI_AWARE + || parsedTransport == NetworkCapabilities.TRANSPORT_LOWPAN) { + Log.e(TAG, "Override transport '" + parsedTransport + "' is not supported -- " + + "Defaulting to TRANSPORT_ETHERNET"); + } else { + transport = parsedTransport; + } + } catch (NumberFormatException nfe) { + Log.e(TAG, "Override transport type '" + overrideTransport + "' could not be parsed" + + "-- Defaulting to TRANSPORT_ETHERNET"); + } + } + + // Apply the transport. If the user supplied a valid number that is not a valid transport + // then adding will throw an exception. Default back to TRANSPORT_ETHERNET if that happens + try { + nc.addTransportType(transport); + } catch (IllegalArgumentException iae) { + Log.e(TAG, transport + " is not a valid NetworkCapability.TRANSPORT_* value" + + " -- Defaulting to TRANSPORT_ETHERNET"); + nc.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); + } + nc.setLinkUpstreamBandwidthKbps(100 * 1000); nc.setLinkDownstreamBandwidthKbps(100 * 1000); if (!TextUtils.isEmpty(commaSeparatedCapabilities)) { for (String strNetworkCapability : commaSeparatedCapabilities.split(",")) { if (!TextUtils.isEmpty(strNetworkCapability)) { - nc.addCapability(Integer.valueOf(strNetworkCapability)); + try { + nc.addCapability(Integer.valueOf(strNetworkCapability)); + } catch (NumberFormatException nfe) { + Log.e(TAG, "Capability '" + strNetworkCapability + "' could not be parsed"); + } catch (IllegalArgumentException iae) { + Log.e(TAG, strNetworkCapability + " is not a valid " + + "NetworkCapability.NET_CAPABILITY_* value"); + } } } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 70d316dbff..a56c9fe9fa 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -23,6 +23,7 @@ import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; +import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; @@ -35,47 +36,55 @@ import java.net.InetAddress; @SmallTest @RunWith(AndroidJUnit4.class) public class EthernetTrackerTest { - + /** + * Test: Creation of various valid static IP configurations + */ @Test public void createStaticIpConfiguration() { - assertStaticConfiguration("", new StaticIpConfiguration()); + // Empty gives default StaticIPConfiguration object + assertStaticConfiguration(new StaticIpConfiguration(), ""); + // Setting only the IP address properly cascades and assumes defaults assertStaticConfiguration( - "ip=192.0.2.10/24", - new StaticIpConfigBuilder().setIp("192.0.2.10/24").build()); + new StaticIpConfigBuilder().setIp("192.0.2.10/24").build(), + "ip=192.0.2.10/24"); + // Setting other fields properly cascades them assertStaticConfiguration( - "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android", new StaticIpConfigBuilder() .setIp("192.0.2.10/24") .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) .setGateway("192.0.2.1") .setDomains("android") - .build()); + .build(), + "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android"); // Verify order doesn't matter assertStaticConfiguration( - "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 ", new StaticIpConfigBuilder() .setIp("192.0.2.10/24") .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) .setGateway("192.0.2.1") .setDomains("android") - .build()); + .build(), + "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 "); } + /** + * Test: Attempt creation of various bad static IP configurations + */ @Test public void createStaticIpConfiguration_Bad() { - assertFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key - assertFails("ip=192.0.2.1"); // mask is missing - assertFails("ip=a.b.c"); // not a valid ip address - assertFails("dns=4.4.4.4,1.2.3.A"); // not valid ip address in dns - assertFails("="); // Key and value is empty - assertFails("ip="); // Value is empty - assertFails("ip=192.0.2.1/24 gateway="); // Gateway is empty + assertStaticConfigurationFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key + assertStaticConfigurationFails("ip=192.0.2.1"); // mask is missing + assertStaticConfigurationFails("ip=a.b.c"); // not a valid ip address + assertStaticConfigurationFails("dns=4.4.4.4,1.2.3.A"); // not valid ip address in dns + assertStaticConfigurationFails("="); // Key and value is empty + assertStaticConfigurationFails("ip="); // Value is empty + assertStaticConfigurationFails("ip=192.0.2.1/24 gateway="); // Gateway is empty } - private void assertFails(String config) { + private void assertStaticConfigurationFails(String config) { try { EthernetTracker.parseStaticIpConfiguration(config); fail("Expected to fail: " + config); @@ -84,8 +93,8 @@ public class EthernetTrackerTest { } } - private void assertStaticConfiguration(String configAsString, - StaticIpConfiguration expectedStaticIpConfig) { + private void assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig, + String configAsString) { IpConfiguration expectedIpConfiguration = new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, expectedStaticIpConfig, null); @@ -118,9 +127,178 @@ public class EthernetTrackerTest { return this; } - StaticIpConfiguration build() { return new StaticIpConfiguration(config); } } + + /** + * Test: Attempt to create a capabilties with various valid sets of capabilities/transports + */ + @Test + public void createNetworkCapabilities() { + + // Particularly common expected results + NetworkCapabilities defaultEthernetCleared = new NetworkCapabilitiesBuilder() + .clearAll() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .build(); + + NetworkCapabilities ethernetClearedWithCommonCaps = new NetworkCapabilitiesBuilder() + .clearAll() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .addCapability(12) + .addCapability(13) + .addCapability(14) + .addCapability(15) + .build(); + + // Empty capabilities and transports lists with a "please clear defaults" should + // yield an empty capabilities set with TRANPORT_ETHERNET + assertNetworkCapabilities(defaultEthernetCleared, true, "", ""); + + // Empty capabilities and transports without the clear defaults flag should return the + // default capabilities set with TRANSPORT_ETHERNET + assertNetworkCapabilities( + new NetworkCapabilitiesBuilder() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .build(), + false, "", ""); + + // A list of capabilities without the clear defaults flag should return the default + // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET + assertNetworkCapabilities( + new NetworkCapabilitiesBuilder() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .addCapability(11) + .addCapability(12) + .build(), + false, "11,12", ""); + + // Adding a list of capabilities with a clear defaults will leave exactly those capabilities + // with a default TRANSPORT_ETHERNET since no overrides are specified + assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", ""); + + // Adding any invalid capabilities to the list will cause them to be ignored + assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", ""); + assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", ""); + + // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport + // and apply only the override to the capabiltities object + assertNetworkCapabilities( + new NetworkCapabilitiesBuilder() + .clearAll() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(0) + .build(), + true, "", "0"); + assertNetworkCapabilities( + new NetworkCapabilitiesBuilder() + .clearAll() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(1) + .build(), + true, "", "1"); + assertNetworkCapabilities( + new NetworkCapabilitiesBuilder() + .clearAll() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(2) + .build(), + true, "", "2"); + assertNetworkCapabilities( + new NetworkCapabilitiesBuilder() + .clearAll() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(3) + .build(), + true, "", "3"); + + // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANPORT_ETHERNET + assertNetworkCapabilities(defaultEthernetCleared, true, "", "4"); + + // "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE + // conversion. When that becomes available, this test must be updated + assertNetworkCapabilities(defaultEthernetCleared, true, "", "5"); + + // "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE + // conversion. When that becomes available, this test must be updated + assertNetworkCapabilities(defaultEthernetCleared, true, "", "6"); + + // Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET + assertNetworkCapabilities(defaultEthernetCleared,true, "", "100"); + assertNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg"); + + // Ensure the adding of both capabilities and transports work + assertNetworkCapabilities( + new NetworkCapabilitiesBuilder() + .clearAll() + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addCapability(12) + .addCapability(13) + .addCapability(14) + .addCapability(15) + .addTransport(3) + .build(), + true, "12,13,14,15", "3"); + + // Ensure order does not matter for capability list + assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", ""); + } + + private void assertNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities, + boolean clearCapabilties, String configCapabiltiies,String configTransports) { + assertEquals(expectedNetworkCapabilities, + EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies, + configTransports)); + } + + private static class NetworkCapabilitiesBuilder { + private final NetworkCapabilities nc = new NetworkCapabilities(); + + NetworkCapabilitiesBuilder clearAll(){ + // This is THE ONLY one that doesn't return a reference to the object so I wrapped + // everything in a builder to keep things consistent and clean above. Fix if this + // ever changes + nc.clearAll(); + return this; + } + + NetworkCapabilitiesBuilder addCapability(int capability) { + nc.addCapability(capability); + return this; + } + + NetworkCapabilitiesBuilder addTransport(int transport) { + nc.addTransportType(transport); + return this; + } + + NetworkCapabilitiesBuilder setLinkUpstreamBandwidthKbps(int upKbps) { + nc.setLinkUpstreamBandwidthKbps(upKbps); + return this; + } + + NetworkCapabilitiesBuilder setLinkDownstreamBandwidthKbps(int downKbps) { + nc.setLinkDownstreamBandwidthKbps(downKbps); + return this; + } + + NetworkCapabilities build() { + return new NetworkCapabilities(nc); + } + } } From 6d52547595fd60d0284174d6888ae88c35928a30 Mon Sep 17 00:00:00 2001 From: Mike SU Date: Mon, 26 Nov 2018 15:05:13 +0800 Subject: [PATCH 244/881] fix getIfaceStats and getTotalStats bug root cause: getIfaceStats and getTotalStats is directly reading iface_stat_fmt or eBPF, not include tether stats. solution: add tether stats to getIfaceStats and getTotalStats. Clean cherry-pick of aosp/848934 Bug: 120039819 Test case1: 1. tether offload is enabled on phone, enable MHS on phone. 2. Use test app to check getMobileRxBytes->getIfaceStats 3. Download 10M file on MHS client 4. Use test app to check getMobileRxBytes->getIfaceStats again result: getMobileRxBytes increased around 10M Test case2: 1. tether offload is disabled on phone, enable MHS on phone. repeat above step 2~4 result: getMobileRxBytes increased around 10M Following CTS cases passed run cts -m CtsNetTestCases --test android.net.cts.TrafficStatsTest run cts -m CtsUsageStatsTestCases --test android.app.usage.cts.NetworkUsageStatsTest Change-Id: I3d94acb71c142ec38b750e58822881ff383341cc --- .../server/net/NetworkStatsService.java | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 8c274e42c9..bffd60bcb8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -962,12 +962,64 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getIfaceStats(String iface, int type) { - return nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + if (nativeIfaceStats == -1) { + return nativeIfaceStats; + } else { + // When tethering offload is in use, nativeIfaceStats does not contain usage from + // offload, add it back here. + // When tethering offload is not in use, nativeIfaceStats contains tethering usage. + // this does not cause double-counting of tethering traffic, because + // NetdTetheringStatsProvider returns zero NetworkStats + // when called with STATS_PER_IFACE. + return nativeIfaceStats + getTetherStats(iface, type); + } } @Override public long getTotalStats(int type) { - return nativeGetTotalStat(type, checkBpfStatsEnable()); + long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable()); + if (nativeTotalStats == -1) { + return nativeTotalStats; + } else { + // Refer to comment in getIfaceStats + return nativeTotalStats + getTetherStats(IFACE_ALL, type); + } + } + + private long getTetherStats(String iface, int type) { + final NetworkStats tetherSnapshot; + final long token = Binder.clearCallingIdentity(); + try { + tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); + } catch (RemoteException e) { + Slog.w(TAG, "Error get TetherStats: " + e); + return 0; + } finally { + Binder.restoreCallingIdentity(token); + } + HashSet limitIfaces; + if (iface == IFACE_ALL) { + limitIfaces = null; + } else { + limitIfaces = new HashSet(); + limitIfaces.add(iface); + } + NetworkStats.Entry entry = tetherSnapshot.getTotal(null, limitIfaces); + if (LOGD) Slog.d(TAG, "TetherStats: iface=" + iface + " type=" + type + + " entry=" + entry); + switch (type) { + case 0: // TYPE_RX_BYTES + return entry.rxBytes; + case 1: // TYPE_RX_PACKETS + return entry.rxPackets; + case 2: // TYPE_TX_BYTES + return entry.txBytes; + case 3: // TYPE_TX_PACKETS + return entry.txPackets; + default: + return 0; + } } private boolean checkBpfStatsEnable() { From e4e5381e0fe89074ebc807e33635b96acc2ec2df Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Thu, 10 Jan 2019 14:48:54 -0800 Subject: [PATCH 245/881] Use delta reads for per uid traffic stats For the detailed network stats of each uid and tag, the native implementation provides delta read instead of consistent stats data since boot. Every time the readNetworkStatsDetail function gets called, the data pulled will be cleared. We will keep a persistent data since boot in NetworkStatsService instead. Fixed some checkstyle complains in related files as well. Bug: 79171384 Test: android.app.usage.cts.NetworkUsageStatsTest NetworkStatsServiceTest Change-Id: I50bcf278739135081d522e50b0e88d76fd9ab131 --- .../internal/net/NetworkStatsFactory.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 9bacf9b6c2..f8483461c2 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -64,6 +64,9 @@ public class NetworkStatsFactory { private boolean mUseBpfStats; + // A persistent Snapshot since device start for eBPF stats + private final NetworkStats mPersistSnapshot; + // TODO: only do adjustments in NetworkStatsService and remove this. /** * (Stacked interface) -> (base interface) association for all connected ifaces since boot. @@ -135,6 +138,7 @@ public class NetworkStatsFactory { mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; + mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); } public NetworkStats readBpfNetworkStatsDev() throws IOException { @@ -268,6 +272,7 @@ public class NetworkStatsFactory { return stats; } + // TODO: delete the lastStats parameter private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces, int limitTag, NetworkStats lastStats) throws IOException { if (USE_NATIVE_PARSING) { @@ -278,16 +283,28 @@ public class NetworkStatsFactory { } else { stats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } - if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, - limitIfaces, limitTag, mUseBpfStats) != 0) { - throw new IOException("Failed to parse network stats"); + if (mUseBpfStats) { + if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, + null, TAG_ALL, mUseBpfStats) != 0) { + throw new IOException("Failed to parse network stats"); + } + mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime()); + mPersistSnapshot.combineAllValues(stats); + NetworkStats result = mPersistSnapshot.clone(); + result.filter(limitUid, limitIfaces, limitTag); + return result; + } else { + if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, + limitIfaces, limitTag, mUseBpfStats) != 0) { + throw new IOException("Failed to parse network stats"); + } + if (SANITY_CHECK_NATIVE) { + final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid, + limitIfaces, limitTag); + assertEquals(javaStats, stats); + } + return stats; } - if (SANITY_CHECK_NATIVE) { - final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid, - limitIfaces, limitTag); - assertEquals(javaStats, stats); - } - return stats; } else { return javaReadNetworkStatsDetail(mStatsXtUid, limitUid, limitIfaces, limitTag); } From 43ac4781a5ea312040e9ac8ba3d52f39e818978d Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 10 Jan 2019 19:12:46 +0900 Subject: [PATCH 246/881] Move IpClient to NetworkStack Test: atest FrameworksNetTests NetworkStackTests Bug: b/112869080 Change-Id: I7d00848c052382cd1b6ce458868bed6a1e9e8ec5 --- services/core/java/com/android/server/IpSecService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 126bf65565..371276fbd2 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -44,7 +44,7 @@ import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.net.TrafficStats; -import android.net.util.NetdService; +import android.net.shared.NetdService; import android.os.Binder; import android.os.IBinder; import android.os.ParcelFileDescriptor; From f8cfbebf2c147c16704884312807e9bbb0680eec Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 4 Dec 2018 11:54:16 +0900 Subject: [PATCH 247/881] Migrate EthernetNetworkFactory to IIpClient Test: atest EthernetServiceTests Bug: b/112869080 Change-Id: I54f32d3031e63c7dea78936b6fe5e83e5b293c33 --- .../ethernet/EthernetNetworkFactory.java | 88 +++++++++++++++---- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 1f4f7fac90..4a1d6587d9 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,6 +16,8 @@ package com.android.server.ethernet; +import static android.net.ConnectivityManager.TYPE_ETHERNET; +import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -33,10 +35,14 @@ import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.StringNetworkSpecifier; -import android.net.ip.IpClient; -import android.net.ip.IpClient.ProvisioningConfiguration; +import android.net.ip.IIpClient; +import android.net.ip.IpClientCallbacks; +import android.net.ip.IpClientUtil; +import android.net.shared.ProvisioningConfiguration; import android.net.util.InterfaceParams; +import android.os.ConditionVariable; import android.os.Handler; +import android.os.RemoteException; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; @@ -239,7 +245,8 @@ public class EthernetNetworkFactory extends NetworkFactory { private boolean mLinkUp; private LinkProperties mLinkProperties = new LinkProperties(); - private IpClient mIpClient; + private volatile IIpClient mIpClient; + private IpClientCallbacksImpl mIpClientCallback; private NetworkAgent mNetworkAgent; private IpConfiguration mIpConfig; @@ -291,7 +298,24 @@ public class EthernetNetworkFactory extends NetworkFactory { long refCount = 0; - private final IpClient.Callback mIpClientCallback = new IpClient.Callback() { + private class IpClientCallbacksImpl extends IpClientCallbacks { + private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); + private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); + + @Override + public void onIpClientCreated(IIpClient ipClient) { + mIpClient = ipClient; + mIpClientStartCv.open(); + } + + private void awaitIpClientStart() { + mIpClientStartCv.block(); + } + + private void awaitIpClientShutdown() { + mIpClientShutdownCv.block(); + } + @Override public void onProvisioningSuccess(LinkProperties newLp) { mHandler.post(() -> onIpLayerStarted(newLp)); @@ -306,7 +330,21 @@ public class EthernetNetworkFactory extends NetworkFactory { public void onLinkPropertiesChange(LinkProperties newLp) { mHandler.post(() -> updateLinkProperties(newLp)); } - }; + + @Override + public void onQuit() { + mIpClient = null; + mIpClientShutdownCv.open(); + } + } + + private static void shutdownIpClient(IIpClient ipClient) { + try { + ipClient.shutdown(); + } catch (RemoteException e) { + Log.e(TAG, "Error stopping IpClient", e); + } + } NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, @NonNull NetworkCapabilities capabilities) { @@ -394,9 +432,9 @@ public class EthernetNetworkFactory extends NetworkFactory { } mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress); - - mIpClient = new IpClient(mContext, name, mIpClientCallback); - + mIpClientCallback = new IpClientCallbacksImpl(); + IpClientUtil.makeIpClient(mContext, name, mIpClientCallback); + mIpClientCallback.awaitIpClientStart(); if (sTcpBufferSizes == null) { sTcpBufferSizes = mContext.getResources().getString( com.android.internal.R.string.config_ethernet_tcp_buffers); @@ -461,11 +499,13 @@ public class EthernetNetworkFactory extends NetworkFactory { } void stop() { + // Invalidate all previous start requests if (mIpClient != null) { - mIpClient.shutdown(); - mIpClient.awaitShutdown(); + shutdownIpClient(mIpClient); + mIpClientCallback.awaitIpClientShutdown(); mIpClient = null; } + mIpClientCallback = null; // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: @@ -503,29 +543,41 @@ public class EthernetNetworkFactory extends NetworkFactory { mNetworkInfo.setIsAvailable(false); } - private static void provisionIpClient(IpClient ipClient, IpConfiguration config, + private static void provisionIpClient(IIpClient ipClient, IpConfiguration config, String tcpBufferSizes) { if (config.getProxySettings() == ProxySettings.STATIC || config.getProxySettings() == ProxySettings.PAC) { - ipClient.setHttpProxy(config.getHttpProxy()); + try { + ipClient.setHttpProxy(toStableParcelable(config.getHttpProxy())); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } if (!TextUtils.isEmpty(tcpBufferSizes)) { - ipClient.setTcpBufferSizes(tcpBufferSizes); + try { + ipClient.setTcpBufferSizes(tcpBufferSizes); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } final ProvisioningConfiguration provisioningConfiguration; if (config.getIpAssignment() == IpAssignment.STATIC) { - provisioningConfiguration = IpClient.buildProvisioningConfiguration() + provisioningConfiguration = new ProvisioningConfiguration.Builder() .withStaticConfiguration(config.getStaticIpConfiguration()) .build(); } else { - provisioningConfiguration = IpClient.buildProvisioningConfiguration() + provisioningConfiguration = new ProvisioningConfiguration.Builder() .withProvisioningTimeoutMs(0) .build(); } - ipClient.startProvisioning(provisioningConfiguration); + try { + ipClient.startProvisioning(provisioningConfiguration.toStableParcelable()); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } @Override @@ -554,9 +606,9 @@ public class EthernetNetworkFactory extends NetworkFactory { NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface); pw.println(iface + ":" + ifaceState); pw.increaseIndent(); - final IpClient ipClient = ifaceState.mIpClient; + final IIpClient ipClient = ifaceState.mIpClient; if (ipClient != null) { - ipClient.dump(fd, pw, args); + IpClientUtil.dumpIpClient(ipClient, fd, pw, args); } else { pw.println("IpClient is null"); } From a71a38b32943c992e4fe51a090d36d42ab25ac52 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 25 Jan 2019 14:28:26 +0800 Subject: [PATCH 248/881] Hide Keepalive offload API in IpSec Since the new keepalive API is exported in ConnectivityManager, hide Keepalive API in IpSec, also make system-current.txt sync for this part. Bug: 114151147 Test: m -j Change-Id: I076030bdbab1cd7d69f6a034577d529970b050dc --- core/java/android/net/IpSecTransform.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 23c8aa368d..e519fdf65e 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -257,7 +257,6 @@ public final class IpSecTransform implements AutoCloseable { * * @hide */ - @SystemApi public static class NattKeepaliveCallback { /** The specified {@code Network} is not connected. */ public static final int ERROR_INVALID_NETWORK = 1; @@ -288,7 +287,6 @@ public final class IpSecTransform implements AutoCloseable { * * @hide */ - @SystemApi @RequiresPermission(anyOf = { android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD @@ -331,7 +329,6 @@ public final class IpSecTransform implements AutoCloseable { * * @hide */ - @SystemApi @RequiresPermission(anyOf = { android.Manifest.permission.MANAGE_IPSEC_TUNNELS, android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD From 38784a056dbeb0c1c0d2eb8d34d77f1fad302181 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 23 Jan 2019 23:11:12 +0900 Subject: [PATCH 249/881] Add SocketUtils for NetworkStack These utilities can only be used for privileged apps. The underlying implementation cannot be @SystemApi. Test: m Bug: 112869080 Change-Id: Idfa90561102e5b03ab2b79486d3ad46457128bf8 --- core/java/android/net/TrafficStats.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index bbf8f97c88..49c6f74b1a 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -128,10 +128,14 @@ public class TrafficStats { public static final int TAG_SYSTEM_APP = 0xFFFFFF05; /** @hide */ + @SystemApi + @TestApi public static final int TAG_SYSTEM_DHCP = 0xFFFFFF40; /** @hide */ public static final int TAG_SYSTEM_NTP = 0xFFFFFF41; /** @hide */ + @SystemApi + @TestApi public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42; /** @hide */ public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF43; @@ -140,6 +144,8 @@ public class TrafficStats { /** @hide */ public static final int TAG_SYSTEM_PAC = 0xFFFFFF45; /** @hide */ + @SystemApi + @TestApi public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46; private static INetworkStatsService sStatsService; From 079fe596922fa71ae286d3538d2c6e04743e3660 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Mon, 28 Jan 2019 10:39:10 -0800 Subject: [PATCH 250/881] jni: more O_CLOEXECs Prevent FDs from leaking across an execve() boundary. Test: compiles and boots Change-Id: I5f91046917b55b6abead0a5c6e939f82814e6f18 --- core/jni/com_android_internal_net_NetworkStatsFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 24bafca9c3..8259ffcd41 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -95,7 +95,7 @@ static jlongArray get_long_array(JNIEnv* env, jobject obj, jfieldID field, int s static int legacyReadNetworkStatsDetail(std::vector* lines, const std::vector& limitIfaces, int limitTag, int limitUid, const char* path) { - FILE* fp = fopen(path, "r"); + FILE* fp = fopen(path, "re"); if (fp == NULL) { return -1; } From 731f7bc00b71acc6ebfeecc30aa72f5e2f14239d Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 29 Jan 2019 15:38:52 +0900 Subject: [PATCH 251/881] Remove last NetworkStack usage of hidden APIs Includes various small changes to stop using hidden APIs Test: make NetworkStack Test: flashed, booted, WiFi and tethering working Bug: 112869080 Change-Id: Id2830795a444f484b377ed6437435a1cd833697a --- services/core/java/com/android/server/IpSecService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 371276fbd2..126bf65565 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -44,7 +44,7 @@ import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.net.TrafficStats; -import android.net.shared.NetdService; +import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; import android.os.ParcelFileDescriptor; From 93f2d251d688f425b4499d8c15284d8fdde4b0a3 Mon Sep 17 00:00:00 2001 From: Andrei Onea Date: Mon, 25 Feb 2019 13:25:32 +0000 Subject: [PATCH 252/881] Add @UnsupportedAppUsage annotations For packages: android.net android.net.wifi android.nfc This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: I7489aad1dceeb18ed7ca48a1ed8829a668b3fa04 --- core/java/android/net/INetworkStatsService.aidl | 5 +++++ core/java/android/net/INetworkStatsSession.aidl | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 8e6f272388..92b685c4b5 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -29,6 +29,7 @@ import android.os.Messenger; interface INetworkStatsService { /** Start a statistics query session. */ + @UnsupportedAppUsage INetworkStatsSession openSession(); /** Start a statistics query session. If calling package is profile or device owner then it is @@ -37,9 +38,11 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ + @UnsupportedAppUsage INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return data layer snapshot of UID network usage. */ + @UnsupportedAppUsage NetworkStats getDataLayerSnapshotForUid(int uid); /** Get a detailed snapshot of stats since boot for all UIDs. @@ -52,6 +55,7 @@ interface INetworkStatsService { NetworkStats getDetailedUidStats(in String[] requiredIfaces); /** Return set of any ifaces associated with mobile networks since boot. */ + @UnsupportedAppUsage String[] getMobileIfaces(); /** Increment data layer count of operations performed for UID and tag. */ @@ -60,6 +64,7 @@ interface INetworkStatsService { /** Force update of ifaces. */ void forceUpdateIfaces(in Network[] defaultNetworks); /** Force update of statistics. */ + @UnsupportedAppUsage void forceUpdate(); /** Registers a callback on data usage. */ diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl index 5229a3b3b9..f13f2cb664 100644 --- a/core/java/android/net/INetworkStatsSession.aidl +++ b/core/java/android/net/INetworkStatsSession.aidl @@ -27,13 +27,17 @@ interface INetworkStatsSession { NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end); /** Return network layer usage summary for traffic that matches template. */ + @UnsupportedAppUsage NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end); /** Return historical network layer stats for traffic that matches template. */ + @UnsupportedAppUsage NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields); /** Return network layer usage summary per UID for traffic that matches template. */ + @UnsupportedAppUsage NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags); /** Return historical network layer stats for specific UID traffic that matches template. */ + @UnsupportedAppUsage NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields); /** Return historical network layer stats for specific UID traffic that matches template. */ NetworkStatsHistory getHistoryIntervalForUid(in NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end); @@ -41,6 +45,7 @@ interface INetworkStatsSession { /** Return array of uids that have stats and are accessible to the calling user */ int[] getRelevantUids(); + @UnsupportedAppUsage void close(); } From 8afc4efd1fed498d996e35a4311ce669311d5cc4 Mon Sep 17 00:00:00 2001 From: Andrei Onea Date: Thu, 28 Feb 2019 14:37:50 +0000 Subject: [PATCH 253/881] Add @UnsupportedAppUsage annotations For packages: android.net android.net.wifi android.nfc This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Merged-In: I7489aad1dceeb18ed7ca48a1ed8829a668b3fa04 Change-Id: I16570aef456b45a5543bf889dddc7a0d25441928 --- core/java/android/net/INetworkStatsService.aidl | 5 +++++ core/java/android/net/INetworkStatsSession.aidl | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 8e6f272388..92b685c4b5 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -29,6 +29,7 @@ import android.os.Messenger; interface INetworkStatsService { /** Start a statistics query session. */ + @UnsupportedAppUsage INetworkStatsSession openSession(); /** Start a statistics query session. If calling package is profile or device owner then it is @@ -37,9 +38,11 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ + @UnsupportedAppUsage INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return data layer snapshot of UID network usage. */ + @UnsupportedAppUsage NetworkStats getDataLayerSnapshotForUid(int uid); /** Get a detailed snapshot of stats since boot for all UIDs. @@ -52,6 +55,7 @@ interface INetworkStatsService { NetworkStats getDetailedUidStats(in String[] requiredIfaces); /** Return set of any ifaces associated with mobile networks since boot. */ + @UnsupportedAppUsage String[] getMobileIfaces(); /** Increment data layer count of operations performed for UID and tag. */ @@ -60,6 +64,7 @@ interface INetworkStatsService { /** Force update of ifaces. */ void forceUpdateIfaces(in Network[] defaultNetworks); /** Force update of statistics. */ + @UnsupportedAppUsage void forceUpdate(); /** Registers a callback on data usage. */ diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl index 5229a3b3b9..f13f2cb664 100644 --- a/core/java/android/net/INetworkStatsSession.aidl +++ b/core/java/android/net/INetworkStatsSession.aidl @@ -27,13 +27,17 @@ interface INetworkStatsSession { NetworkStats getDeviceSummaryForNetwork(in NetworkTemplate template, long start, long end); /** Return network layer usage summary for traffic that matches template. */ + @UnsupportedAppUsage NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end); /** Return historical network layer stats for traffic that matches template. */ + @UnsupportedAppUsage NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields); /** Return network layer usage summary per UID for traffic that matches template. */ + @UnsupportedAppUsage NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags); /** Return historical network layer stats for specific UID traffic that matches template. */ + @UnsupportedAppUsage NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields); /** Return historical network layer stats for specific UID traffic that matches template. */ NetworkStatsHistory getHistoryIntervalForUid(in NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end); @@ -41,6 +45,7 @@ interface INetworkStatsSession { /** Return array of uids that have stats and are accessible to the calling user */ int[] getRelevantUids(); + @UnsupportedAppUsage void close(); } From f664be533b4088975ac2781473d90e74ff0f5265 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Thu, 7 Feb 2019 14:13:13 -0800 Subject: [PATCH 254/881] Remove ConnectivityManager and its usages from NetworkStatsService. NSS needed it for getting VpnInfo[], NetworkState[] and activeLinkProperties which it used to query via ConnectivityManager. For VpnInfo[], this was racy as NSS may ignore intermediate changes to a VPN's underlying networks. See http://b/123961098 for more context. It may also lead to deadlocks b/w ConnectivityService and NetworkStatsService. See http://b/126245192 for more info. This change will ensure that NSS is never contending on any of ConnectivityService locks. Bug: 123961098 Bug: 126245192 Bug: 120145746 Test: atest FrameworksNetTests Change-Id: I57e117bb4e9efe491b19d6b5a479f2d58d1c58e6 --- .../android/net/INetworkStatsService.aidl | 8 +++- .../server/net/NetworkStatsService.java | 46 +++++++++---------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 8e6f272388..148b25dfa8 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -19,11 +19,13 @@ package android.net; import android.net.DataUsageRequest; import android.net.INetworkStatsSession; import android.net.Network; +import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.IBinder; import android.os.Messenger; +import com.android.internal.net.VpnInfo; /** {@hide} */ interface INetworkStatsService { @@ -58,7 +60,11 @@ interface INetworkStatsService { void incrementOperationCount(int uid, int tag, int operationCount); /** Force update of ifaces. */ - void forceUpdateIfaces(in Network[] defaultNetworks); + void forceUpdateIfaces( + in Network[] defaultNetworks, + in VpnInfo[] vpnArray, + in NetworkState[] networkStates, + in String activeIface); /** Force update of statistics. */ void forceUpdate(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index bffd60bcb8..205ddb07ec 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -82,7 +82,6 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.DataUsageRequest; -import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; @@ -196,8 +195,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final boolean mUseBpfTrafficStats; - private IConnectivityManager mConnManager; - @VisibleForTesting public static final String ACTION_NETWORK_STATS_POLL = "com.android.server.action.NETWORK_STATS_POLL"; @@ -259,6 +256,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final ArrayMap mActiveUidIfaces = new ArrayMap<>(); /** Current default active iface. */ + @GuardedBy("mStatsLock") private String mActiveIface; /** Set of any ifaces associated with mobile networks since boot. */ @@ -269,6 +267,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; + /** Set containing info about active VPNs and their underlying networks. */ + @GuardedBy("mStatsLock") + private VpnInfo[] mVpnInfos = new VpnInfo[0]; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -382,10 +384,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mHandlerCallback = callback; } - public void bindConnectivityManager(IConnectivityManager connManager) { - mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); - } - public void systemReady() { mSystemReady = true; @@ -864,13 +862,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void forceUpdateIfaces(Network[] defaultNetworks) { + public void forceUpdateIfaces( + Network[] defaultNetworks, + VpnInfo[] vpnArray, + NetworkState[] networkStates, + String activeIface) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks); + updateIfaces(defaultNetworks, vpnArray, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1134,11 +1136,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; - private void updateIfaces(Network[] defaultNetworks) { + private void updateIfaces( + Network[] defaultNetworks, + VpnInfo[] vpnArray, + NetworkState[] networkStates, + String activeIface) { synchronized (mStatsLock) { mWakeLock.acquire(); try { - updateIfacesLocked(defaultNetworks); + mVpnInfos = vpnArray; + mActiveIface = activeIface; + updateIfacesLocked(defaultNetworks, networkStates); } finally { mWakeLock.release(); } @@ -1152,7 +1160,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(Network[] defaultNetworks) { + private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1164,18 +1172,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // will be persisted during next alarm poll event. performPollLocked(FLAG_PERSIST_NETWORK); - final NetworkState[] states; - final LinkProperties activeLink; - try { - states = mConnManager.getAllNetworkState(); - activeLink = mConnManager.getActiveLinkProperties(); - } catch (RemoteException e) { - // ignored; service lives in system_server - return; - } - - mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null; - // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); @@ -1287,7 +1283,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. - VpnInfo[] vpnArray = mConnManager.getAllVpnInfo(); + VpnInfo[] vpnArray = mVpnInfos; Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); From e889557e8bcc905e4c0eaca849e823174f2b7d1e Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Thu, 7 Feb 2019 14:13:13 -0800 Subject: [PATCH 255/881] Remove ConnectivityManager and its usages from NetworkStatsService. NSS needed it for getting VpnInfo[], NetworkState[] and activeLinkProperties which it used to query via ConnectivityManager. For VpnInfo[], this was racy as NSS may ignore intermediate changes to a VPN's underlying networks. See http://b/123961098 for more context. It may also lead to deadlocks b/w ConnectivityService and NetworkStatsService. See http://b/126245192 for more info. This change will ensure that NSS is never contending on any of ConnectivityService locks. Bug: 123961098 Bug: 126245192 Bug: 120145746 Test: atest FrameworksNetTests Change-Id: Id1da446b54d95ee68ed14079107b1a10318bcf8b Merged-In: I57e117bb4e9efe491b19d6b5a479f2d58d1c58e6 --- .../android/net/INetworkStatsService.aidl | 8 +++- .../server/net/NetworkStatsService.java | 46 +++++++++---------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 8e6f272388..148b25dfa8 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -19,11 +19,13 @@ package android.net; import android.net.DataUsageRequest; import android.net.INetworkStatsSession; import android.net.Network; +import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.IBinder; import android.os.Messenger; +import com.android.internal.net.VpnInfo; /** {@hide} */ interface INetworkStatsService { @@ -58,7 +60,11 @@ interface INetworkStatsService { void incrementOperationCount(int uid, int tag, int operationCount); /** Force update of ifaces. */ - void forceUpdateIfaces(in Network[] defaultNetworks); + void forceUpdateIfaces( + in Network[] defaultNetworks, + in VpnInfo[] vpnArray, + in NetworkState[] networkStates, + in String activeIface); /** Force update of statistics. */ void forceUpdate(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 2e7cbc684c..8fa435cd93 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -82,7 +82,6 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.DataUsageRequest; -import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; @@ -195,8 +194,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final boolean mUseBpfTrafficStats; - private IConnectivityManager mConnManager; - @VisibleForTesting public static final String ACTION_NETWORK_STATS_POLL = "com.android.server.action.NETWORK_STATS_POLL"; @@ -258,6 +255,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final ArrayMap mActiveUidIfaces = new ArrayMap<>(); /** Current default active iface. */ + @GuardedBy("mStatsLock") private String mActiveIface; /** Set of any ifaces associated with mobile networks since boot. */ @@ -268,6 +266,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; + /** Set containing info about active VPNs and their underlying networks. */ + @GuardedBy("mStatsLock") + private VpnInfo[] mVpnInfos = new VpnInfo[0]; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -375,10 +377,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mHandlerCallback = callback; } - public void bindConnectivityManager(IConnectivityManager connManager) { - mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); - } - public void systemReady() { mSystemReady = true; @@ -857,13 +855,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void forceUpdateIfaces(Network[] defaultNetworks) { + public void forceUpdateIfaces( + Network[] defaultNetworks, + VpnInfo[] vpnArray, + NetworkState[] networkStates, + String activeIface) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks); + updateIfaces(defaultNetworks, vpnArray, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1127,11 +1129,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; - private void updateIfaces(Network[] defaultNetworks) { + private void updateIfaces( + Network[] defaultNetworks, + VpnInfo[] vpnArray, + NetworkState[] networkStates, + String activeIface) { synchronized (mStatsLock) { mWakeLock.acquire(); try { - updateIfacesLocked(defaultNetworks); + mVpnInfos = vpnArray; + mActiveIface = activeIface; + updateIfacesLocked(defaultNetworks, networkStates); } finally { mWakeLock.release(); } @@ -1145,7 +1153,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(Network[] defaultNetworks) { + private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1157,18 +1165,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // will be persisted during next alarm poll event. performPollLocked(FLAG_PERSIST_NETWORK); - final NetworkState[] states; - final LinkProperties activeLink; - try { - states = mConnManager.getAllNetworkState(); - activeLink = mConnManager.getActiveLinkProperties(); - } catch (RemoteException e) { - // ignored; service lives in system_server - return; - } - - mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null; - // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); @@ -1280,7 +1276,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. - VpnInfo[] vpnArray = mConnManager.getAllVpnInfo(); + VpnInfo[] vpnArray = mVpnInfos; Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); From 26b24a58735dfb8fb68cc3ea2c7451c1a26d8c89 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Thu, 7 Feb 2019 14:13:13 -0800 Subject: [PATCH 256/881] Remove ConnectivityManager and its usages from NetworkStatsService. NSS needed it for getting VpnInfo[], NetworkState[] and activeLinkProperties which it used to query via ConnectivityManager. For VpnInfo[], this was racy as NSS may ignore intermediate changes to a VPN's underlying networks. See http://b/123961098 for more context. It may also lead to deadlocks b/w ConnectivityService and NetworkStatsService. See http://b/126245192 for more info. This change will ensure that NSS is never contending on any of ConnectivityService locks. This change also is cherry-picking cleanup made to NSS in http://aosp/628368. Bug: 123961098 Bug: 126245192 Bug: 120145746 Test: atest FrameworksNetTests Change-Id: Ia687845888434c8ddd24bdf44b4c70dfe80e03f5 Merged-In: I57e117bb4e9efe491b19d6b5a479f2d58d1c58e6 --- .../android/net/INetworkStatsService.aidl | 8 ++- .../server/net/NetworkStatsService.java | 53 ++++++++----------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 8e6f272388..148b25dfa8 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -19,11 +19,13 @@ package android.net; import android.net.DataUsageRequest; import android.net.INetworkStatsSession; import android.net.Network; +import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.IBinder; import android.os.Messenger; +import com.android.internal.net.VpnInfo; /** {@hide} */ interface INetworkStatsService { @@ -58,7 +60,11 @@ interface INetworkStatsService { void incrementOperationCount(int uid, int tag, int operationCount); /** Force update of ifaces. */ - void forceUpdateIfaces(in Network[] defaultNetworks); + void forceUpdateIfaces( + in Network[] defaultNetworks, + in VpnInfo[] vpnArray, + in NetworkState[] networkStates, + in String activeIface); /** Force update of statistics. */ void forceUpdate(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 17ab29d747..2fef560afd 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -82,7 +82,6 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.net.DataUsageRequest; -import android.net.IConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; @@ -161,9 +160,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Perform polling and persist all (FLAG_PERSIST_ALL). private static final int MSG_PERFORM_POLL = 1; - private static final int MSG_UPDATE_IFACES = 2; // Perform polling, persist network, and register the global alert again. - private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 3; + private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -196,8 +194,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final boolean mUseBpfTrafficStats; - private IConnectivityManager mConnManager; - @VisibleForTesting public static final String ACTION_NETWORK_STATS_POLL = "com.android.server.action.NETWORK_STATS_POLL"; @@ -259,6 +255,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final ArrayMap mActiveUidIfaces = new ArrayMap<>(); /** Current default active iface. */ + @GuardedBy("mStatsLock") private String mActiveIface; /** Set of any ifaces associated with mobile networks since boot. */ @@ -269,6 +266,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; + /** Set containing info about active VPNs and their underlying networks. */ + @GuardedBy("mStatsLock") + private VpnInfo[] mVpnInfos = new VpnInfo[0]; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -371,10 +372,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mHandlerCallback = callback; } - public void bindConnectivityManager(IConnectivityManager connManager) { - mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); - } - public void systemReady() { mSystemReady = true; @@ -853,13 +850,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void forceUpdateIfaces(Network[] defaultNetworks) { + public void forceUpdateIfaces( + Network[] defaultNetworks, + VpnInfo[] vpnArray, + NetworkState[] networkStates, + String activeIface) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks); + updateIfaces(defaultNetworks, vpnArray, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1077,11 +1078,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; - private void updateIfaces(Network[] defaultNetworks) { + private void updateIfaces( + Network[] defaultNetworks, + VpnInfo[] vpnArray, + NetworkState[] networkStates, + String activeIface) { synchronized (mStatsLock) { mWakeLock.acquire(); try { - updateIfacesLocked(defaultNetworks); + mVpnInfos = vpnArray; + mActiveIface = activeIface; + updateIfacesLocked(defaultNetworks, networkStates); } finally { mWakeLock.release(); } @@ -1095,7 +1102,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(Network[] defaultNetworks) { + private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1107,18 +1114,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // will be persisted during next alarm poll event. performPollLocked(FLAG_PERSIST_NETWORK); - final NetworkState[] states; - final LinkProperties activeLink; - try { - states = mConnManager.getAllNetworkState(); - activeLink = mConnManager.getActiveLinkProperties(); - } catch (RemoteException e) { - // ignored; service lives in system_server - return; - } - - mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null; - // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); @@ -1230,7 +1225,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. - VpnInfo[] vpnArray = mConnManager.getAllVpnInfo(); + VpnInfo[] vpnArray = mVpnInfos; Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); @@ -1689,10 +1684,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mService.performPoll(FLAG_PERSIST_ALL); return true; } - case MSG_UPDATE_IFACES: { - mService.updateIfaces(null); - return true; - } case MSG_PERFORM_POLL_REGISTER_ALERT: { mService.performPoll(FLAG_PERSIST_NETWORK); mService.registerGlobalAlert(); From 43cdbac7d0b3cb3b71bdb021283657b49d4d398c Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 28 Feb 2019 12:06:45 -0700 Subject: [PATCH 257/881] All Parcelable CREATOR fields are @NonNull. If they were null, then the Parcelable would fail to work. Bug: 126726802 Test: manual Change-Id: I7929ffa2f20e5de1c8e68e8263cca99496e9d014 Exempt-From-Owner-Approval: Trivial API annotations --- core/java/android/net/DataUsageRequest.java | 2 +- core/java/android/net/IpSecAlgorithm.java | 2 +- core/java/android/net/IpSecConfig.java | 2 +- core/java/android/net/IpSecSpiResponse.java | 2 +- core/java/android/net/IpSecTransformResponse.java | 2 +- core/java/android/net/IpSecTunnelInterfaceResponse.java | 2 +- core/java/android/net/IpSecUdpEncapResponse.java | 2 +- core/java/android/net/NetworkStats.java | 2 +- core/java/android/net/NetworkStatsHistory.java | 2 +- core/java/android/net/NetworkTemplate.java | 2 +- core/java/android/net/nsd/NsdServiceInfo.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java index ac9a5a3668..0ac8f7e794 100644 --- a/core/java/android/net/DataUsageRequest.java +++ b/core/java/android/net/DataUsageRequest.java @@ -69,7 +69,7 @@ public final class DataUsageRequest implements Parcelable { dest.writeLong(thresholdInBytes); } - public static final Creator CREATOR = + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public DataUsageRequest createFromParcel(Parcel in) { diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 8034bb62c9..38d9883f00 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -191,7 +191,7 @@ public final class IpSecAlgorithm implements Parcelable { } /** Parcelable Creator */ - public static final Parcelable.Creator CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecAlgorithm createFromParcel(Parcel in) { final String name = in.readString(); diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 3552655983..a64014fe55 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -322,7 +322,7 @@ public final class IpSecConfig implements Parcelable { return strBuilder.toString(); } - public static final Parcelable.Creator CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecConfig createFromParcel(Parcel in) { return new IpSecConfig(in); diff --git a/core/java/android/net/IpSecSpiResponse.java b/core/java/android/net/IpSecSpiResponse.java index 71dfa03ac1..f99e570fb7 100644 --- a/core/java/android/net/IpSecSpiResponse.java +++ b/core/java/android/net/IpSecSpiResponse.java @@ -65,7 +65,7 @@ public final class IpSecSpiResponse implements Parcelable { spi = in.readInt(); } - public static final Parcelable.Creator CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecSpiResponse createFromParcel(Parcel in) { return new IpSecSpiResponse(in); diff --git a/core/java/android/net/IpSecTransformResponse.java b/core/java/android/net/IpSecTransformResponse.java index cfc176227f..a38488954f 100644 --- a/core/java/android/net/IpSecTransformResponse.java +++ b/core/java/android/net/IpSecTransformResponse.java @@ -60,7 +60,7 @@ public final class IpSecTransformResponse implements Parcelable { resourceId = in.readInt(); } - public static final Parcelable.Creator CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecTransformResponse createFromParcel(Parcel in) { return new IpSecTransformResponse(in); diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/core/java/android/net/IpSecTunnelInterfaceResponse.java index c23d831a44..e3411e003d 100644 --- a/core/java/android/net/IpSecTunnelInterfaceResponse.java +++ b/core/java/android/net/IpSecTunnelInterfaceResponse.java @@ -65,7 +65,7 @@ public final class IpSecTunnelInterfaceResponse implements Parcelable { interfaceName = in.readString(); } - public static final Parcelable.Creator CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) { return new IpSecTunnelInterfaceResponse(in); diff --git a/core/java/android/net/IpSecUdpEncapResponse.java b/core/java/android/net/IpSecUdpEncapResponse.java index 4679267cf9..4e7ba9b515 100644 --- a/core/java/android/net/IpSecUdpEncapResponse.java +++ b/core/java/android/net/IpSecUdpEncapResponse.java @@ -83,7 +83,7 @@ public final class IpSecUdpEncapResponse implements Parcelable { fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); } - public static final Parcelable.Creator CREATOR = + public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecUdpEncapResponse createFromParcel(Parcel in) { return new IpSecUdpEncapResponse(in); diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9cf582bef1..e892b650bf 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1153,7 +1153,7 @@ public class NetworkStats implements Parcelable { } @UnsupportedAppUsage - public static final Creator CREATOR = new Creator() { + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public NetworkStats createFromParcel(Parcel in) { return new NetworkStats(in); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index d53e0326ae..f61260ee3e 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -719,7 +719,7 @@ public class NetworkStatsHistory implements Parcelable { } @UnsupportedAppUsage - public static final Creator CREATOR = new Creator() { + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public NetworkStatsHistory createFromParcel(Parcel in) { return new NetworkStatsHistory(in); diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index bb75c63436..d42fce3a4c 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -482,7 +482,7 @@ public class NetworkTemplate implements Parcelable { } @UnsupportedAppUsage - public static final Creator CREATOR = new Creator() { + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { @Override public NetworkTemplate createFromParcel(Parcel in) { return new NetworkTemplate(in); diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java index 9ba17edfb9..459b140980 100644 --- a/core/java/android/net/nsd/NsdServiceInfo.java +++ b/core/java/android/net/nsd/NsdServiceInfo.java @@ -355,7 +355,7 @@ public final class NsdServiceInfo implements Parcelable { } /** Implement the Parcelable interface */ - public static final Creator CREATOR = + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { public NsdServiceInfo createFromParcel(Parcel in) { NsdServiceInfo info = new NsdServiceInfo(); From 54a272dbdf773565a663d9b0a35883b048e8ae8f Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Tue, 26 Feb 2019 14:52:33 -0800 Subject: [PATCH 258/881] Migrate frameworks/base/tests/testables and its users to androidx.test See go/jetpack-test-android-migration Test: atest TestablesTests NetworkStackTests FrameworksServicesTests SystemUITests FrameworksUiServicesTests ExtServicesUnitTests Exempt-From-Owner-Approval: already reviewed Change-Id: I083fcdaa71b503535aa2b3c257740f3ecf055373 Merged-In: Ib04d80954bd8536914d88c66b28e6632e60a6245 --- .../src/com/android/server/net/IpConfigStoreTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java index 9f4b754621..7767a2810a 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -27,9 +27,10 @@ import android.net.LinkAddress; import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; -import android.support.test.runner.AndroidJUnit4; import android.util.ArrayMap; +import androidx.test.runner.AndroidJUnit4; + import org.junit.Test; import org.junit.runner.RunWith; From 2d9a9a9fa3285f634c6943806cbe7af2d453006d Mon Sep 17 00:00:00 2001 From: Brett Chabot Date: Tue, 5 Mar 2019 09:10:36 -0800 Subject: [PATCH 259/881] Migrate frameworks/opt/net/ethernet to androidx.test See go/jetpack-test-android-migration Test: compile Change-Id: I20fc49dd2487af2245f060454e7f32f5e9145a9c --- tests/ethernet/Android.bp | 2 +- tests/ethernet/AndroidManifest.xml | 2 +- .../com/android/server/ethernet/EthernetTrackerTest.java | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp index 8c5df21dae..9c776e604f 100644 --- a/tests/ethernet/Android.bp +++ b/tests/ethernet/Android.bp @@ -27,7 +27,7 @@ android_test { ], static_libs: [ - "android-support-test", + "androidx.test.rules", "ethernet-service", ], } diff --git a/tests/ethernet/AndroidManifest.xml b/tests/ethernet/AndroidManifest.xml index 1bc0775310..302bb6c9a1 100644 --- a/tests/ethernet/AndroidManifest.xml +++ b/tests/ethernet/AndroidManifest.xml @@ -22,7 +22,7 @@ - diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index a56c9fe9fa..fa945d6659 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -25,8 +25,9 @@ import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; From 85cd5b63535a76da6ba7a425db38671b08f54f8f Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Sun, 17 Feb 2019 23:15:15 -0800 Subject: [PATCH 260/881] Add unit tests related to data accounting for VPNs with one underlying network. This is to establish a baseline for the existing behavior, and to ensure that following changes are not causing a regression in existing behavior. This CL is also adding missing cleanup for NetworkStatsCollectionTest which was forcing all network types in NetworkTemplate that was causing NetworkStatsService related tests to fail. Bug: 113122541 Bug: 120145746 Test: atest FrameworksNetTests Change-Id: I285f186cfb16bc9fa704c797996b1e4f8a73dee4 --- core/java/android/net/NetworkTemplate.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index bb75c63436..60ae352d5c 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -40,6 +40,7 @@ import android.os.Parcelable; import android.util.BackupUtils; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import java.io.ByteArrayOutputStream; @@ -89,10 +90,22 @@ public class NetworkTemplate implements Parcelable { private static boolean sForceAllNetworkTypes = false; + /** + * Results in matching against all mobile network types. + * + *

See {@link #matchesMobile} and {@link matchesMobileWildcard}. + */ + @VisibleForTesting public static void forceAllNetworkTypes() { sForceAllNetworkTypes = true; } + /** Resets the affect of {@link #forceAllNetworkTypes}. */ + @VisibleForTesting + public static void resetForceAllNetworkTypes() { + sForceAllNetworkTypes = false; + } + /** * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with * the given IMSI. From d54527084e29e3c0dfe7e5151132b2ac375b3bed Mon Sep 17 00:00:00 2001 From: Andrei Onea Date: Thu, 21 Mar 2019 13:57:17 +0000 Subject: [PATCH 261/881] Add @UnsupportedAppUsage annotations For packages: android.companion android.filterfw android.hardware.camera2.utils android.inputmethodservice android.net.nsd android.os android.preference android.security.keymaster android.service.dreams android.telecom android.telephony.ims.compat.feature android.telephony android.util android.view.accessibility android.media.effect This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Change-Id: I9c2f8347952f3cc65759472b0e1a2717b285e44e --- core/java/android/net/nsd/INsdManager.aidl | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 3361a7b84b..9484c74bcb 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,6 +25,7 @@ import android.os.Messenger; */ interface INsdManager { + @UnsupportedAppUsage Messenger getMessenger(); void setEnabled(boolean enable); } From c323b81b4beef6a61aabae14ed8bca43b93e70f5 Mon Sep 17 00:00:00 2001 From: Andrei Onea Date: Fri, 22 Mar 2019 11:32:59 +0000 Subject: [PATCH 262/881] Add @UnsupportedAppUsage annotations For packages: android.companion android.filterfw android.hardware.camera2.utils android.inputmethodservice android.net.nsd android.os android.preference android.security.keymaster android.service.dreams android.telecom android.telephony.ims.compat.feature android.telephony android.util android.view.accessibility android.media.effect This is an automatically generated CL. See go/UnsupportedAppUsage for more details. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 110868826 Test: m Merged-In: I9c2f8347952f3cc65759472b0e1a2717b285e44e Change-Id: I14793863cf815fa3383fec6c6bf5a9365c2e17eb --- core/java/android/net/nsd/INsdManager.aidl | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 3361a7b84b..9484c74bcb 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,6 +25,7 @@ import android.os.Messenger; */ interface INsdManager { + @UnsupportedAppUsage Messenger getMessenger(); void setEnabled(boolean enable); } From afbdf8f7bbe7a4a01f1e9d7439ae950b5f2ca85c Mon Sep 17 00:00:00 2001 From: Sal Savage Date: Wed, 23 Jan 2019 14:25:59 -0800 Subject: [PATCH 263/881] Update comments and documentation in net type prop change Bug: b/112588045 Test: atest EthernetServiceTests --verbose Test: kitchensink, dumpsys ethernet, with RPi devices and USB to ethernet adapters. Change-Id: Iaa260aabbbd7aa4b7864eba32ecff7e3f84123c3 --- .../ethernet/EthernetNetworkFactory.java | 17 ++++++--- .../server/ethernet/EthernetTracker.java | 18 +++++----- .../server/ethernet/EthernetTrackerTest.java | 36 +++++++++---------- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 4a1d6587d9..b8ed845c2c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -44,6 +44,7 @@ import android.os.ConditionVariable; import android.os.Handler; import android.os.RemoteException; import android.text.TextUtils; +import android.util.AndroidRuntimeException; import android.util.Log; import android.util.SparseArray; @@ -71,6 +72,12 @@ public class EthernetNetworkFactory extends NetworkFactory { private final Handler mHandler; private final Context mContext; + public static class ConfigurationException extends AndroidRuntimeException { + public ConfigurationException(String msg) { + super(msg); + } + } + public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) { super(handler.getLooper(), context, NETWORK_TYPE, filter); @@ -358,8 +365,8 @@ public class EthernetNetworkFactory extends NetworkFactory { legacyType = getLegacyType(transportTypes[0]); } else { // Should never happen as transport is always one of ETHERNET or a valid override - Log.w(TAG, "There is no transport type associated with network interface '" - + mLinkProperties.getInterfaceName() + "' -- Legacy type set to TYPE_NONE"); + throw new ConfigurationException("Network Capabilities do not have an associated " + + "transport type."); } mHwAddress = hwAddress; @@ -410,8 +417,8 @@ public class EthernetNetworkFactory extends NetworkFactory { int[] transportTypes = mCapabilities.getTransportTypes(); if (transportTypes.length < 1) { - Log.w(TAG, "There is no transport type associated with network interface '" - + mLinkProperties.getInterfaceName() + "' -- Score set to zero"); + Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no " + + "transport type associated with it. Score set to zero"); return 0; } TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null); @@ -532,7 +539,7 @@ public class EthernetNetworkFactory extends NetworkFactory { mNetworkAgent.sendLinkProperties(mLinkProperties); // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now - // since the agent isn't update frequently. Consider caching the score in the future if + // since the agent isn't updated frequently. Consider caching the score in the future if // agent updating is required more often mNetworkAgent.sendNetworkScore(getNetworkScore()); } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 099e05414c..4ab1dff881 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -337,10 +337,10 @@ final class EthernetTracker { * @param clearDefaultCapabilities Indicates whether or not to clear any default capabilities * @param commaSeparatedCapabilities A comma separated string list of integer encoded * NetworkCapability.NET_CAPABILITY_* values - * @param overrideTransport A string representing a single override transport type, must be one - * of the NetworkCapability.TRANSPORT_* values. TRANSPORT_VPN is - * not supported. Errors with input will cause the override to - * be ignored. + * @param overrideTransport A string representing a single integer encoded override transport + * type. Must be one of the NetworkCapability.TRANSPORT_* + * values. TRANSPORT_VPN is not supported. Errors with input + * will cause the override to be ignored. */ @VisibleForTesting static NetworkCapabilities createNetworkCapabilities( @@ -363,14 +363,14 @@ final class EthernetTracker { if (parsedTransport == NetworkCapabilities.TRANSPORT_VPN || parsedTransport == NetworkCapabilities.TRANSPORT_WIFI_AWARE || parsedTransport == NetworkCapabilities.TRANSPORT_LOWPAN) { - Log.e(TAG, "Override transport '" + parsedTransport + "' is not supported -- " + Log.e(TAG, "Override transport '" + parsedTransport + "' is not supported. " + "Defaulting to TRANSPORT_ETHERNET"); } else { transport = parsedTransport; } } catch (NumberFormatException nfe) { - Log.e(TAG, "Override transport type '" + overrideTransport + "' could not be parsed" - + "-- Defaulting to TRANSPORT_ETHERNET"); + Log.e(TAG, "Override transport type '" + overrideTransport + "' " + + "could not be parsed. Defaulting to TRANSPORT_ETHERNET"); } } @@ -379,8 +379,8 @@ final class EthernetTracker { try { nc.addTransportType(transport); } catch (IllegalArgumentException iae) { - Log.e(TAG, transport + " is not a valid NetworkCapability.TRANSPORT_* value" - + " -- Defaulting to TRANSPORT_ETHERNET"); + Log.e(TAG, transport + " is not a valid NetworkCapability.TRANSPORT_* value. " + + "Defaulting to TRANSPORT_ETHERNET"); nc.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index fa945d6659..67740b666a 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -160,11 +160,11 @@ public class EthernetTrackerTest { // Empty capabilities and transports lists with a "please clear defaults" should // yield an empty capabilities set with TRANPORT_ETHERNET - assertNetworkCapabilities(defaultEthernetCleared, true, "", ""); + assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", ""); // Empty capabilities and transports without the clear defaults flag should return the // default capabilities set with TRANSPORT_ETHERNET - assertNetworkCapabilities( + assertParsedNetworkCapabilities( new NetworkCapabilitiesBuilder() .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) @@ -174,7 +174,7 @@ public class EthernetTrackerTest { // A list of capabilities without the clear defaults flag should return the default // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET - assertNetworkCapabilities( + assertParsedNetworkCapabilities( new NetworkCapabilitiesBuilder() .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) @@ -186,15 +186,15 @@ public class EthernetTrackerTest { // Adding a list of capabilities with a clear defaults will leave exactly those capabilities // with a default TRANSPORT_ETHERNET since no overrides are specified - assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", ""); + assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", ""); // Adding any invalid capabilities to the list will cause them to be ignored - assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", ""); - assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", ""); + assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", ""); + assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", ""); // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport // and apply only the override to the capabiltities object - assertNetworkCapabilities( + assertParsedNetworkCapabilities( new NetworkCapabilitiesBuilder() .clearAll() .setLinkUpstreamBandwidthKbps(100000) @@ -202,7 +202,7 @@ public class EthernetTrackerTest { .addTransport(0) .build(), true, "", "0"); - assertNetworkCapabilities( + assertParsedNetworkCapabilities( new NetworkCapabilitiesBuilder() .clearAll() .setLinkUpstreamBandwidthKbps(100000) @@ -210,7 +210,7 @@ public class EthernetTrackerTest { .addTransport(1) .build(), true, "", "1"); - assertNetworkCapabilities( + assertParsedNetworkCapabilities( new NetworkCapabilitiesBuilder() .clearAll() .setLinkUpstreamBandwidthKbps(100000) @@ -218,7 +218,7 @@ public class EthernetTrackerTest { .addTransport(2) .build(), true, "", "2"); - assertNetworkCapabilities( + assertParsedNetworkCapabilities( new NetworkCapabilitiesBuilder() .clearAll() .setLinkUpstreamBandwidthKbps(100000) @@ -228,22 +228,22 @@ public class EthernetTrackerTest { true, "", "3"); // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANPORT_ETHERNET - assertNetworkCapabilities(defaultEthernetCleared, true, "", "4"); + assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "4"); // "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE // conversion. When that becomes available, this test must be updated - assertNetworkCapabilities(defaultEthernetCleared, true, "", "5"); + assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "5"); // "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE // conversion. When that becomes available, this test must be updated - assertNetworkCapabilities(defaultEthernetCleared, true, "", "6"); + assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "6"); // Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET - assertNetworkCapabilities(defaultEthernetCleared,true, "", "100"); - assertNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg"); + assertParsedNetworkCapabilities(defaultEthernetCleared,true, "", "100"); + assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg"); // Ensure the adding of both capabilities and transports work - assertNetworkCapabilities( + assertParsedNetworkCapabilities( new NetworkCapabilitiesBuilder() .clearAll() .setLinkUpstreamBandwidthKbps(100000) @@ -257,10 +257,10 @@ public class EthernetTrackerTest { true, "12,13,14,15", "3"); // Ensure order does not matter for capability list - assertNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", ""); + assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", ""); } - private void assertNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities, + private void assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities, boolean clearCapabilties, String configCapabiltiies,String configTransports) { assertEquals(expectedNetworkCapabilities, EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies, From 2e2662fbcfe1611def7ee2055cf17cb2f39d9511 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Sun, 17 Feb 2019 23:43:25 -0800 Subject: [PATCH 264/881] Take all VPN underlying networks into account when migrating traffic for VPN uid. Bug: 113122541 Bug: 120145746 Test: atest FrameworksNetTests Test: Manually verified on device that stats from VPN UID are moved appropriately based on its declared underlying network set. Test: vogar --mode app_process --benchmark NetworkStatsBenchmark.java Change-Id: I9d8d0cc58d18002c1c96f8ddff780ef8dc452d21 --- core/java/android/net/NetworkStats.java | 330 +++++++++++------- .../server/net/NetworkStatsRecorder.java | 6 +- 2 files changed, 214 insertions(+), 122 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9cf582bef1..9e79606a24 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,6 +18,7 @@ package android.net; import static android.os.Process.CLAT_UID; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -1175,133 +1176,217 @@ public class NetworkStats implements Parcelable { /** * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface. * - * This method should only be called on delta NetworkStats. Do not call this method on a - * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may - * change over time. + *

This method should only be called on delta NetworkStats. Do not call this method on a + * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change + * over time. * - * This method performs adjustments for one active VPN package and one VPN iface at a time. - * - * It is possible for the VPN software to use multiple underlying networks. This method - * only migrates traffic for the primary underlying network. + *

This method performs adjustments for one active VPN package and one VPN iface at a time. * * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel - * @param underlyingIface the primary underlying network iface used by the VPN application - * @return true if it successfully adjusts the accounting for VPN, false otherwise + * @param underlyingIfaces underlying network ifaces used by the VPN application */ - public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) { - Entry tunIfaceTotal = new Entry(); - Entry underlyingIfaceTotal = new Entry(); + public void migrateTun(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces) { + // Combined usage by all apps using VPN. + final Entry tunIfaceTotal = new Entry(); + // Usage by VPN, grouped by its {@code underlyingIfaces}. + final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; + // Usage by VPN, summed across all its {@code underlyingIfaces}. + final Entry underlyingIfacesTotal = new Entry(); - tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal); + for (int i = 0; i < perInterfaceTotal.length; i++) { + perInterfaceTotal[i] = new Entry(); + } - // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app. - // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression. + tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal, + underlyingIfacesTotal); + + // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app. + // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression. // Negative stats should be avoided. - Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal); - if (pool.isEmpty()) { - return true; - } - Entry moved = - addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); - deductTrafficFromVpnApp(tunUid, underlyingIface, moved); - - if (!moved.isEmpty()) { - Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved=" - + moved); - return false; - } - return true; + final Entry[] moved = + addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, + perInterfaceTotal, underlyingIfacesTotal); + deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved); } /** * Initializes the data used by the migrateTun() method. * - * This is the first pass iteration which does the following work: - * (1) Adds up all the traffic through the tunUid's underlyingIface - * (both foreground and background). - * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *

This is the first pass iteration which does the following work: + * + *

    + *
  • Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and + * background). + *
  • Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *
+ * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN + * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code + * underlyingIfaces} + * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its + * {@code underlyingIfaces} */ - private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry recycle = new Entry(); + private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + final Entry recycle = new Entry(); for (int i = 0; i < size; i++) { getValues(i, recycle); if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); - } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + } + if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { throw new IllegalStateException( "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } - - if (recycle.uid == tunUid && recycle.tag == TAG_NONE - && Objects.equals(underlyingIface, recycle.iface)) { - underlyingIfaceTotal.add(recycle); + if (recycle.tag != TAG_NONE) { + // TODO(b/123666283): Take all tags for tunUid into account. + continue; } - if (recycle.uid != tunUid && recycle.tag == TAG_NONE - && Objects.equals(tunIface, recycle.iface)) { + if (recycle.uid == tunUid) { + // Add up traffic through tunUid's underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + if (Objects.equals(underlyingIfaces[j], recycle.iface)) { + perInterfaceTotal[j].add(recycle); + underlyingIfacesTotal.add(recycle); + break; + } + } + } else if (tunIface.equals(recycle.iface)) { // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } } - private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry pool = new Entry(); - pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes); - pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets); - pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes); - pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets); - pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations); - return pool; - } + /** + * Distributes traffic across apps that are using given {@code tunIface}, and returns the total + * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}. + * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal combined data usage across all apps using {@code tunIface} + * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces} + * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code + * underlyingIfaces} + */ + private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + // Traffic that should be moved off of each underlying interface for tunUid (see + // deductTrafficFromVpnApp below). + final Entry[] moved = new Entry[underlyingIfaces.length]; + for (int i = 0; i < underlyingIfaces.length; i++) { + moved[i] = new Entry(); + } - private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry pool) { - Entry moved = new Entry(); - Entry tmpEntry = new Entry(); - tmpEntry.iface = underlyingIface; + final Entry tmpEntry = new Entry(); for (int i = 0; i < size; i++) { - // the vpn app is excluded from the redistribution but all moved traffic will be - // deducted from the vpn app (see deductTrafficFromVpnApp below). - if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { - if (tunIfaceTotal.rxBytes > 0) { - tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; - } else { - tmpEntry.rxBytes = 0; - } - if (tunIfaceTotal.rxPackets > 0) { - tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; - } else { - tmpEntry.rxPackets = 0; - } - if (tunIfaceTotal.txBytes > 0) { - tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes; - } else { - tmpEntry.txBytes = 0; - } - if (tunIfaceTotal.txPackets > 0) { - tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets; - } else { - tmpEntry.txPackets = 0; - } - if (tunIfaceTotal.operations > 0) { - tmpEntry.operations = - pool.operations * operations[i] / tunIfaceTotal.operations; - } else { - tmpEntry.operations = 0; - } - tmpEntry.uid = uid[i]; - tmpEntry.tag = tag[i]; + if (!Objects.equals(iface[i], tunIface)) { + // Consider only entries that go onto the VPN interface. + continue; + } + if (uid[i] == tunUid) { + // Exclude VPN app from the redistribution, as it can choose to create packet + // streams by writing to itself. + continue; + } + tmpEntry.uid = uid[i]; + tmpEntry.tag = tag[i]; + tmpEntry.metered = metered[i]; + tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; + + // In a first pass, compute each UID's total share of data across all underlyingIfaces. + // This is computed on the basis of the share of each UID's usage over tunIface. + // TODO: Consider refactoring first pass into a separate helper method. + long totalRxBytes = 0; + if (tunIfaceTotal.rxBytes > 0) { + // Note - The multiplication below should not overflow since NetworkStatsService + // processes this every time device has transmitted/received amount equivalent to + // global threshold alert (~ 2MB) across all interfaces. + final long rxBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + // app must not be blamed for more than it consumed on tunIface + totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); + } + long totalRxPackets = 0; + if (tunIfaceTotal.rxPackets > 0) { + final long rxPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); + } + long totalTxBytes = 0; + if (tunIfaceTotal.txBytes > 0) { + final long txBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); + } + long totalTxPackets = 0; + if (tunIfaceTotal.txPackets > 0) { + final long txPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); + } + long totalOperations = 0; + if (tunIfaceTotal.operations > 0) { + final long operationsAcrossUnderlyingIfaces = + underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; + totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); + } + // In a second pass, distribute these values across interfaces in the proportion that + // each interface represents of the total traffic of the underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + tmpEntry.iface = underlyingIfaces[j]; + tmpEntry.rxBytes = 0; + // Reset 'set' to correct value since it gets updated when adding debug info below. tmpEntry.set = set[i]; - tmpEntry.metered = metered[i]; - tmpEntry.roaming = roaming[i]; - tmpEntry.defaultNetwork = defaultNetwork[i]; + if (underlyingIfacesTotal.rxBytes > 0) { + tmpEntry.rxBytes = + totalRxBytes + * perInterfaceTotal[j].rxBytes + / underlyingIfacesTotal.rxBytes; + } + tmpEntry.rxPackets = 0; + if (underlyingIfacesTotal.rxPackets > 0) { + tmpEntry.rxPackets = + totalRxPackets + * perInterfaceTotal[j].rxPackets + / underlyingIfacesTotal.rxPackets; + } + tmpEntry.txBytes = 0; + if (underlyingIfacesTotal.txBytes > 0) { + tmpEntry.txBytes = + totalTxBytes + * perInterfaceTotal[j].txBytes + / underlyingIfacesTotal.txBytes; + } + tmpEntry.txPackets = 0; + if (underlyingIfacesTotal.txPackets > 0) { + tmpEntry.txPackets = + totalTxPackets + * perInterfaceTotal[j].txPackets + / underlyingIfacesTotal.txPackets; + } + tmpEntry.operations = 0; + if (underlyingIfacesTotal.operations > 0) { + tmpEntry.operations = + totalOperations + * perInterfaceTotal[j].operations + / underlyingIfacesTotal.operations; + } + combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - moved.add(tmpEntry); + moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; combineValues(tmpEntry); @@ -1311,38 +1396,45 @@ public class NetworkStats implements Parcelable { return moved; } - private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { - // Add debug info - moved.uid = tunUid; - moved.set = SET_DBG_VPN_OUT; - moved.tag = TAG_NONE; - moved.iface = underlyingIface; - moved.metered = METERED_ALL; - moved.roaming = ROAMING_ALL; - moved.defaultNetwork = DEFAULT_NETWORK_ALL; - combineValues(moved); + private void deductTrafficFromVpnApp( + int tunUid, + @NonNull String[] underlyingIfaces, + @NonNull Entry[] moved) { + for (int i = 0; i < underlyingIfaces.length; i++) { + // Add debug info + moved[i].uid = tunUid; + moved[i].set = SET_DBG_VPN_OUT; + moved[i].tag = TAG_NONE; + moved[i].iface = underlyingIfaces[i]; + moved[i].metered = METERED_ALL; + moved[i].roaming = ROAMING_ALL; + moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; + combineValues(moved[i]); - // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than - // the TAG_NONE traffic. - // - // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, - // which should be the case as it comes directly from the /proc file. We only blend in the - // roaming data after applying these adjustments, by checking the NetworkIdentity of the - // underlying iface. - int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnBackground != -1) { - tunSubtract(idxVpnBackground, this, moved); - } + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than + // the TAG_NONE traffic. + // + // Relies on the fact that the underlying traffic only has state ROAMING_NO and + // METERED_NO, which should be the case as it comes directly from the /proc file. + // We only blend in the roaming data after applying these adjustments, by checking the + // NetworkIdentity of the underlying iface. + final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnBackground != -1) { + // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed + // from foreground usage. + tunSubtract(idxVpnBackground, this, moved[i]); + } - int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnForeground != -1) { - tunSubtract(idxVpnForeground, this, moved); + final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnForeground != -1) { + tunSubtract(idxVpnForeground, this, moved[i]); + } } } - private static void tunSubtract(int i, NetworkStats left, Entry right) { + private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) { long rxBytes = Math.min(left.rxBytes[i], right.rxBytes); left.rxBytes[i] -= rxBytes; right.rxBytes -= rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a2e7e0cae9..bdff50053f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import libcore.io.IoUtils; - import com.google.android.collect.Sets; +import libcore.io.IoUtils; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -234,7 +234,7 @@ public class NetworkStatsRecorder { if (vpnArray != null) { for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); } } From 48f57628283d7cdacd831af3b5b6de8fb44c20ac Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Fri, 18 Jan 2019 19:22:48 -0800 Subject: [PATCH 265/881] NetworkStatsService: Fix getDetailedUidStats to take VPNs into account. This API is similar to one provided by NetworkStatsFactory with the difference that NSS also migrates traffic from VPN UID to other apps. Since traffic can only be migrated over NetworkStats delta, NSS therefore maintains NetworkStats snapshot across all UIDs/ifaces/tags. This snapshot gets updated whenever NSS records a new snapshot (based on various hooks such as VPN updating its underlying networks, network getting lost, etc.), or getDetailedUidStats API is invoked by one of its callers. Bug: 113122541 Bug: 120145746 Test: atest FrameworksNetTests Test: manually verified that battery stats are migrating traffic off of TUN (after patching above CL where we point BatteryStats to use this API). Change-Id: Ib0f0c2d4d41ee1d7a027ea9da457baaf198d649e --- core/java/android/net/NetworkStats.java | 29 +++++--- .../internal/net/NetworkStatsFactory.java | 5 ++ .../server/net/NetworkStatsService.java | 70 ++++++++++++++++++- 3 files changed, 94 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9e79606a24..27e0414961 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -34,6 +34,7 @@ import libcore.util.EmptyArray; import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; +import java.util.function.Predicate; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -994,23 +995,33 @@ public class NetworkStats implements Parcelable { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { return; } + filter(e -> (limitUid == UID_ALL || limitUid == e.uid) + && (limitTag == TAG_ALL || limitTag == e.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, e.iface))); + } + /** + * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. + * + *

This mutates the original structure in place. + */ + public void filterDebugEntries() { + filter(e -> e.set < SET_DEBUG_START); + } + + private void filter(Predicate predicate) { Entry entry = new Entry(); int nextOutputEntry = 0; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - final boolean matches = - (limitUid == UID_ALL || limitUid == entry.uid) - && (limitTag == TAG_ALL || limitTag == entry.tag) - && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, entry.iface)); - - if (matches) { - setValues(nextOutputEntry, entry); + if (predicate.test(entry)) { + if (nextOutputEntry != i) { + setValues(nextOutputEntry, entry); + } nextOutputEntry++; } } - size = nextOutputEntry; } diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index f8483461c2..1f3b4c4121 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -256,6 +256,11 @@ public class NetworkStatsFactory { return stats; } + /** + * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for + * VPN traffic + */ + @Deprecated public NetworkStats readNetworkStatsDetail() throws IOException { return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 8fa435cd93..4c07678173 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -292,6 +292,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); + /** + * Snapshot containing most recent network stats for all UIDs across all interfaces and tags + * since boot. + * + *

Maintains migrated VPN stats which are result of performing TUN migration on {@link + * #mLastUidDetailSnapshot}. + */ + @GuardedBy("mStatsLock") + private NetworkStats mTunAdjustedStats; + /** + * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot + * and latest snapshot. + */ + @GuardedBy("mStatsLock") + private NetworkStats mLastUidDetailSnapshot; + /** Must be set in factory by calling #setHandler. */ private Handler mHandler; private Handler.Callback mHandlerCallback; @@ -805,15 +821,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { + // Get the latest snapshot from NetworkStatsFactory. + // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting + // this to limited set of ifaces. + NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL); + + // Migrate traffic from VPN UID over delta and update mTunAdjustedStats. + NetworkStats result; + synchronized (mStatsLock) { + migrateTunTraffic(uidDetailStats, mVpnInfos); + result = mTunAdjustedStats.clone(); + } + + // Apply filter based on ifacesToQuery. final String[] ifacesToQuery = NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); - return getNetworkStatsUidDetail(ifacesToQuery); + result.filter(UID_ALL, ifacesToQuery, TAG_ALL); + return result; } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); return new NetworkStats(0L, 0); } } + @VisibleForTesting + NetworkStats getTunAdjustedStats() { + synchronized (mStatsLock) { + if (mTunAdjustedStats == null) { + return null; + } + return mTunAdjustedStats.clone(); + } + } + @Override public String[] getMobileIfaces() { return mMobileIfaces; @@ -1288,6 +1328,34 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime); + + migrateTunTraffic(uidSnapshot, vpnArray); + } + + /** + * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs. + */ + @GuardedBy("mStatsLock") + private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) { + if (mTunAdjustedStats == null) { + // Either device booted or system server restarted, hence traffic cannot be migrated + // correctly without knowing the past state of VPN's underlying networks. + mTunAdjustedStats = uidDetailStats; + mLastUidDetailSnapshot = uidDetailStats; + return; + } + // Migrate delta traffic from VPN to other apps. + NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot); + for (VpnInfo info : vpnInfoArray) { + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + } + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); + // Update #mTunAdjustedStats with migrated delta. + mTunAdjustedStats.combineAllValues(delta); + mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); + // Update last snapshot. + mLastUidDetailSnapshot = uidDetailStats; } /** From eb5e7d58e648d32bb18e31825329aeb2b5c78a4b Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Fri, 1 Mar 2019 15:07:24 -0800 Subject: [PATCH 266/881] Move NetworkStatsFactory into service directory In order to notify netd to swap eBPF maps before pulling the networkStats from eBPF maps, NetworkStatsFactory need to use the NetdServices to issue binder calls. So it need to be moved from framework/base/core to framework/base/service since object in framework/base/core cannot get any system services. This change is also necessary for setting up a lock inside NetworkStatsFactory to prevent racing between two netstats caller since the lock need to be hold before netd trigger the map swap. Also fix the compile problem caused by moving the NetworkStatsFactory and the related tests. Rename the packages and the jni functions to a more proper name. Bug: 124764595 Bug: 128900919 Test: NetworkStatsFactoryTest android.app.usage.cts.NetworkUsageStatsTest android.net.cts.TrafficStatsTest Merged-In: Ifcfe4df81caf8ede2e4e66a76552cb3200378fa8 Change-Id: Ifcfe4df81caf8ede2e4e66a76552cb3200378fa8 --- .../server}/net/NetworkStatsFactory.java | 2 +- .../server/net/NetworkStatsService.java | 1 - ...android_server_net_NetworkStatsFactory.cpp | 42 +++++++++---------- 3 files changed, 21 insertions(+), 24 deletions(-) rename {core/java/com/android/internal => services/core/java/com/android/server}/net/NetworkStatsFactory.java (99%) rename core/jni/com_android_internal_net_NetworkStatsFactory.cpp => services/core/jni/com_android_server_net_NetworkStatsFactory.cpp (88%) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java similarity index 99% rename from core/java/com/android/internal/net/NetworkStatsFactory.java rename to services/core/java/com/android/server/net/NetworkStatsFactory.java index 1f3b4c4121..bf34d8fa6b 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.net; +package com.android.server.net; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.TAG_ALL; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4c07678173..f237c4bca5 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -129,7 +129,6 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.NetworkStatsFactory; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp similarity index 88% rename from core/jni/com_android_internal_net_NetworkStatsFactory.cpp rename to services/core/jni/com_android_server_net_NetworkStatsFactory.cpp index 8259ffcd41..9cd743b346 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp @@ -21,9 +21,9 @@ #include #include -#include #include +#include #include #include #include @@ -333,29 +333,27 @@ static const JNINativeMethod gMethods[] = { (void*) readNetworkStatsDev }, }; -int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { - int err = RegisterMethodsOrDie(env, - "com/android/internal/net/NetworkStatsFactory", gMethods, +int register_android_server_net_NetworkStatsFactory(JNIEnv* env) { + int err = jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsFactory", gMethods, NELEM(gMethods)); + gStringClass = env->FindClass("java/lang/String"); + gStringClass = static_cast(env->NewGlobalRef(gStringClass)); - gStringClass = FindClassOrDie(env, "java/lang/String"); - gStringClass = MakeGlobalRefOrDie(env, gStringClass); - - jclass clazz = FindClassOrDie(env, "android/net/NetworkStats"); - gNetworkStatsClassInfo.size = GetFieldIDOrDie(env, clazz, "size", "I"); - gNetworkStatsClassInfo.capacity = GetFieldIDOrDie(env, clazz, "capacity", "I"); - gNetworkStatsClassInfo.iface = GetFieldIDOrDie(env, clazz, "iface", "[Ljava/lang/String;"); - gNetworkStatsClassInfo.uid = GetFieldIDOrDie(env, clazz, "uid", "[I"); - gNetworkStatsClassInfo.set = GetFieldIDOrDie(env, clazz, "set", "[I"); - gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I"); - gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I"); - gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I"); - gNetworkStatsClassInfo.defaultNetwork = GetFieldIDOrDie(env, clazz, "defaultNetwork", "[I"); - gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J"); - gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J"); - gNetworkStatsClassInfo.txBytes = GetFieldIDOrDie(env, clazz, "txBytes", "[J"); - gNetworkStatsClassInfo.txPackets = GetFieldIDOrDie(env, clazz, "txPackets", "[J"); - gNetworkStatsClassInfo.operations = GetFieldIDOrDie(env, clazz, "operations", "[J"); + jclass clazz = env->FindClass("android/net/NetworkStats"); + gNetworkStatsClassInfo.size = env->GetFieldID(clazz, "size", "I"); + gNetworkStatsClassInfo.capacity = env->GetFieldID(clazz, "capacity", "I"); + gNetworkStatsClassInfo.iface = env->GetFieldID(clazz, "iface", "[Ljava/lang/String;"); + gNetworkStatsClassInfo.uid = env->GetFieldID(clazz, "uid", "[I"); + gNetworkStatsClassInfo.set = env->GetFieldID(clazz, "set", "[I"); + gNetworkStatsClassInfo.tag = env->GetFieldID(clazz, "tag", "[I"); + gNetworkStatsClassInfo.metered = env->GetFieldID(clazz, "metered", "[I"); + gNetworkStatsClassInfo.roaming = env->GetFieldID(clazz, "roaming", "[I"); + gNetworkStatsClassInfo.defaultNetwork = env->GetFieldID(clazz, "defaultNetwork", "[I"); + gNetworkStatsClassInfo.rxBytes = env->GetFieldID(clazz, "rxBytes", "[J"); + gNetworkStatsClassInfo.rxPackets = env->GetFieldID(clazz, "rxPackets", "[J"); + gNetworkStatsClassInfo.txBytes = env->GetFieldID(clazz, "txBytes", "[J"); + gNetworkStatsClassInfo.txPackets = env->GetFieldID(clazz, "txPackets", "[J"); + gNetworkStatsClassInfo.operations = env->GetFieldID(clazz, "operations", "[J"); return err; } From 36ba2a62c4f4efba0d57eec250a6cfc18dae0bd7 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Fri, 1 Mar 2019 15:07:24 -0800 Subject: [PATCH 267/881] Move NetworkStatsFactory into service directory In order to notify netd to swap eBPF maps before pulling the networkStats from eBPF maps, NetworkStatsFactory need to use the NetdServices to issue binder calls. So it need to be moved from framework/base/core to framework/base/service since object in framework/base/core cannot get any system services. This change is also necessary for setting up a lock inside NetworkStatsFactory to prevent racing between two netstats caller since the lock need to be hold before netd trigger the map swap. Also fix the compile problem caused by moving the NetworkStatsFactory and the related tests. Rename the packages and the jni functions to a more proper name. Bug: 124764595 Bug: 128900919 Test: NetworkStatsFactoryTest android.app.usage.cts.NetworkUsageStatsTest android.net.cts.TrafficStatsTest Change-Id: Ifcfe4df81caf8ede2e4e66a76552cb3200378fa8 --- .../server}/net/NetworkStatsFactory.java | 2 +- .../server/net/NetworkStatsService.java | 1 - ...android_server_net_NetworkStatsFactory.cpp | 42 +++++++++---------- 3 files changed, 21 insertions(+), 24 deletions(-) rename {core/java/com/android/internal => services/core/java/com/android/server}/net/NetworkStatsFactory.java (99%) rename core/jni/com_android_internal_net_NetworkStatsFactory.cpp => services/core/jni/com_android_server_net_NetworkStatsFactory.cpp (88%) diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java similarity index 99% rename from core/java/com/android/internal/net/NetworkStatsFactory.java rename to services/core/java/com/android/server/net/NetworkStatsFactory.java index f8483461c2..af299cf66d 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.net; +package com.android.server.net; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.TAG_ALL; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 205ddb07ec..15599111f6 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -130,7 +130,6 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.NetworkStatsFactory; import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp similarity index 88% rename from core/jni/com_android_internal_net_NetworkStatsFactory.cpp rename to services/core/jni/com_android_server_net_NetworkStatsFactory.cpp index 8259ffcd41..9cd743b346 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp @@ -21,9 +21,9 @@ #include #include -#include #include +#include #include #include #include @@ -333,29 +333,27 @@ static const JNINativeMethod gMethods[] = { (void*) readNetworkStatsDev }, }; -int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { - int err = RegisterMethodsOrDie(env, - "com/android/internal/net/NetworkStatsFactory", gMethods, +int register_android_server_net_NetworkStatsFactory(JNIEnv* env) { + int err = jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsFactory", gMethods, NELEM(gMethods)); + gStringClass = env->FindClass("java/lang/String"); + gStringClass = static_cast(env->NewGlobalRef(gStringClass)); - gStringClass = FindClassOrDie(env, "java/lang/String"); - gStringClass = MakeGlobalRefOrDie(env, gStringClass); - - jclass clazz = FindClassOrDie(env, "android/net/NetworkStats"); - gNetworkStatsClassInfo.size = GetFieldIDOrDie(env, clazz, "size", "I"); - gNetworkStatsClassInfo.capacity = GetFieldIDOrDie(env, clazz, "capacity", "I"); - gNetworkStatsClassInfo.iface = GetFieldIDOrDie(env, clazz, "iface", "[Ljava/lang/String;"); - gNetworkStatsClassInfo.uid = GetFieldIDOrDie(env, clazz, "uid", "[I"); - gNetworkStatsClassInfo.set = GetFieldIDOrDie(env, clazz, "set", "[I"); - gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I"); - gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I"); - gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I"); - gNetworkStatsClassInfo.defaultNetwork = GetFieldIDOrDie(env, clazz, "defaultNetwork", "[I"); - gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J"); - gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J"); - gNetworkStatsClassInfo.txBytes = GetFieldIDOrDie(env, clazz, "txBytes", "[J"); - gNetworkStatsClassInfo.txPackets = GetFieldIDOrDie(env, clazz, "txPackets", "[J"); - gNetworkStatsClassInfo.operations = GetFieldIDOrDie(env, clazz, "operations", "[J"); + jclass clazz = env->FindClass("android/net/NetworkStats"); + gNetworkStatsClassInfo.size = env->GetFieldID(clazz, "size", "I"); + gNetworkStatsClassInfo.capacity = env->GetFieldID(clazz, "capacity", "I"); + gNetworkStatsClassInfo.iface = env->GetFieldID(clazz, "iface", "[Ljava/lang/String;"); + gNetworkStatsClassInfo.uid = env->GetFieldID(clazz, "uid", "[I"); + gNetworkStatsClassInfo.set = env->GetFieldID(clazz, "set", "[I"); + gNetworkStatsClassInfo.tag = env->GetFieldID(clazz, "tag", "[I"); + gNetworkStatsClassInfo.metered = env->GetFieldID(clazz, "metered", "[I"); + gNetworkStatsClassInfo.roaming = env->GetFieldID(clazz, "roaming", "[I"); + gNetworkStatsClassInfo.defaultNetwork = env->GetFieldID(clazz, "defaultNetwork", "[I"); + gNetworkStatsClassInfo.rxBytes = env->GetFieldID(clazz, "rxBytes", "[J"); + gNetworkStatsClassInfo.rxPackets = env->GetFieldID(clazz, "rxPackets", "[J"); + gNetworkStatsClassInfo.txBytes = env->GetFieldID(clazz, "txBytes", "[J"); + gNetworkStatsClassInfo.txPackets = env->GetFieldID(clazz, "txPackets", "[J"); + gNetworkStatsClassInfo.operations = env->GetFieldID(clazz, "operations", "[J"); return err; } From bf388d54a4bfea5aa32440f2e0ef4b898f370bde Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 20 Mar 2019 09:44:09 -0700 Subject: [PATCH 268/881] Fix flaky UdpEncapsulationSocket test This commit reduces the flakiness of the testOpenAndCloseUdpEncapsulationSocket by retrying up to three times. Unfortunately, testing port-selected socket creation is racy against other applications. This helps to handle the same race condition as done in IpSecService#bindToRandomPort Bug: 128024100 Test: 200x runs of testOpenAndCloseUdpEncapsulationSocket Change-Id: I7e036ce821019dbac6c50899bd0894e89d2fe82a --- services/core/java/com/android/server/IpSecService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 126bf65565..2cfcecca5f 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -96,9 +96,10 @@ public class IpSecService extends IIpSecService.Stub { new int[] {OsConstants.AF_INET, OsConstants.AF_INET6}; private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms - private static final int MAX_PORT_BIND_ATTEMPTS = 10; private static final InetAddress INADDR_ANY; + @VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10; + static { try { INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0}); From d184120d8d515eb1fa452e1aeff88906192fee07 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 28 Feb 2019 20:28:48 -0800 Subject: [PATCH 269/881] Fix remove-before-add for IpSecService RefcountedResource This patch fixes a bug where if a binder dies before the linkToDeath call, the cleanup will be performed before the entry is added to the array. While it is safe in that quotas and tracking performs as per normal, the RefcountedRecord may not be cleaned up. Rethrowing this exception is safe, since the only paths that would hit this are all on binder threads coming from applications. Further, it seems there is only one real way of this getting hit - if the app that called the creation died during the binder call. Bug: 126802451 Test: Compiled, CTS tests passing Change-Id: I6db75853da9f29e1573512e26351623f22770c5d --- services/core/java/com/android/server/IpSecService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 126bf65565..fc7fe5ea56 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -207,6 +207,7 @@ public class IpSecService extends IIpSecService.Stub { mBinder.linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); + e.rethrowFromSystemServer(); } } } From 587caa5aa8299114cf31df9ebbd2632dee33ee68 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 4 Apr 2019 09:18:29 -0700 Subject: [PATCH 270/881] Fix flaky UdpEncapsulationSocket test This commit reduces the flakiness of the testOpenAndCloseUdpEncapsulationSocket by retrying up to three times. Unfortunately, testing port-selected socket creation is racy against other applications. This helps to handle the same race condition as done in IpSecService#bindToRandomPort Bug: 128024100 Test: 200x runs of testOpenAndCloseUdpEncapsulationSocket Change-Id: I7e036ce821019dbac6c50899bd0894e89d2fe82a Merged-In: Idf040a67e53d9b9ec6e6c647ce24f8ada501d355 Merged-In: Iad9aea4b42cd8b31a5a2659bb9cb54dd1c64e8b7 (cherry picked from commit 13fda9e39bdaf5f0503c8db68b4560a2c0034c49) --- services/core/java/com/android/server/IpSecService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 126bf65565..2cfcecca5f 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -96,9 +96,10 @@ public class IpSecService extends IIpSecService.Stub { new int[] {OsConstants.AF_INET, OsConstants.AF_INET6}; private static final int NETD_FETCH_TIMEOUT_MS = 5000; // ms - private static final int MAX_PORT_BIND_ATTEMPTS = 10; private static final InetAddress INADDR_ANY; + @VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10; + static { try { INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0}); From 4722cf1e44c8bd091fbeacd0f2a5e77968ddad56 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 9 Apr 2019 15:46:21 +0900 Subject: [PATCH 271/881] Restrict access to dangerous methods to <= P Test: make Fixes: 130143562 Change-Id: I1a6a472f83cf00a1ab174a9c5e67d3e9357a0c45 --- core/java/android/net/TrafficStats.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 49c6f74b1a..5a22747cb4 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -25,6 +25,7 @@ import android.app.backup.BackupManager; import android.app.usage.NetworkStatsManager; import android.content.Context; import android.media.MediaPlayer; +import android.os.Build; import android.os.RemoteException; import android.os.ServiceManager; import android.util.DataUnit; @@ -150,7 +151,7 @@ public class TrafficStats { private static INetworkStatsService sStatsService; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private synchronized static INetworkStatsService getStatsService() { if (sStatsService == null) { sStatsService = INetworkStatsService.Stub.asInterface( @@ -960,7 +961,7 @@ public class TrafficStats { * Interfaces are never removed from this list, so counters should always be * monotonic. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private static String[] getMobileIfaces() { try { return getStatsService().getMobileIfaces(); From d2fa72a3e1c600f1436d8bee6aa5cc431ba4fd2a Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 9 Apr 2019 19:42:52 +0800 Subject: [PATCH 272/881] Enforce NETWORK_STACK permission for calling NSS#forceUpdateIfaces ConnectivityManager and its usages are removed from NetworkStatsService. After that, forceUpdateIfaces requires information that only ConnectivityService has, hence restricting the calling permission to NETWORK_STACK or MAINLINE_NETWORK_STACK permission. The required permission will be changed from READ_NETWORK_USAGE_HISTORY to NETWORK_STACK or MAINLINE_NETWORK_STACK. This change would make it impossible to call outside the system. Bug: 126830974 Test: atest FrameworksNetTests Change-Id: I776484921b2dbb6735d7940c558fb5e4baed6d1e --- .../core/java/com/android/server/net/NetworkStatsService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index f237c4bca5..484efd6bfd 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -25,6 +25,7 @@ import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.INTERFACES_ALL; @@ -899,7 +900,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { VpnInfo[] vpnArray, NetworkState[] networkStates, String activeIface) { - mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); + checkNetworkStackPermission(mContext); assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); From f786f8914a07e3e0519018429bb88f4e604cf20a Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 9 Apr 2019 11:31:46 -0700 Subject: [PATCH 273/881] Fix remove-before-add for IpSecService RefcountedResource This patch fixes a bug where if a binder dies before the linkToDeath call, the cleanup will be performed before the entry is added to the array. While it is safe in that quotas and tracking performs as per normal, the RefcountedRecord may not be cleaned up. Rethrowing this exception is safe, since the only paths that would hit this are all on binder threads coming from applications. Further, it seems there is only one real way of this getting hit - if the app that called the creation died during the binder call. Bug: 126802451 Test: Compiled, CTS tests passing Change-Id: Ib955acaa5e498c0e977cb5f2e48cffbc9fea8c7c Merged-In: I6db75853da9f29e1573512e26351623f22770c5d Merged-In: I416c2e43961ec0e1cc6b2fbcef970fbce858603b Merged-In: Ib955acaa5e498c0e977cb5f2e48cffbc9fea8c7c (cherry picked from commit c206dde1bdfadb09939f415cf8c0689f24918e03) --- services/core/java/com/android/server/IpSecService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 2cfcecca5f..2055b64483 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -208,6 +208,7 @@ public class IpSecService extends IIpSecService.Stub { mBinder.linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); + e.rethrowFromSystemServer(); } } } From 9ca2f8c911080f80284737edb754c13a490d2133 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 9 Apr 2019 23:24:41 -0700 Subject: [PATCH 274/881] Enforce NETWORK_STACK permission for calling NSS#forceUpdateIfaces ConnectivityManager and its usages are removed from NetworkStatsService. After that, forceUpdateIfaces requires information that only ConnectivityService has, hence restricting the calling permission to NETWORK_STACK or MAINLINE_NETWORK_STACK permission. The required permission will be changed from READ_NETWORK_USAGE_HISTORY to NETWORK_STACK or MAINLINE_NETWORK_STACK. This change would make it impossible to call outside the system. Bug: 126830974 Test: atest FrameworksNetTests Merged-In: I1b26dc64eaab2151e6885fd01cc5e8d4e18c4e60 Change-Id: I4ea421e4126a45f65d25fe0bec74243a3b20aeab (cherry picked from commit e5245130bd3c9196a9854b14ec0866cee137ed33) --- .../core/java/com/android/server/net/NetworkStatsService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 15599111f6..f34ace55a7 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -25,6 +25,7 @@ import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.INTERFACES_ALL; @@ -866,7 +867,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { VpnInfo[] vpnArray, NetworkState[] networkStates, String activeIface) { - mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); + checkNetworkStackPermission(mContext); assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); From a61c36281278e282ac53f5ba91b73748374e192f Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 10 Apr 2019 12:55:07 -0700 Subject: [PATCH 275/881] Add a lock to protect persistent stats snapshot Since the network stats could be polled from multiple services at runtime, it is not thread safe for networkStatsFactory to hold a persistent stats snapshot without any protection. Use a internal lock to prevent concurrent modification on mPersistentSnapshot to fix the problem. Bug: 124764595 Test: android.app.usage.cts.NetworkUsageStatsTest android.net.cts.TrafficStatsTest Change-Id: I22afb46f17697e8b6359d4f593802e0f4b95db8b --- .../server/net/NetworkStatsFactory.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index bf34d8fa6b..bd11d46a97 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -28,6 +28,7 @@ import android.net.NetworkStats; import android.os.StrictMode; import android.os.SystemClock; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; @@ -65,6 +66,7 @@ public class NetworkStatsFactory { private boolean mUseBpfStats; // A persistent Snapshot since device start for eBPF stats + @GuardedBy("mPersistSnapshot") private final NetworkStats mPersistSnapshot; // TODO: only do adjustments in NetworkStatsService and remove this. @@ -289,15 +291,17 @@ public class NetworkStatsFactory { stats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } if (mUseBpfStats) { - if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, - null, TAG_ALL, mUseBpfStats) != 0) { - throw new IOException("Failed to parse network stats"); + synchronized (mPersistSnapshot) { + if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, + null, TAG_ALL, mUseBpfStats) != 0) { + throw new IOException("Failed to parse network stats"); + } + mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime()); + mPersistSnapshot.combineAllValues(stats); + NetworkStats result = mPersistSnapshot.clone(); + result.filter(limitUid, limitIfaces, limitTag); + return result; } - mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime()); - mPersistSnapshot.combineAllValues(stats); - NetworkStats result = mPersistSnapshot.clone(); - result.filter(limitUid, limitIfaces, limitTag); - return result; } else { if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, limitIfaces, limitTag, mUseBpfStats) != 0) { From b7a5ed712570811045cd286da72defd95628fe30 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 27 Feb 2019 19:07:39 -0800 Subject: [PATCH 276/881] Ask netd to swap stats map before reading To avoid protentail race problem between netd and system_server when reading the network stats map. Always inform netd before reading the stats and let netd to do a swap between active stats map and inactive stats map. So the system_server can safely remove the stats after reading. Bug: 126620214 Test: android.app.usage.cts.NetworkUsageStatsTest android.net.cts.TrafficStatsTest Change-Id: I8fa37c26bec23ffca0b29b679e72ba1189f557f1 --- .../server/net/NetworkStatsFactory.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index bd11d46a97..2e64965a61 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -24,7 +24,10 @@ import static android.net.NetworkStats.UID_ALL; import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.annotation.Nullable; +import android.net.INetd; import android.net.NetworkStats; +import android.net.util.NetdService; +import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemClock; @@ -65,6 +68,8 @@ public class NetworkStatsFactory { private boolean mUseBpfStats; + private INetd mNetdService; + // A persistent Snapshot since device start for eBPF stats @GuardedBy("mPersistSnapshot") private final NetworkStats mPersistSnapshot; @@ -279,6 +284,19 @@ public class NetworkStatsFactory { return stats; } + @GuardedBy("mPersistSnapshot") + private void requestSwapActiveStatsMapLocked() throws RemoteException { + // Ask netd to do a active map stats swap. When the binder call successfully returns, + // the system server should be able to safely read and clean the inactive map + // without race problem. + if (mUseBpfStats) { + if (mNetdService == null) { + mNetdService = NetdService.getInstance(); + } + mNetdService.trafficSwapActiveStatsMap(); + } + } + // TODO: delete the lastStats parameter private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces, int limitTag, NetworkStats lastStats) throws IOException { @@ -292,6 +310,13 @@ public class NetworkStatsFactory { } if (mUseBpfStats) { synchronized (mPersistSnapshot) { + try { + requestSwapActiveStatsMapLocked(); + } catch (RemoteException e) { + throw new IOException(e); + } + // Stats are always read from the inactive map, so they must be read after the + // swap if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, null, TAG_ALL, mUseBpfStats) != 0) { throw new IOException("Failed to parse network stats"); From c25767ac57208f7563cb32b9f1ba3c51ac24bafc Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 9 Apr 2019 11:16:56 +0900 Subject: [PATCH 277/881] Move TrafficStats tags for the network stack constants As per API council feedback, these constants should live in a place that is private to the network stack, only with a range defined in system API. Bug: 129433383 Test: m Change-Id: I84a90f84a9af6fef4667ee4d512ebd0413222086 (cherry picked from commit 79a6330650ca04bd7a08afbd63f8016a3b30bc72) --- core/java/android/net/TrafficStats.java | 55 +++++++++++++++++-------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 49c6f74b1a..4332d8abbc 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -89,6 +89,42 @@ public class TrafficStats { */ public static final int UID_TETHERING = -5; + /** + * Tag values in this range are reserved for the network stack. The network stack is + * running as UID {@link android.os.Process.NETWORK_STACK_UID} when in the mainline + * module separate process, and as the system UID otherwise. + */ + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_RANGE_START = 0xFFFFFD00; + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_RANGE_END = 0xFFFFFEFF; + + /** + * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system services + * like DownloadManager when performing traffic on behalf of an application. + */ + // Please note there is no enforcement of these constants, so do not rely on them to + // determine that the caller is a system caller. + /** @hide */ + @SystemApi + public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = 0xFFFFFF00; + /** @hide */ + @SystemApi + public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = 0xFFFFFF0F; + + /** + * Tag values between these ranges are reserved for the network stack to do traffic + * on behalf of applications. It is a subrange of the range above. + */ + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = 0xFFFFFF80; + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = 0xFFFFFF8F; + /** * Default tag value for {@link DownloadManager} traffic. * @@ -127,26 +163,9 @@ public class TrafficStats { */ public static final int TAG_SYSTEM_APP = 0xFFFFFF05; + // TODO : remove this constant when Wifi code is updated /** @hide */ - @SystemApi - @TestApi - public static final int TAG_SYSTEM_DHCP = 0xFFFFFF40; - /** @hide */ - public static final int TAG_SYSTEM_NTP = 0xFFFFFF41; - /** @hide */ - @SystemApi - @TestApi public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42; - /** @hide */ - public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF43; - /** @hide */ - public static final int TAG_SYSTEM_GPS = 0xFFFFFF44; - /** @hide */ - public static final int TAG_SYSTEM_PAC = 0xFFFFFF45; - /** @hide */ - @SystemApi - @TestApi - public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46; private static INetworkStatsService sStatsService; From ed723aee02844541b723d8dcd99ec85c6bcf0f0a Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 9 Apr 2019 15:46:21 +0900 Subject: [PATCH 278/881] Restrict access to dangerous methods to <= P Test: make Fixes: 130143562 Change-Id: I1a6a472f83cf00a1ab174a9c5e67d3e9357a0c45 Merged-In: I95107f7b628eecb54e9f4411785186b668e9f3d8 Merged-In: I890030580fdad45c3f8589bf6adbe5798d578cfe (cherry picked from commit 4722cf1e44c8bd091fbeacd0f2a5e77968ddad56) --- core/java/android/net/TrafficStats.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 49c6f74b1a..5a22747cb4 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -25,6 +25,7 @@ import android.app.backup.BackupManager; import android.app.usage.NetworkStatsManager; import android.content.Context; import android.media.MediaPlayer; +import android.os.Build; import android.os.RemoteException; import android.os.ServiceManager; import android.util.DataUnit; @@ -150,7 +151,7 @@ public class TrafficStats { private static INetworkStatsService sStatsService; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private synchronized static INetworkStatsService getStatsService() { if (sStatsService == null) { sStatsService = INetworkStatsService.Stub.asInterface( @@ -960,7 +961,7 @@ public class TrafficStats { * Interfaces are never removed from this list, so counters should always be * monotonic. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private static String[] getMobileIfaces() { try { return getStatsService().getMobileIfaces(); From 65c3968e29e7af4e26e0a0505f75ffcf934d6310 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 9 Apr 2019 11:16:56 +0900 Subject: [PATCH 279/881] Move TrafficStats tags for the network stack constants As per API council feedback, these constants should live in a place that is private to the network stack, only with a range defined in system API. Bug: 129433383 Test: m Change-Id: I84a90f84a9af6fef4667ee4d512ebd0413222086 Merged-In: I4882686a86e7c6d42f4b0619b921d02619ed6d4c Merged-In: I9b648ed6c687d56db61a54570c7880c51c1bae51 --- core/java/android/net/TrafficStats.java | 55 +++++++++++++++++-------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 49c6f74b1a..4332d8abbc 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -89,6 +89,42 @@ public class TrafficStats { */ public static final int UID_TETHERING = -5; + /** + * Tag values in this range are reserved for the network stack. The network stack is + * running as UID {@link android.os.Process.NETWORK_STACK_UID} when in the mainline + * module separate process, and as the system UID otherwise. + */ + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_RANGE_START = 0xFFFFFD00; + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_RANGE_END = 0xFFFFFEFF; + + /** + * Tags between 0xFFFFFF00 and 0xFFFFFFFF are reserved and used internally by system services + * like DownloadManager when performing traffic on behalf of an application. + */ + // Please note there is no enforcement of these constants, so do not rely on them to + // determine that the caller is a system caller. + /** @hide */ + @SystemApi + public static final int TAG_SYSTEM_IMPERSONATION_RANGE_START = 0xFFFFFF00; + /** @hide */ + @SystemApi + public static final int TAG_SYSTEM_IMPERSONATION_RANGE_END = 0xFFFFFF0F; + + /** + * Tag values between these ranges are reserved for the network stack to do traffic + * on behalf of applications. It is a subrange of the range above. + */ + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_START = 0xFFFFFF80; + /** @hide */ + @SystemApi + public static final int TAG_NETWORK_STACK_IMPERSONATION_RANGE_END = 0xFFFFFF8F; + /** * Default tag value for {@link DownloadManager} traffic. * @@ -127,26 +163,9 @@ public class TrafficStats { */ public static final int TAG_SYSTEM_APP = 0xFFFFFF05; + // TODO : remove this constant when Wifi code is updated /** @hide */ - @SystemApi - @TestApi - public static final int TAG_SYSTEM_DHCP = 0xFFFFFF40; - /** @hide */ - public static final int TAG_SYSTEM_NTP = 0xFFFFFF41; - /** @hide */ - @SystemApi - @TestApi public static final int TAG_SYSTEM_PROBE = 0xFFFFFF42; - /** @hide */ - public static final int TAG_SYSTEM_NEIGHBOR = 0xFFFFFF43; - /** @hide */ - public static final int TAG_SYSTEM_GPS = 0xFFFFFF44; - /** @hide */ - public static final int TAG_SYSTEM_PAC = 0xFFFFFF45; - /** @hide */ - @SystemApi - @TestApi - public static final int TAG_SYSTEM_DHCP_SERVER = 0xFFFFFF46; private static INetworkStatsService sStatsService; From e5b426fba66157edd159c21bad8ca8189f9e47e5 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 25 Feb 2019 12:33:22 -0800 Subject: [PATCH 280/881] Add NATT keepalive resources and methods into IpSecService This change adds a new NATTKeepalive resource type, along with the associated allocation/deallocation. Additionally, this change allows ReferenceCountedResource(s) to not be binder-linked, to allow the ConnectivityService to verify ownership and allocate a NattKeepalive without double-registering for binder-death notifications. Bug: 125517194 Test: IpSecService frameworks tests ran Change-Id: I8293f79940ad57dabb6f2b9de5e334d06b869443 --- core/java/android/net/IIpSecService.aidl | 4 + .../java/com/android/server/IpSecService.java | 166 ++++++++++++++++-- 2 files changed, 159 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index d6774d47b4..b5a2a16c7f 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -72,4 +72,8 @@ interface IIpSecService int tunnelResourceId, int direction, int transformResourceId, in String callingPackage); void removeTransportModeTransforms(in ParcelFileDescriptor socket); + + int lockEncapSocketForNattKeepalive(int encapSocketResourceId, int requesterUid); + + void releaseNattKeepalive(int nattKeepaliveResourceId, int ownerUid); } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 2055b64483..c1f52552ea 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -28,8 +28,10 @@ import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; import android.net.IIpSecService; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -42,6 +44,7 @@ import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; +import android.net.NetworkStack; import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; @@ -74,6 +77,8 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; /** @@ -174,6 +179,14 @@ public class IpSecService extends IIpSecService.Stub { void freeUnderlyingResources() throws RemoteException; } + /** + * Sentinel value placeholder for a real binder in RefcountedResources. + * + *

Used for cases where there the allocating party is a system service, and thus is expected + * to track the resource lifecycles instead of IpSecService. + */ + private static final Binder DUMMY_BINDER = new Binder(); + /** * RefcountedResource manages references and dependencies in an exclusively acyclic graph. * @@ -188,24 +201,42 @@ public class IpSecService extends IIpSecService.Stub { */ @VisibleForTesting public class RefcountedResource implements IBinder.DeathRecipient { - private final T mResource; - private final List mChildren; - int mRefCount = 1; // starts at 1 for user's reference. - IBinder mBinder; - RefcountedResource(T resource, IBinder binder, RefcountedResource... children) { + @NonNull private final T mResource; + @NonNull private final List mChildren; + int mRefCount = 1; // starts at 1 for user's reference. + + /* + * This field can take one of three states: + * 1. null, when the object has been released by the user (or the user's binder dies) + * 2. DUMMY_BINDER, when the refcounted resource is allocated from another system service + * and the other system service manages the lifecycle of the resource instead of + * IpSecService. + * 3. an actual binder, to ensure IpSecService can cleanup after users that forget to close + * their resources. + */ + @Nullable IBinder mBinder; + + RefcountedResource(@NonNull T resource, @NonNull RefcountedResource... children) { + this(resource, DUMMY_BINDER, children); + } + + RefcountedResource( + @NonNull T resource, + @NonNull IBinder binder, + @NonNull RefcountedResource... children) { synchronized (IpSecService.this) { this.mResource = resource; - this.mChildren = new ArrayList<>(children.length); this.mBinder = binder; - + this.mChildren = Collections.unmodifiableList(Arrays.asList(children)); for (RefcountedResource child : children) { - mChildren.add(child); child.mRefCount++; } try { - mBinder.linkToDeath(this, 0); + if (mBinder != DUMMY_BINDER) { + mBinder.linkToDeath(this, 0); + } } catch (RemoteException e) { binderDied(); e.rethrowFromSystemServer(); @@ -252,11 +283,12 @@ public class IpSecService extends IIpSecService.Stub { return; } - mBinder.unlinkToDeath(this, 0); + if (mBinder != DUMMY_BINDER) { + mBinder.unlinkToDeath(this, 0); + } mBinder = null; mResource.invalidate(); - releaseReference(); } @@ -381,6 +413,8 @@ public class IpSecService extends IIpSecService.Stub { new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName()); final RefcountedResourceArray mTunnelInterfaceRecords = new RefcountedResourceArray<>(TunnelInterfaceRecord.class.getSimpleName()); + final RefcountedResourceArray mNattKeepaliveRecords = + new RefcountedResourceArray<>(NattKeepaliveRecord.class.getSimpleName()); /** * Trackers for quotas for each of the OwnedResource types. @@ -394,6 +428,8 @@ public class IpSecService extends IIpSecService.Stub { final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS); final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS); final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); + final ResourceTracker mNattKeepaliveQuotaTracker = + new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); // Max 1 NATT keepalive per encap socket final ResourceTracker mTunnelQuotaTracker = new ResourceTracker(MAX_NUM_TUNNEL_INTERFACES); void removeSpiRecord(int resourceId) { @@ -412,6 +448,10 @@ public class IpSecService extends IIpSecService.Stub { mEncapSocketRecords.remove(resourceId); } + void removeNattKeepaliveRecord(int resourceId) { + mNattKeepaliveRecords.remove(resourceId); + } + @Override public String toString() { return new StringBuilder() @@ -421,6 +461,8 @@ public class IpSecService extends IIpSecService.Stub { .append(mTransformQuotaTracker) .append(", mSocketQuotaTracker=") .append(mSocketQuotaTracker) + .append(", mNattKeepaliveQuotaTracker=") + .append(mNattKeepaliveQuotaTracker) .append(", mTunnelQuotaTracker=") .append(mTunnelQuotaTracker) .append(", mSpiRecords=") @@ -429,6 +471,8 @@ public class IpSecService extends IIpSecService.Stub { .append(mTransformRecords) .append(", mEncapSocketRecords=") .append(mEncapSocketRecords) + .append(", mNattKeepaliveRecords=") + .append(mNattKeepaliveRecords) .append(", mTunnelInterfaceRecords=") .append(mTunnelInterfaceRecords) .append("}") @@ -573,6 +617,11 @@ public class IpSecService extends IIpSecService.Stub { mArray.remove(key); } + @VisibleForTesting + int size() { + return mArray.size(); + } + @Override public String toString() { return mArray.toString(); @@ -983,6 +1032,50 @@ public class IpSecService extends IIpSecService.Stub { } } + /** + * Tracks a NATT-keepalive instance + * + *

This class ensures that while a NATT-keepalive is active, the UDP encap socket that it is + * supporting will stay open until the NATT-keepalive is finished. NATT-keepalive offload + * lifecycles will be managed by ConnectivityService, which will validate that the UDP Encap + * socket is owned by the requester, and take a reference to it via this NattKeepaliveRecord + * + *

It shall be the responsibility of the caller to ensure that instances of an EncapSocket do + * not spawn multiple instances of NATT keepalives (and thereby register duplicate records) + */ + private final class NattKeepaliveRecord extends OwnedResourceRecord { + NattKeepaliveRecord(int resourceId) { + super(resourceId); + } + + @Override + @GuardedBy("IpSecService.this") + public void freeUnderlyingResources() { + Log.d(TAG, "Natt Keepalive released: " + mResourceId); + + getResourceTracker().give(); + } + + @Override + protected ResourceTracker getResourceTracker() { + return getUserRecord().mNattKeepaliveQuotaTracker; + } + + @Override + public void invalidate() { + getUserRecord().removeNattKeepaliveRecord(mResourceId); + } + + @Override + public String toString() { + return new StringBuilder() + .append("{super=") + .append(super.toString()) + .append("}") + .toString(); + } + } + /** * Constructs a new IpSecService instance * @@ -1818,6 +1911,57 @@ public class IpSecService extends IIpSecService.Stub { } } + private void verifyNetworkStackCaller() { + if (mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + != PackageManager.PERMISSION_GRANTED + && mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Requires permission NETWORK_STACK or MAINLINE_NETWORK_STACK"); + } + } + + /** + * Validates that a provided UID owns the encapSocket, and creates a NATT keepalive record + * + *

For system server use only. Caller must have NETWORK_STACK permission + * + * @param encapSocketResourceId resource identifier of the encap socket record + * @param ownerUid the UID of the caller. Used to verify ownership. + * @return + */ + public synchronized int lockEncapSocketForNattKeepalive( + int encapSocketResourceId, int ownerUid) { + verifyNetworkStackCaller(); + + // Verify ownership. Will throw IllegalArgumentException if the UID specified does not + // own the specified UDP encapsulation socket + UserRecord userRecord = mUserResourceTracker.getUserRecord(ownerUid); + RefcountedResource refcountedSocketRecord = + userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(encapSocketResourceId); + + // Build NattKeepaliveRecord + final int resourceId = mNextResourceId++; + userRecord.mNattKeepaliveRecords.put( + resourceId, + new RefcountedResource( + new NattKeepaliveRecord(resourceId), refcountedSocketRecord)); + + return resourceId; + } + + /** + * Release a previously allocated NattKeepalive that has been registered with the system server + */ + @Override + public synchronized void releaseNattKeepalive(int nattKeepaliveResourceId, int ownerUid) + throws RemoteException { + verifyNetworkStackCaller(); + + UserRecord userRecord = mUserResourceTracker.getUserRecord(ownerUid); + releaseResource(userRecord.mNattKeepaliveRecords, nattKeepaliveResourceId); + } + @Override protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); From e98964d7d287296aeb5619c6f0e2d1f0b868dd3b Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Thu, 11 Apr 2019 18:44:45 -0700 Subject: [PATCH 281/881] Add a lock to protect persistent stats snapshot Since the network stats could be polled from multiple services at runtime, it is not thread safe for networkStatsFactory to hold a persistent stats snapshot without any protection. Use a internal lock to prevent concurrent modification on mPersistentSnapshot to fix the problem. Bug: 124764595 Test: android.app.usage.cts.NetworkUsageStatsTest android.net.cts.TrafficStatsTest Change-Id: I73851336452110afb74d6dd1ca5e50047d5b3d4a Merged-In: I73851336452110afb74d6dd1ca5e50047d5b3d4a Merged-In: I22afb46f17697e8b6359d4f593802e0f4b95db8b (cherry picked from commit 180c020966422bcd127de0adb7b1042534ac5baf) --- .../server/net/NetworkStatsFactory.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index af299cf66d..174f60091d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -28,6 +28,7 @@ import android.net.NetworkStats; import android.os.StrictMode; import android.os.SystemClock; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; @@ -65,6 +66,7 @@ public class NetworkStatsFactory { private boolean mUseBpfStats; // A persistent Snapshot since device start for eBPF stats + @GuardedBy("mPersistSnapshot") private final NetworkStats mPersistSnapshot; // TODO: only do adjustments in NetworkStatsService and remove this. @@ -284,15 +286,17 @@ public class NetworkStatsFactory { stats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } if (mUseBpfStats) { - if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, - null, TAG_ALL, mUseBpfStats) != 0) { - throw new IOException("Failed to parse network stats"); + synchronized (mPersistSnapshot) { + if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, + null, TAG_ALL, mUseBpfStats) != 0) { + throw new IOException("Failed to parse network stats"); + } + mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime()); + mPersistSnapshot.combineAllValues(stats); + NetworkStats result = mPersistSnapshot.clone(); + result.filter(limitUid, limitIfaces, limitTag); + return result; } - mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime()); - mPersistSnapshot.combineAllValues(stats); - NetworkStats result = mPersistSnapshot.clone(); - result.filter(limitUid, limitIfaces, limitTag); - return result; } else { if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, limitIfaces, limitTag, mUseBpfStats) != 0) { From 04a2c86ba594cb02c330acfa85163d85da44c8fe Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Wed, 27 Feb 2019 19:07:39 -0800 Subject: [PATCH 282/881] Ask netd to swap stats map before reading To avoid protentail race problem between netd and system_server when reading the network stats map. Always inform netd before reading the stats and let netd to do a swap between active stats map and inactive stats map. So the system_server can safely remove the stats after reading. Bug: 126620214 Test: android.app.usage.cts.NetworkUsageStatsTest android.net.cts.TrafficStatsTest Change-Id: I8fa37c26bec23ffca0b29b679e72ba1189f557f1 Merged-In: I8fa37c26bec23ffca0b29b679e72ba1189f557f1 (cherry picked from commit b7a5ed712570811045cd286da72defd95628fe30) --- .../server/net/NetworkStatsFactory.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 174f60091d..69efd02dea 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -24,7 +24,10 @@ import static android.net.NetworkStats.UID_ALL; import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.annotation.Nullable; +import android.net.INetd; import android.net.NetworkStats; +import android.net.util.NetdService; +import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemClock; @@ -65,6 +68,8 @@ public class NetworkStatsFactory { private boolean mUseBpfStats; + private INetd mNetdService; + // A persistent Snapshot since device start for eBPF stats @GuardedBy("mPersistSnapshot") private final NetworkStats mPersistSnapshot; @@ -274,6 +279,19 @@ public class NetworkStatsFactory { return stats; } + @GuardedBy("mPersistSnapshot") + private void requestSwapActiveStatsMapLocked() throws RemoteException { + // Ask netd to do a active map stats swap. When the binder call successfully returns, + // the system server should be able to safely read and clean the inactive map + // without race problem. + if (mUseBpfStats) { + if (mNetdService == null) { + mNetdService = NetdService.getInstance(); + } + mNetdService.trafficSwapActiveStatsMap(); + } + } + // TODO: delete the lastStats parameter private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces, int limitTag, NetworkStats lastStats) throws IOException { @@ -287,6 +305,13 @@ public class NetworkStatsFactory { } if (mUseBpfStats) { synchronized (mPersistSnapshot) { + try { + requestSwapActiveStatsMapLocked(); + } catch (RemoteException e) { + throw new IOException(e); + } + // Stats are always read from the inactive map, so they must be read after the + // swap if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, null, TAG_ALL, mUseBpfStats) != 0) { throw new IOException("Failed to parse network stats"); From c32795470c56ba7517b12d09519239ab3c13e0ab Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 16 Jul 2018 14:56:20 -0700 Subject: [PATCH 283/881] Add EPROTONOSUPPORT to IpSecManager SSE map This change maps EPROTONOSUPPORT to the list of error codes that map to UnsupportedOperationException in IpSecManager. Bug: 80103456 Test: Compiles, CTS tests ran Change-Id: Iec3d5fc4a9bcad7c104414afefae775232d46558 --- core/java/android/net/IpSecManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index d4c3edca43..889e9bc787 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -941,7 +941,8 @@ public final class IpSecManager { throw new IllegalArgumentException(sse); } else if (sse.errorCode == OsConstants.EAGAIN) { throw new IllegalStateException(sse); - } else if (sse.errorCode == OsConstants.EOPNOTSUPP) { + } else if (sse.errorCode == OsConstants.EOPNOTSUPP + || sse.errorCode == OsConstants.EPROTONOSUPPORT) { throw new UnsupportedOperationException(sse); } } From 540ea7d69ab4a640a9a1a4593bc024c3b1f78b94 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 16 Jul 2018 14:56:20 -0700 Subject: [PATCH 284/881] Add EPROTONOSUPPORT to IpSecManager SSE map This change maps EPROTONOSUPPORT to the list of error codes that map to UnsupportedOperationException in IpSecManager. Bug: 80103456 Test: Compiles, CTS tests ran Change-Id: Iec3d5fc4a9bcad7c104414afefae775232d46558 Merged-In: Iec3d5fc4a9bcad7c104414afefae775232d46558 (cherry picked from commit dcbc670688d815ce89954765fac46aa2ad6d8adb) --- core/java/android/net/IpSecManager.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 1145d5bd4d..7d34381f73 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -947,7 +947,8 @@ public final class IpSecManager { throw new IllegalArgumentException(sse); } else if (sse.errorCode == OsConstants.EAGAIN) { throw new IllegalStateException(sse); - } else if (sse.errorCode == OsConstants.EOPNOTSUPP) { + } else if (sse.errorCode == OsConstants.EOPNOTSUPP + || sse.errorCode == OsConstants.EPROTONOSUPPORT) { throw new UnsupportedOperationException(sse); } } From 01e9de82dc41c7c698d9cd07419644c2f9b119b5 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 8 Nov 2018 19:45:34 -0800 Subject: [PATCH 285/881] Add IPsec checks for IPSEC_TUNNEL feature This patch adds checks to ensure that the IPSEC_TUNNEL feature flag is enabled. Bug: 117183273 Test: Compiles & tests passing Change-Id: I2699dda29e1eed139bc6fd1b70071e5ab33cad88 --- core/java/android/net/IpSecManager.java | 6 ++++++ core/java/android/net/IpSecTransform.java | 3 +++ .../java/com/android/server/IpSecService.java | 20 ++++++++++++------- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 1145d5bd4d..61fa04aed0 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -19,11 +19,13 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -749,6 +751,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { @@ -771,6 +774,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { try { @@ -886,6 +890,7 @@ public final class IpSecManager { */ @SystemApi @NonNull + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) @@ -916,6 +921,7 @@ public final class IpSecManager { * @hide */ @SystemApi + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, @PolicyDirection int direction, @NonNull IpSecTransform transform) throws IOException { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index e519fdf65e..36111f2a37 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -21,9 +21,11 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -483,6 +485,7 @@ public final class IpSecTransform implements AutoCloseable { */ @SystemApi @NonNull + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public IpSecTransform buildTunnelModeTransform( @NonNull InetAddress sourceAddress, diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 2055b64483..fe22dcda96 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -30,6 +30,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; import android.net.IIpSecService; import android.net.INetd; import android.net.IpSecAlgorithm; @@ -1276,7 +1277,7 @@ public class IpSecService extends IIpSecService.Stub { public synchronized IpSecTunnelInterfaceResponse createTunnelInterface( String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, String callingPackage) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); checkNotNull(binder, "Null Binder passed to createTunnelInterface"); checkNotNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); @@ -1362,7 +1363,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void addAddressToTunnelInterface( int tunnelResourceId, LinkAddress localAddr, String callingPackage) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1391,7 +1392,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeAddressFromTunnelInterface( int tunnelResourceId, LinkAddress localAddr, String callingPackage) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); // Get tunnelInterface record; if no such interface is found, will throw @@ -1420,7 +1421,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void deleteTunnelInterface( int resourceId, String callingPackage) throws RemoteException { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); releaseResource(userRecord.mTunnelInterfaceRecords, resourceId); } @@ -1549,7 +1550,12 @@ public class IpSecService extends IIpSecService.Stub { private static final String TUNNEL_OP = AppOpsManager.OPSTR_MANAGE_IPSEC_TUNNELS; - private void enforceTunnelPermissions(String callingPackage) { + private void enforceTunnelFeatureAndPermissions(String callingPackage) { + if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) { + throw new UnsupportedOperationException( + "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS"); + } + checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) { case AppOpsManager.MODE_DEFAULT: @@ -1621,7 +1627,7 @@ public class IpSecService extends IIpSecService.Stub { IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { checkNotNull(c); if (c.getMode() == IpSecTransform.MODE_TUNNEL) { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); } checkIpSecConfig(c); checkNotNull(binder, "Null Binder passed to createTransform"); @@ -1729,7 +1735,7 @@ public class IpSecService extends IIpSecService.Stub { public synchronized void applyTunnelModeTransform( int tunnelResourceId, int direction, int transformResourceId, String callingPackage) throws RemoteException { - enforceTunnelPermissions(callingPackage); + enforceTunnelFeatureAndPermissions(callingPackage); checkDirection(direction); int callingUid = Binder.getCallingUid(); From b8c6549326a2089fb62de8a105940f8584f29e44 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 26 Apr 2019 01:38:04 +0000 Subject: [PATCH 286/881] Revert "Add NATT keepalive resources and methods into IpSecService" This reverts commit e5b426fba66157edd159c21bad8ca8189f9e47e5. Reason for revert: Adds dependency between IpSecService and ConnectivityService may lead to future deadlock problems. Uses a simpler approach instead, hence the solution is not needed. See aosp/954040. Change-Id: Ibff278a6eee666cd85dba81c2bed94d568679b02 --- core/java/android/net/IIpSecService.aidl | 4 - .../java/com/android/server/IpSecService.java | 163 ++---------------- 2 files changed, 10 insertions(+), 157 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index b5a2a16c7f..d6774d47b4 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -72,8 +72,4 @@ interface IIpSecService int tunnelResourceId, int direction, int transformResourceId, in String callingPackage); void removeTransportModeTransforms(in ParcelFileDescriptor socket); - - int lockEncapSocketForNattKeepalive(int encapSocketResourceId, int requesterUid); - - void releaseNattKeepalive(int nattKeepaliveResourceId, int ownerUid); } diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index c1f52552ea..b4e1c32f25 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -28,7 +28,6 @@ import static android.system.OsConstants.SOCK_DGRAM; import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; @@ -44,7 +43,6 @@ import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; -import android.net.NetworkStack; import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; @@ -77,8 +75,6 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; /** @@ -179,14 +175,6 @@ public class IpSecService extends IIpSecService.Stub { void freeUnderlyingResources() throws RemoteException; } - /** - * Sentinel value placeholder for a real binder in RefcountedResources. - * - *

Used for cases where there the allocating party is a system service, and thus is expected - * to track the resource lifecycles instead of IpSecService. - */ - private static final Binder DUMMY_BINDER = new Binder(); - /** * RefcountedResource manages references and dependencies in an exclusively acyclic graph. * @@ -201,42 +189,24 @@ public class IpSecService extends IIpSecService.Stub { */ @VisibleForTesting public class RefcountedResource implements IBinder.DeathRecipient { - - @NonNull private final T mResource; - @NonNull private final List mChildren; + private final T mResource; + private final List mChildren; int mRefCount = 1; // starts at 1 for user's reference. + IBinder mBinder; - /* - * This field can take one of three states: - * 1. null, when the object has been released by the user (or the user's binder dies) - * 2. DUMMY_BINDER, when the refcounted resource is allocated from another system service - * and the other system service manages the lifecycle of the resource instead of - * IpSecService. - * 3. an actual binder, to ensure IpSecService can cleanup after users that forget to close - * their resources. - */ - @Nullable IBinder mBinder; - - RefcountedResource(@NonNull T resource, @NonNull RefcountedResource... children) { - this(resource, DUMMY_BINDER, children); - } - - RefcountedResource( - @NonNull T resource, - @NonNull IBinder binder, - @NonNull RefcountedResource... children) { + RefcountedResource(T resource, IBinder binder, RefcountedResource... children) { synchronized (IpSecService.this) { this.mResource = resource; + this.mChildren = new ArrayList<>(children.length); this.mBinder = binder; - this.mChildren = Collections.unmodifiableList(Arrays.asList(children)); + for (RefcountedResource child : children) { + mChildren.add(child); child.mRefCount++; } try { - if (mBinder != DUMMY_BINDER) { - mBinder.linkToDeath(this, 0); - } + mBinder.linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); e.rethrowFromSystemServer(); @@ -283,12 +253,11 @@ public class IpSecService extends IIpSecService.Stub { return; } - if (mBinder != DUMMY_BINDER) { - mBinder.unlinkToDeath(this, 0); - } + mBinder.unlinkToDeath(this, 0); mBinder = null; mResource.invalidate(); + releaseReference(); } @@ -413,8 +382,6 @@ public class IpSecService extends IIpSecService.Stub { new RefcountedResourceArray<>(EncapSocketRecord.class.getSimpleName()); final RefcountedResourceArray mTunnelInterfaceRecords = new RefcountedResourceArray<>(TunnelInterfaceRecord.class.getSimpleName()); - final RefcountedResourceArray mNattKeepaliveRecords = - new RefcountedResourceArray<>(NattKeepaliveRecord.class.getSimpleName()); /** * Trackers for quotas for each of the OwnedResource types. @@ -428,8 +395,6 @@ public class IpSecService extends IIpSecService.Stub { final ResourceTracker mSpiQuotaTracker = new ResourceTracker(MAX_NUM_SPIS); final ResourceTracker mTransformQuotaTracker = new ResourceTracker(MAX_NUM_TRANSFORMS); final ResourceTracker mSocketQuotaTracker = new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); - final ResourceTracker mNattKeepaliveQuotaTracker = - new ResourceTracker(MAX_NUM_ENCAP_SOCKETS); // Max 1 NATT keepalive per encap socket final ResourceTracker mTunnelQuotaTracker = new ResourceTracker(MAX_NUM_TUNNEL_INTERFACES); void removeSpiRecord(int resourceId) { @@ -448,10 +413,6 @@ public class IpSecService extends IIpSecService.Stub { mEncapSocketRecords.remove(resourceId); } - void removeNattKeepaliveRecord(int resourceId) { - mNattKeepaliveRecords.remove(resourceId); - } - @Override public String toString() { return new StringBuilder() @@ -461,8 +422,6 @@ public class IpSecService extends IIpSecService.Stub { .append(mTransformQuotaTracker) .append(", mSocketQuotaTracker=") .append(mSocketQuotaTracker) - .append(", mNattKeepaliveQuotaTracker=") - .append(mNattKeepaliveQuotaTracker) .append(", mTunnelQuotaTracker=") .append(mTunnelQuotaTracker) .append(", mSpiRecords=") @@ -471,8 +430,6 @@ public class IpSecService extends IIpSecService.Stub { .append(mTransformRecords) .append(", mEncapSocketRecords=") .append(mEncapSocketRecords) - .append(", mNattKeepaliveRecords=") - .append(mNattKeepaliveRecords) .append(", mTunnelInterfaceRecords=") .append(mTunnelInterfaceRecords) .append("}") @@ -617,11 +574,6 @@ public class IpSecService extends IIpSecService.Stub { mArray.remove(key); } - @VisibleForTesting - int size() { - return mArray.size(); - } - @Override public String toString() { return mArray.toString(); @@ -1032,50 +984,6 @@ public class IpSecService extends IIpSecService.Stub { } } - /** - * Tracks a NATT-keepalive instance - * - *

This class ensures that while a NATT-keepalive is active, the UDP encap socket that it is - * supporting will stay open until the NATT-keepalive is finished. NATT-keepalive offload - * lifecycles will be managed by ConnectivityService, which will validate that the UDP Encap - * socket is owned by the requester, and take a reference to it via this NattKeepaliveRecord - * - *

It shall be the responsibility of the caller to ensure that instances of an EncapSocket do - * not spawn multiple instances of NATT keepalives (and thereby register duplicate records) - */ - private final class NattKeepaliveRecord extends OwnedResourceRecord { - NattKeepaliveRecord(int resourceId) { - super(resourceId); - } - - @Override - @GuardedBy("IpSecService.this") - public void freeUnderlyingResources() { - Log.d(TAG, "Natt Keepalive released: " + mResourceId); - - getResourceTracker().give(); - } - - @Override - protected ResourceTracker getResourceTracker() { - return getUserRecord().mNattKeepaliveQuotaTracker; - } - - @Override - public void invalidate() { - getUserRecord().removeNattKeepaliveRecord(mResourceId); - } - - @Override - public String toString() { - return new StringBuilder() - .append("{super=") - .append(super.toString()) - .append("}") - .toString(); - } - } - /** * Constructs a new IpSecService instance * @@ -1911,57 +1819,6 @@ public class IpSecService extends IIpSecService.Stub { } } - private void verifyNetworkStackCaller() { - if (mContext.checkCallingOrSelfPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) - != PackageManager.PERMISSION_GRANTED - && mContext.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_STACK) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException( - "Requires permission NETWORK_STACK or MAINLINE_NETWORK_STACK"); - } - } - - /** - * Validates that a provided UID owns the encapSocket, and creates a NATT keepalive record - * - *

For system server use only. Caller must have NETWORK_STACK permission - * - * @param encapSocketResourceId resource identifier of the encap socket record - * @param ownerUid the UID of the caller. Used to verify ownership. - * @return - */ - public synchronized int lockEncapSocketForNattKeepalive( - int encapSocketResourceId, int ownerUid) { - verifyNetworkStackCaller(); - - // Verify ownership. Will throw IllegalArgumentException if the UID specified does not - // own the specified UDP encapsulation socket - UserRecord userRecord = mUserResourceTracker.getUserRecord(ownerUid); - RefcountedResource refcountedSocketRecord = - userRecord.mEncapSocketRecords.getRefcountedResourceOrThrow(encapSocketResourceId); - - // Build NattKeepaliveRecord - final int resourceId = mNextResourceId++; - userRecord.mNattKeepaliveRecords.put( - resourceId, - new RefcountedResource( - new NattKeepaliveRecord(resourceId), refcountedSocketRecord)); - - return resourceId; - } - - /** - * Release a previously allocated NattKeepalive that has been registered with the system server - */ - @Override - public synchronized void releaseNattKeepalive(int nattKeepaliveResourceId, int ownerUid) - throws RemoteException { - verifyNetworkStackCaller(); - - UserRecord userRecord = mUserResourceTracker.getUserRecord(ownerUid); - releaseResource(userRecord.mNattKeepaliveRecords, nattKeepaliveResourceId); - } - @Override protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); From 624100d0432e654d6832081ff410dc28e9304a10 Mon Sep 17 00:00:00 2001 From: Lei Yu Date: Thu, 9 May 2019 11:53:57 -0700 Subject: [PATCH 287/881] Use merged NetworkTemplate to query data usage This CL uses merged NetworkTemplate so that it shows correct data for carrier which is a virtual that has multiple subscriberId under the hood. By doing this, this CL also adds several hidden API so settings can query by NetworkTemplate directly. Fixes: 120566366 Test: RunSettingsLibRoboTests Change-Id: I8b747697933c75b48b14387adafb5ac9ca165926 --- .../app/usage/NetworkStatsManager.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 59ae3347f4..8e40449fa5 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -278,6 +278,12 @@ public class NetworkStatsManager { return null; } + return querySummary(template, startTime, endTime); + } + + /** @hide */ + public NetworkStats querySummary(NetworkTemplate template, long startTime, + long endTime) throws SecurityException, RemoteException { NetworkStats result; result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); result.startSummaryEnumeration(); @@ -296,6 +302,13 @@ public class NetworkStatsManager { NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL); } + /** @hide */ + public NetworkStats queryDetailsForUid(NetworkTemplate template, + long startTime, long endTime, int uid) throws SecurityException { + return queryDetailsForUidTagState(template, startTime, endTime, uid, + NetworkStats.Bucket.TAG_NONE, NetworkStats.Bucket.STATE_ALL); + } + /** * Query network usage statistics details for a given uid and tag. * @@ -340,6 +353,13 @@ public class NetworkStatsManager { NetworkTemplate template; template = createTemplate(networkType, subscriberId); + return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state); + } + + /** @hide */ + public NetworkStats queryDetailsForUidTagState(NetworkTemplate template, + long startTime, long endTime, int uid, int tag, int state) throws SecurityException { + NetworkStats result; try { result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); From 438e6cbbd51b2e5f8521f6022937086ba4cae3a6 Mon Sep 17 00:00:00 2001 From: "tank.hung" Date: Thu, 4 Apr 2019 22:37:49 +0800 Subject: [PATCH 288/881] Add reconnect flow when updateIPConfiguration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: 119085164 Test: manual, test with AndroidTV device Partner gerrit review CL: https://partner-android-review.googlesource.com/c/platform/frameworks/opt/net/ethernet/+/1215654 [Analysis] APP called EthernetManager.setConfiguration API for switch DHCP to Static, setConfiguration’s flow just only update IpConfig finally but have not trigger EthernetNetworkFactory.start(). So Static IP Setting just only take effect when unplug/plug Ethernet Cable or AC Off&On. [Repeat Steps] 1. Connect Ethernet with DHCP and Network access is normal 2. Change IP settings from DHCP to Static and set Static IP. 3. After setting, you can not automatically obtain Static IP. [Recovery Method] Unplug the Ethernet and insert it or AC OFF / ON Change-Id: Idbb6a24ccfa360582f48e4f9369def7fc729fb9f Bug: 112171349 --- .../server/ethernet/EthernetNetworkFactory.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index b8ed845c2c..6ed1310d2e 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -376,7 +376,14 @@ public class EthernetNetworkFactory extends NetworkFactory { } void setIpConfig(IpConfiguration ipConfig) { + if (this.mIpConfig.equals(ipConfig)) { + if (DBG) Log.d(TAG, "ipConfig have not changed,so ignore setIpConfig"); + return; + } this.mIpConfig = ipConfig; + if (mNetworkInfo.getDetailedState() != DetailedState.DISCONNECTED) { + restart(); + } } boolean statisified(NetworkCapabilities requestedCapabilities) { @@ -587,6 +594,12 @@ public class EthernetNetworkFactory extends NetworkFactory { } } + void restart(){ + if (DBG) Log.d(TAG, "reconnecting Etherent"); + stop(); + start(); + } + @Override public String toString() { return getClass().getSimpleName() + "{ " From bbf19a273d552799b23bf1a7371a426adc5a6bfb Mon Sep 17 00:00:00 2001 From: chen xu Date: Wed, 22 May 2019 14:10:29 -0700 Subject: [PATCH 289/881] NetworkStatAccess Should checkCarrierPrivileges cross all subscriptions Bug: 133236378 Test: Manual Change-Id: I49fbde1fe73b33aadcf8fd23ad224f363b137bf3 --- .../core/java/com/android/server/net/NetworkStatsAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index cebc472178..7c1c1c7ce4 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -109,7 +109,7 @@ public final class NetworkStatsAccess { final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); boolean hasCarrierPrivileges = tm != null && - tm.checkCarrierPrivilegesForPackage(callingPackage) == + tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); From 08c6a361a5e9a289fe89d98f5fc4105e6c9c405e Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Sun, 17 Feb 2019 23:43:25 -0800 Subject: [PATCH 290/881] Take all VPN underlying networks into account when migrating traffic for VPN uid. (cherry picked from commit 2e2662fbcfe1611def7ee2055cf17cb2f39d9511) Bug: 113122541 Bug: 120145746 Test: atest FrameworksNetTests Test: Manually verified on device that stats from VPN UID are moved appropriately based on its declared underlying network set. Test: vogar --mode app_process --benchmark NetworkStatsBenchmark.java Change-Id: I7f368c5970b2dcb969fe0daf5ef44edb1f51d09d --- core/java/android/net/NetworkStats.java | 330 +++++++++++------- .../server/net/NetworkStatsRecorder.java | 6 +- 2 files changed, 214 insertions(+), 122 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index e892b650bf..f09f2ee223 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,6 +18,7 @@ package android.net; import static android.os.Process.CLAT_UID; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -1175,133 +1176,217 @@ public class NetworkStats implements Parcelable { /** * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface. * - * This method should only be called on delta NetworkStats. Do not call this method on a - * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may - * change over time. + *

This method should only be called on delta NetworkStats. Do not call this method on a + * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change + * over time. * - * This method performs adjustments for one active VPN package and one VPN iface at a time. - * - * It is possible for the VPN software to use multiple underlying networks. This method - * only migrates traffic for the primary underlying network. + *

This method performs adjustments for one active VPN package and one VPN iface at a time. * * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel - * @param underlyingIface the primary underlying network iface used by the VPN application - * @return true if it successfully adjusts the accounting for VPN, false otherwise + * @param underlyingIfaces underlying network ifaces used by the VPN application */ - public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) { - Entry tunIfaceTotal = new Entry(); - Entry underlyingIfaceTotal = new Entry(); + public void migrateTun(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces) { + // Combined usage by all apps using VPN. + final Entry tunIfaceTotal = new Entry(); + // Usage by VPN, grouped by its {@code underlyingIfaces}. + final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; + // Usage by VPN, summed across all its {@code underlyingIfaces}. + final Entry underlyingIfacesTotal = new Entry(); - tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal); + for (int i = 0; i < perInterfaceTotal.length; i++) { + perInterfaceTotal[i] = new Entry(); + } - // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app. - // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression. + tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal, + underlyingIfacesTotal); + + // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app. + // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression. // Negative stats should be avoided. - Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal); - if (pool.isEmpty()) { - return true; - } - Entry moved = - addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); - deductTrafficFromVpnApp(tunUid, underlyingIface, moved); - - if (!moved.isEmpty()) { - Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved=" - + moved); - return false; - } - return true; + final Entry[] moved = + addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, + perInterfaceTotal, underlyingIfacesTotal); + deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved); } /** * Initializes the data used by the migrateTun() method. * - * This is the first pass iteration which does the following work: - * (1) Adds up all the traffic through the tunUid's underlyingIface - * (both foreground and background). - * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *

This is the first pass iteration which does the following work: + * + *

    + *
  • Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and + * background). + *
  • Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *
+ * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN + * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code + * underlyingIfaces} + * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its + * {@code underlyingIfaces} */ - private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry recycle = new Entry(); + private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + final Entry recycle = new Entry(); for (int i = 0; i < size; i++) { getValues(i, recycle); if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); - } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + } + if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { throw new IllegalStateException( "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } - - if (recycle.uid == tunUid && recycle.tag == TAG_NONE - && Objects.equals(underlyingIface, recycle.iface)) { - underlyingIfaceTotal.add(recycle); + if (recycle.tag != TAG_NONE) { + // TODO(b/123666283): Take all tags for tunUid into account. + continue; } - if (recycle.uid != tunUid && recycle.tag == TAG_NONE - && Objects.equals(tunIface, recycle.iface)) { + if (recycle.uid == tunUid) { + // Add up traffic through tunUid's underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + if (Objects.equals(underlyingIfaces[j], recycle.iface)) { + perInterfaceTotal[j].add(recycle); + underlyingIfacesTotal.add(recycle); + break; + } + } + } else if (tunIface.equals(recycle.iface)) { // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } } - private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry pool = new Entry(); - pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes); - pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets); - pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes); - pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets); - pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations); - return pool; - } + /** + * Distributes traffic across apps that are using given {@code tunIface}, and returns the total + * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}. + * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal combined data usage across all apps using {@code tunIface} + * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces} + * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code + * underlyingIfaces} + */ + private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + // Traffic that should be moved off of each underlying interface for tunUid (see + // deductTrafficFromVpnApp below). + final Entry[] moved = new Entry[underlyingIfaces.length]; + for (int i = 0; i < underlyingIfaces.length; i++) { + moved[i] = new Entry(); + } - private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry pool) { - Entry moved = new Entry(); - Entry tmpEntry = new Entry(); - tmpEntry.iface = underlyingIface; + final Entry tmpEntry = new Entry(); for (int i = 0; i < size; i++) { - // the vpn app is excluded from the redistribution but all moved traffic will be - // deducted from the vpn app (see deductTrafficFromVpnApp below). - if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { - if (tunIfaceTotal.rxBytes > 0) { - tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; - } else { - tmpEntry.rxBytes = 0; - } - if (tunIfaceTotal.rxPackets > 0) { - tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; - } else { - tmpEntry.rxPackets = 0; - } - if (tunIfaceTotal.txBytes > 0) { - tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes; - } else { - tmpEntry.txBytes = 0; - } - if (tunIfaceTotal.txPackets > 0) { - tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets; - } else { - tmpEntry.txPackets = 0; - } - if (tunIfaceTotal.operations > 0) { - tmpEntry.operations = - pool.operations * operations[i] / tunIfaceTotal.operations; - } else { - tmpEntry.operations = 0; - } - tmpEntry.uid = uid[i]; - tmpEntry.tag = tag[i]; + if (!Objects.equals(iface[i], tunIface)) { + // Consider only entries that go onto the VPN interface. + continue; + } + if (uid[i] == tunUid) { + // Exclude VPN app from the redistribution, as it can choose to create packet + // streams by writing to itself. + continue; + } + tmpEntry.uid = uid[i]; + tmpEntry.tag = tag[i]; + tmpEntry.metered = metered[i]; + tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; + + // In a first pass, compute each UID's total share of data across all underlyingIfaces. + // This is computed on the basis of the share of each UID's usage over tunIface. + // TODO: Consider refactoring first pass into a separate helper method. + long totalRxBytes = 0; + if (tunIfaceTotal.rxBytes > 0) { + // Note - The multiplication below should not overflow since NetworkStatsService + // processes this every time device has transmitted/received amount equivalent to + // global threshold alert (~ 2MB) across all interfaces. + final long rxBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + // app must not be blamed for more than it consumed on tunIface + totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); + } + long totalRxPackets = 0; + if (tunIfaceTotal.rxPackets > 0) { + final long rxPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); + } + long totalTxBytes = 0; + if (tunIfaceTotal.txBytes > 0) { + final long txBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); + } + long totalTxPackets = 0; + if (tunIfaceTotal.txPackets > 0) { + final long txPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); + } + long totalOperations = 0; + if (tunIfaceTotal.operations > 0) { + final long operationsAcrossUnderlyingIfaces = + underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; + totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); + } + // In a second pass, distribute these values across interfaces in the proportion that + // each interface represents of the total traffic of the underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + tmpEntry.iface = underlyingIfaces[j]; + tmpEntry.rxBytes = 0; + // Reset 'set' to correct value since it gets updated when adding debug info below. tmpEntry.set = set[i]; - tmpEntry.metered = metered[i]; - tmpEntry.roaming = roaming[i]; - tmpEntry.defaultNetwork = defaultNetwork[i]; + if (underlyingIfacesTotal.rxBytes > 0) { + tmpEntry.rxBytes = + totalRxBytes + * perInterfaceTotal[j].rxBytes + / underlyingIfacesTotal.rxBytes; + } + tmpEntry.rxPackets = 0; + if (underlyingIfacesTotal.rxPackets > 0) { + tmpEntry.rxPackets = + totalRxPackets + * perInterfaceTotal[j].rxPackets + / underlyingIfacesTotal.rxPackets; + } + tmpEntry.txBytes = 0; + if (underlyingIfacesTotal.txBytes > 0) { + tmpEntry.txBytes = + totalTxBytes + * perInterfaceTotal[j].txBytes + / underlyingIfacesTotal.txBytes; + } + tmpEntry.txPackets = 0; + if (underlyingIfacesTotal.txPackets > 0) { + tmpEntry.txPackets = + totalTxPackets + * perInterfaceTotal[j].txPackets + / underlyingIfacesTotal.txPackets; + } + tmpEntry.operations = 0; + if (underlyingIfacesTotal.operations > 0) { + tmpEntry.operations = + totalOperations + * perInterfaceTotal[j].operations + / underlyingIfacesTotal.operations; + } + combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - moved.add(tmpEntry); + moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; combineValues(tmpEntry); @@ -1311,38 +1396,45 @@ public class NetworkStats implements Parcelable { return moved; } - private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { - // Add debug info - moved.uid = tunUid; - moved.set = SET_DBG_VPN_OUT; - moved.tag = TAG_NONE; - moved.iface = underlyingIface; - moved.metered = METERED_ALL; - moved.roaming = ROAMING_ALL; - moved.defaultNetwork = DEFAULT_NETWORK_ALL; - combineValues(moved); + private void deductTrafficFromVpnApp( + int tunUid, + @NonNull String[] underlyingIfaces, + @NonNull Entry[] moved) { + for (int i = 0; i < underlyingIfaces.length; i++) { + // Add debug info + moved[i].uid = tunUid; + moved[i].set = SET_DBG_VPN_OUT; + moved[i].tag = TAG_NONE; + moved[i].iface = underlyingIfaces[i]; + moved[i].metered = METERED_ALL; + moved[i].roaming = ROAMING_ALL; + moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; + combineValues(moved[i]); - // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than - // the TAG_NONE traffic. - // - // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, - // which should be the case as it comes directly from the /proc file. We only blend in the - // roaming data after applying these adjustments, by checking the NetworkIdentity of the - // underlying iface. - int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnBackground != -1) { - tunSubtract(idxVpnBackground, this, moved); - } + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than + // the TAG_NONE traffic. + // + // Relies on the fact that the underlying traffic only has state ROAMING_NO and + // METERED_NO, which should be the case as it comes directly from the /proc file. + // We only blend in the roaming data after applying these adjustments, by checking the + // NetworkIdentity of the underlying iface. + final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnBackground != -1) { + // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed + // from foreground usage. + tunSubtract(idxVpnBackground, this, moved[i]); + } - int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnForeground != -1) { - tunSubtract(idxVpnForeground, this, moved); + final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnForeground != -1) { + tunSubtract(idxVpnForeground, this, moved[i]); + } } } - private static void tunSubtract(int i, NetworkStats left, Entry right) { + private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) { long rxBytes = Math.min(left.rxBytes[i], right.rxBytes); left.rxBytes[i] -= rxBytes; right.rxBytes -= rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a2e7e0cae9..bdff50053f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import libcore.io.IoUtils; - import com.google.android.collect.Sets; +import libcore.io.IoUtils; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -234,7 +234,7 @@ public class NetworkStatsRecorder { if (vpnArray != null) { for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); } } From e1c0117fcfa06e4acaa354a3d60a9b48ee67484b Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Fri, 18 Jan 2019 19:22:48 -0800 Subject: [PATCH 291/881] NetworkStatsService: Fix getDetailedUidStats to take VPNs into account. (cherry picked from commit 48f57628283d7cdacd831af3b5b6de8fb44c20ac) This API is similar to one provided by NetworkStatsFactory with the difference that NSS also migrates traffic from VPN UID to other apps. Since traffic can only be migrated over NetworkStats delta, NSS therefore maintains NetworkStats snapshot across all UIDs/ifaces/tags. This snapshot gets updated whenever NSS records a new snapshot (based on various hooks such as VPN updating its underlying networks, network getting lost, etc.), or getDetailedUidStats API is invoked by one of its callers. Bug: 113122541 Bug: 120145746 Test: atest FrameworksNetTests Test: manually verified that battery stats are migrating traffic off of TUN (after patching above CL where we point BatteryStats to use this API). Change-Id: I4b8d7c5b6905a4a12c1806dfd35c2c4c63610404 --- core/java/android/net/NetworkStats.java | 29 +++++--- .../server/net/NetworkStatsFactory.java | 4 ++ .../server/net/NetworkStatsService.java | 70 ++++++++++++++++++- 3 files changed, 93 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index f09f2ee223..e8625f34f0 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -34,6 +34,7 @@ import libcore.util.EmptyArray; import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; +import java.util.function.Predicate; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -994,23 +995,33 @@ public class NetworkStats implements Parcelable { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { return; } + filter(e -> (limitUid == UID_ALL || limitUid == e.uid) + && (limitTag == TAG_ALL || limitTag == e.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, e.iface))); + } + /** + * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. + * + *

This mutates the original structure in place. + */ + public void filterDebugEntries() { + filter(e -> e.set < SET_DEBUG_START); + } + + private void filter(Predicate predicate) { Entry entry = new Entry(); int nextOutputEntry = 0; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - final boolean matches = - (limitUid == UID_ALL || limitUid == entry.uid) - && (limitTag == TAG_ALL || limitTag == entry.tag) - && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, entry.iface)); - - if (matches) { - setValues(nextOutputEntry, entry); + if (predicate.test(entry)) { + if (nextOutputEntry != i) { + setValues(nextOutputEntry, entry); + } nextOutputEntry++; } } - size = nextOutputEntry; } diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 69efd02dea..473cc97b7e 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -263,6 +263,10 @@ public class NetworkStatsFactory { return stats; } + /** + * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for + * VPN traffic + */ public NetworkStats readNetworkStatsDetail() throws IOException { return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index f34ace55a7..a13368ff9d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -293,6 +293,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); + /** + * Snapshot containing most recent network stats for all UIDs across all interfaces and tags + * since boot. + * + *

Maintains migrated VPN stats which are result of performing TUN migration on {@link + * #mLastUidDetailSnapshot}. + */ + @GuardedBy("mStatsLock") + private NetworkStats mTunAdjustedStats; + /** + * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot + * and latest snapshot. + */ + @GuardedBy("mStatsLock") + private NetworkStats mLastUidDetailSnapshot; + /** Must be set in factory by calling #setHandler. */ private Handler mHandler; private Handler.Callback mHandlerCallback; @@ -812,15 +828,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { + // Get the latest snapshot from NetworkStatsFactory. + // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting + // this to limited set of ifaces. + NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL); + + // Migrate traffic from VPN UID over delta and update mTunAdjustedStats. + NetworkStats result; + synchronized (mStatsLock) { + migrateTunTraffic(uidDetailStats, mVpnInfos); + result = mTunAdjustedStats.clone(); + } + + // Apply filter based on ifacesToQuery. final String[] ifacesToQuery = NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); - return getNetworkStatsUidDetail(ifacesToQuery); + result.filter(UID_ALL, ifacesToQuery, TAG_ALL); + return result; } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); return new NetworkStats(0L, 0); } } + @VisibleForTesting + NetworkStats getTunAdjustedStats() { + synchronized (mStatsLock) { + if (mTunAdjustedStats == null) { + return null; + } + return mTunAdjustedStats.clone(); + } + } + @Override public String[] getMobileIfaces() { return mMobileIfaces; @@ -1295,6 +1335,34 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime); + + migrateTunTraffic(uidSnapshot, vpnArray); + } + + /** + * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs. + */ + @GuardedBy("mStatsLock") + private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) { + if (mTunAdjustedStats == null) { + // Either device booted or system server restarted, hence traffic cannot be migrated + // correctly without knowing the past state of VPN's underlying networks. + mTunAdjustedStats = uidDetailStats; + mLastUidDetailSnapshot = uidDetailStats; + return; + } + // Migrate delta traffic from VPN to other apps. + NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot); + for (VpnInfo info : vpnInfoArray) { + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + } + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); + // Update #mTunAdjustedStats with migrated delta. + mTunAdjustedStats.combineAllValues(delta); + mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); + // Update last snapshot. + mLastUidDetailSnapshot = uidDetailStats; } /** From 3c3e4846d1fe3fec51756281acbd4715d2837de4 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Fri, 24 May 2019 16:29:22 -0700 Subject: [PATCH 292/881] Addressing comments for http://ag/7700679. Note, that its in a separate CL so we could cherry-pick this CL to aosp. http://ag/7700679 is already in aosp. Bug: 113122541 Bug: 120145746 Test: atest FrameworksNetTests Change-Id: I7cfda226b4ed11b67002b83b38fba0f5caf96718 --- core/java/android/net/NetworkStats.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index e8625f34f0..bb344e2896 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1300,7 +1300,8 @@ public class NetworkStats implements Parcelable { } final Entry tmpEntry = new Entry(); - for (int i = 0; i < size; i++) { + final int origSize = size; + for (int i = 0; i < origSize; i++) { if (!Objects.equals(iface[i], tunIface)) { // Consider only entries that go onto the VPN interface. continue; @@ -1316,8 +1317,9 @@ public class NetworkStats implements Parcelable { tmpEntry.roaming = roaming[i]; tmpEntry.defaultNetwork = defaultNetwork[i]; - // In a first pass, compute each UID's total share of data across all underlyingIfaces. - // This is computed on the basis of the share of each UID's usage over tunIface. + // In a first pass, compute this entry's total share of data across all + // underlyingIfaces. This is computed on the basis of the share of this entry's usage + // over tunIface. // TODO: Consider refactoring first pass into a separate helper method. long totalRxBytes = 0; if (tunIfaceTotal.rxBytes > 0) { @@ -1394,9 +1396,11 @@ public class NetworkStats implements Parcelable { * perInterfaceTotal[j].operations / underlyingIfacesTotal.operations; } - + // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying + // interface. Add that data usage to this object. combineValues(tmpEntry); if (tag[i] == TAG_NONE) { + // Add the migrated data to moved so it is deducted from the VPN app later. moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; @@ -1412,8 +1416,8 @@ public class NetworkStats implements Parcelable { @NonNull String[] underlyingIfaces, @NonNull Entry[] moved) { for (int i = 0; i < underlyingIfaces.length; i++) { - // Add debug info moved[i].uid = tunUid; + // Add debug info moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; moved[i].iface = underlyingIfaces[i]; From 146b95b1231c74fc7cf533dd5365a605a9ce8b07 Mon Sep 17 00:00:00 2001 From: chen xu Date: Wed, 22 May 2019 14:10:29 -0700 Subject: [PATCH 293/881] NetworkStatAccess Should checkCarrierPrivileges cross all subscriptions Bug: 133236378 Test: Manual Change-Id: I49fbde1fe73b33aadcf8fd23ad224f363b137bf3 Merged-in: I49fbde1fe73b33aadcf8fd23ad224f363b137bf3 --- .../core/java/com/android/server/net/NetworkStatsAccess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index cebc472178..7c1c1c7ce4 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -109,7 +109,7 @@ public final class NetworkStatsAccess { final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); boolean hasCarrierPrivileges = tm != null && - tm.checkCarrierPrivilegesForPackage(callingPackage) == + tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); From 2b1e8581a34ce281223670d4f51e37f97add0f06 Mon Sep 17 00:00:00 2001 From: Wally Yau Date: Wed, 22 May 2019 09:22:06 -0700 Subject: [PATCH 294/881] Fixed fatal exception in EthernetServiceThread When this.mIpConfig is not initialized, it will cause a java.lang.NullPointerException and put the device in a boot loop with the following error: FATAL EXCEPTION IN SYSTEM PROCESS: EthernetServiceThread Test: passed pre-submit boot test. Change-Id: I47df68071b4c07a4136c0abcbe69ee7ada7090e0 --- .../server/ethernet/EthernetNetworkFactory.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 6ed1310d2e..e3f114ed21 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -21,6 +21,7 @@ import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.net.ConnectivityManager; import android.net.IpConfiguration; @@ -53,6 +54,7 @@ import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; import java.lang.Math; import java.util.concurrent.ConcurrentHashMap; +import java.util.Objects; /** * {@link NetworkFactory} that represents Ethernet networks. @@ -252,10 +254,10 @@ public class EthernetNetworkFactory extends NetworkFactory { private boolean mLinkUp; private LinkProperties mLinkProperties = new LinkProperties(); - private volatile IIpClient mIpClient; - private IpClientCallbacksImpl mIpClientCallback; - private NetworkAgent mNetworkAgent; - private IpConfiguration mIpConfig; + private volatile @Nullable IIpClient mIpClient; + private @Nullable IpClientCallbacksImpl mIpClientCallback; + private @Nullable NetworkAgent mNetworkAgent; + private @Nullable IpConfiguration mIpConfig; /** * An object to contain all transport type information, including base network score and @@ -376,7 +378,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } void setIpConfig(IpConfiguration ipConfig) { - if (this.mIpConfig.equals(ipConfig)) { + if (Objects.equals(this.mIpConfig, ipConfig)) { if (DBG) Log.d(TAG, "ipConfig have not changed,so ignore setIpConfig"); return; } From 290d5733ae066b79104da41a405596d042bcfef9 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Fri, 24 May 2019 16:29:22 -0700 Subject: [PATCH 295/881] Addressing comments for http://ag/7700679. (cherry picked from commit 3c3e4846d1fe3fec51756281acbd4715d2837de4) Note, that its in a separate CL so we could cherry-pick this CL to aosp. http://ag/7700679 is already in aosp (http://aosp/865073). Bug: 113122541 Bug: 120145746 Test: atest FrameworksNetTests Change-Id: Ic1767bc8bf1460e4223f86465fc72344428e6055 Merged-In: I7cfda226b4ed11b67002b83b38fba0f5caf96718 --- core/java/android/net/NetworkStats.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 27e0414961..b27b1c0578 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1300,7 +1300,8 @@ public class NetworkStats implements Parcelable { } final Entry tmpEntry = new Entry(); - for (int i = 0; i < size; i++) { + final int origSize = size; + for (int i = 0; i < origSize; i++) { if (!Objects.equals(iface[i], tunIface)) { // Consider only entries that go onto the VPN interface. continue; @@ -1316,8 +1317,9 @@ public class NetworkStats implements Parcelable { tmpEntry.roaming = roaming[i]; tmpEntry.defaultNetwork = defaultNetwork[i]; - // In a first pass, compute each UID's total share of data across all underlyingIfaces. - // This is computed on the basis of the share of each UID's usage over tunIface. + // In a first pass, compute this entry's total share of data across all + // underlyingIfaces. This is computed on the basis of the share of this entry's usage + // over tunIface. // TODO: Consider refactoring first pass into a separate helper method. long totalRxBytes = 0; if (tunIfaceTotal.rxBytes > 0) { @@ -1394,9 +1396,11 @@ public class NetworkStats implements Parcelable { * perInterfaceTotal[j].operations / underlyingIfacesTotal.operations; } - + // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying + // interface. Add that data usage to this object. combineValues(tmpEntry); if (tag[i] == TAG_NONE) { + // Add the migrated data to moved so it is deducted from the VPN app later. moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; @@ -1412,8 +1416,8 @@ public class NetworkStats implements Parcelable { @NonNull String[] underlyingIfaces, @NonNull Entry[] moved) { for (int i = 0; i < underlyingIfaces.length; i++) { - // Add debug info moved[i].uid = tunUid; + // Add debug info moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; moved[i].iface = underlyingIfaces[i]; From 7123ebdd2f674a88129f1f6eded5e30bbce35d67 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 6 Jun 2019 17:06:39 -0700 Subject: [PATCH 296/881] Revert "Addressing comments for http://ag/7700679." This reverts commit 3c3e4846d1fe3fec51756281acbd4715d2837de4. Reason for revert: This change has been implicated in 4-way deadlocks as seen in b/134244752. Bug: 134244752 Change-Id: I5fbb3443a39a21fc9d96442726cd10d20e8d61cd --- core/java/android/net/NetworkStats.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index bb344e2896..e8625f34f0 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1300,8 +1300,7 @@ public class NetworkStats implements Parcelable { } final Entry tmpEntry = new Entry(); - final int origSize = size; - for (int i = 0; i < origSize; i++) { + for (int i = 0; i < size; i++) { if (!Objects.equals(iface[i], tunIface)) { // Consider only entries that go onto the VPN interface. continue; @@ -1317,9 +1316,8 @@ public class NetworkStats implements Parcelable { tmpEntry.roaming = roaming[i]; tmpEntry.defaultNetwork = defaultNetwork[i]; - // In a first pass, compute this entry's total share of data across all - // underlyingIfaces. This is computed on the basis of the share of this entry's usage - // over tunIface. + // In a first pass, compute each UID's total share of data across all underlyingIfaces. + // This is computed on the basis of the share of each UID's usage over tunIface. // TODO: Consider refactoring first pass into a separate helper method. long totalRxBytes = 0; if (tunIfaceTotal.rxBytes > 0) { @@ -1396,11 +1394,9 @@ public class NetworkStats implements Parcelable { * perInterfaceTotal[j].operations / underlyingIfacesTotal.operations; } - // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying - // interface. Add that data usage to this object. + combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - // Add the migrated data to moved so it is deducted from the VPN app later. moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; @@ -1416,8 +1412,8 @@ public class NetworkStats implements Parcelable { @NonNull String[] underlyingIfaces, @NonNull Entry[] moved) { for (int i = 0; i < underlyingIfaces.length; i++) { - moved[i].uid = tunUid; // Add debug info + moved[i].uid = tunUid; moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; moved[i].iface = underlyingIfaces[i]; From ed2eba3a1a94e97cbdc890034e2fd2799b192fe1 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 6 Jun 2019 17:06:48 -0700 Subject: [PATCH 297/881] Revert "NetworkStatsService: Fix getDetailedUidStats to take VPNs into account." This reverts commit e1c0117fcfa06e4acaa354a3d60a9b48ee67484b. Reason for revert: This change has been implicated in 4-way deadlocks as seen in b/134244752. Bug: 134244752 Change-Id: I0c00e8f0e30cee987b71b561079a97bf09d4dae4 --- core/java/android/net/NetworkStats.java | 29 +++----- .../server/net/NetworkStatsFactory.java | 4 -- .../server/net/NetworkStatsService.java | 70 +------------------ 3 files changed, 10 insertions(+), 93 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index e8625f34f0..f09f2ee223 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -34,7 +34,6 @@ import libcore.util.EmptyArray; import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; -import java.util.function.Predicate; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -995,33 +994,23 @@ public class NetworkStats implements Parcelable { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { return; } - filter(e -> (limitUid == UID_ALL || limitUid == e.uid) - && (limitTag == TAG_ALL || limitTag == e.tag) - && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, e.iface))); - } - /** - * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. - * - *

This mutates the original structure in place. - */ - public void filterDebugEntries() { - filter(e -> e.set < SET_DEBUG_START); - } - - private void filter(Predicate predicate) { Entry entry = new Entry(); int nextOutputEntry = 0; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - if (predicate.test(entry)) { - if (nextOutputEntry != i) { - setValues(nextOutputEntry, entry); - } + final boolean matches = + (limitUid == UID_ALL || limitUid == entry.uid) + && (limitTag == TAG_ALL || limitTag == entry.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, entry.iface)); + + if (matches) { + setValues(nextOutputEntry, entry); nextOutputEntry++; } } + size = nextOutputEntry; } diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 473cc97b7e..69efd02dea 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -263,10 +263,6 @@ public class NetworkStatsFactory { return stats; } - /** - * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for - * VPN traffic - */ public NetworkStats readNetworkStatsDetail() throws IOException { return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index a13368ff9d..f34ace55a7 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -293,22 +293,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); - /** - * Snapshot containing most recent network stats for all UIDs across all interfaces and tags - * since boot. - * - *

Maintains migrated VPN stats which are result of performing TUN migration on {@link - * #mLastUidDetailSnapshot}. - */ - @GuardedBy("mStatsLock") - private NetworkStats mTunAdjustedStats; - /** - * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot - * and latest snapshot. - */ - @GuardedBy("mStatsLock") - private NetworkStats mLastUidDetailSnapshot; - /** Must be set in factory by calling #setHandler. */ private Handler mHandler; private Handler.Callback mHandlerCallback; @@ -828,39 +812,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { - // Get the latest snapshot from NetworkStatsFactory. - // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting - // this to limited set of ifaces. - NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL); - - // Migrate traffic from VPN UID over delta and update mTunAdjustedStats. - NetworkStats result; - synchronized (mStatsLock) { - migrateTunTraffic(uidDetailStats, mVpnInfos); - result = mTunAdjustedStats.clone(); - } - - // Apply filter based on ifacesToQuery. final String[] ifacesToQuery = NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); - result.filter(UID_ALL, ifacesToQuery, TAG_ALL); - return result; + return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); return new NetworkStats(0L, 0); } } - @VisibleForTesting - NetworkStats getTunAdjustedStats() { - synchronized (mStatsLock) { - if (mTunAdjustedStats == null) { - return null; - } - return mTunAdjustedStats.clone(); - } - } - @Override public String[] getMobileIfaces() { return mMobileIfaces; @@ -1335,34 +1295,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime); - - migrateTunTraffic(uidSnapshot, vpnArray); - } - - /** - * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs. - */ - @GuardedBy("mStatsLock") - private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) { - if (mTunAdjustedStats == null) { - // Either device booted or system server restarted, hence traffic cannot be migrated - // correctly without knowing the past state of VPN's underlying networks. - mTunAdjustedStats = uidDetailStats; - mLastUidDetailSnapshot = uidDetailStats; - return; - } - // Migrate delta traffic from VPN to other apps. - NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot); - for (VpnInfo info : vpnInfoArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); - } - // Filter out debug entries as that may lead to over counting. - delta.filterDebugEntries(); - // Update #mTunAdjustedStats with migrated delta. - mTunAdjustedStats.combineAllValues(delta); - mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); - // Update last snapshot. - mLastUidDetailSnapshot = uidDetailStats; } /** From 4892220eb7f0f7b0bc6ad14dfaf05accd9cf5028 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 6 Jun 2019 17:08:02 -0700 Subject: [PATCH 298/881] Revert "Take all VPN underlying networks into account when migrating traffic for" This reverts commit 08c6a361a5e9a289fe89d98f5fc4105e6c9c405e. Reason for revert: This change has been implicated in 4-way deadlocks as seen in b/134244752. Bug: 134244752 Change-Id: Ibdaad3a4cbf0d8ef1ed53cfab1e454b9b878bae9 --- core/java/android/net/NetworkStats.java | 320 +++++++----------- .../server/net/NetworkStatsRecorder.java | 6 +- 2 files changed, 117 insertions(+), 209 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index f09f2ee223..e892b650bf 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,7 +18,6 @@ package android.net; import static android.os.Process.CLAT_UID; -import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -1176,217 +1175,133 @@ public class NetworkStats implements Parcelable { /** * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface. * - *

This method should only be called on delta NetworkStats. Do not call this method on a - * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change - * over time. + * This method should only be called on delta NetworkStats. Do not call this method on a + * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may + * change over time. * - *

This method performs adjustments for one active VPN package and one VPN iface at a time. + * This method performs adjustments for one active VPN package and one VPN iface at a time. + * + * It is possible for the VPN software to use multiple underlying networks. This method + * only migrates traffic for the primary underlying network. * * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel - * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param underlyingIface the primary underlying network iface used by the VPN application + * @return true if it successfully adjusts the accounting for VPN, false otherwise */ - public void migrateTun(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces) { - // Combined usage by all apps using VPN. - final Entry tunIfaceTotal = new Entry(); - // Usage by VPN, grouped by its {@code underlyingIfaces}. - final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; - // Usage by VPN, summed across all its {@code underlyingIfaces}. - final Entry underlyingIfacesTotal = new Entry(); + public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) { + Entry tunIfaceTotal = new Entry(); + Entry underlyingIfaceTotal = new Entry(); - for (int i = 0; i < perInterfaceTotal.length; i++) { - perInterfaceTotal[i] = new Entry(); - } + tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal); - tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal, - underlyingIfacesTotal); - - // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app. - // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression. + // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app. + // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression. // Negative stats should be avoided. - final Entry[] moved = - addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, - perInterfaceTotal, underlyingIfacesTotal); - deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved); + Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal); + if (pool.isEmpty()) { + return true; + } + Entry moved = + addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); + deductTrafficFromVpnApp(tunUid, underlyingIface, moved); + + if (!moved.isEmpty()) { + Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved=" + + moved); + return false; + } + return true; } /** * Initializes the data used by the migrateTun() method. * - *

This is the first pass iteration which does the following work: - * - *

    - *
  • Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and - * background). - *
  • Adds up all the traffic through tun0 excluding traffic from the vpn app itself. - *
- * - * @param tunUid uid of the VPN application - * @param tunIface iface of the vpn tunnel - * @param underlyingIfaces underlying network ifaces used by the VPN application - * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN - * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code - * underlyingIfaces} - * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its - * {@code underlyingIfaces} + * This is the first pass iteration which does the following work: + * (1) Adds up all the traffic through the tunUid's underlyingIface + * (both foreground and background). + * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. */ - private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, - @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { - final Entry recycle = new Entry(); + private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, + Entry tunIfaceTotal, Entry underlyingIfaceTotal) { + Entry recycle = new Entry(); for (int i = 0; i < size; i++) { getValues(i, recycle); if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); - } - if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { throw new IllegalStateException( "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } - if (recycle.tag != TAG_NONE) { - // TODO(b/123666283): Take all tags for tunUid into account. - continue; + + if (recycle.uid == tunUid && recycle.tag == TAG_NONE + && Objects.equals(underlyingIface, recycle.iface)) { + underlyingIfaceTotal.add(recycle); } - if (recycle.uid == tunUid) { - // Add up traffic through tunUid's underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - if (Objects.equals(underlyingIfaces[j], recycle.iface)) { - perInterfaceTotal[j].add(recycle); - underlyingIfacesTotal.add(recycle); - break; - } - } - } else if (tunIface.equals(recycle.iface)) { + if (recycle.uid != tunUid && recycle.tag == TAG_NONE + && Objects.equals(tunIface, recycle.iface)) { // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } } - /** - * Distributes traffic across apps that are using given {@code tunIface}, and returns the total - * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}. - * - * @param tunUid uid of the VPN application - * @param tunIface iface of the vpn tunnel - * @param underlyingIfaces underlying network ifaces used by the VPN application - * @param tunIfaceTotal combined data usage across all apps using {@code tunIface} - * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces} - * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code - * underlyingIfaces} - */ - private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, - @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { - // Traffic that should be moved off of each underlying interface for tunUid (see - // deductTrafficFromVpnApp below). - final Entry[] moved = new Entry[underlyingIfaces.length]; - for (int i = 0; i < underlyingIfaces.length; i++) { - moved[i] = new Entry(); - } + private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) { + Entry pool = new Entry(); + pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes); + pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets); + pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes); + pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets); + pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations); + return pool; + } - final Entry tmpEntry = new Entry(); + private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, + Entry tunIfaceTotal, Entry pool) { + Entry moved = new Entry(); + Entry tmpEntry = new Entry(); + tmpEntry.iface = underlyingIface; for (int i = 0; i < size; i++) { - if (!Objects.equals(iface[i], tunIface)) { - // Consider only entries that go onto the VPN interface. - continue; - } - if (uid[i] == tunUid) { - // Exclude VPN app from the redistribution, as it can choose to create packet - // streams by writing to itself. - continue; - } - tmpEntry.uid = uid[i]; - tmpEntry.tag = tag[i]; - tmpEntry.metered = metered[i]; - tmpEntry.roaming = roaming[i]; - tmpEntry.defaultNetwork = defaultNetwork[i]; - - // In a first pass, compute each UID's total share of data across all underlyingIfaces. - // This is computed on the basis of the share of each UID's usage over tunIface. - // TODO: Consider refactoring first pass into a separate helper method. - long totalRxBytes = 0; - if (tunIfaceTotal.rxBytes > 0) { - // Note - The multiplication below should not overflow since NetworkStatsService - // processes this every time device has transmitted/received amount equivalent to - // global threshold alert (~ 2MB) across all interfaces. - final long rxBytesAcrossUnderlyingIfaces = - underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; - // app must not be blamed for more than it consumed on tunIface - totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); - } - long totalRxPackets = 0; - if (tunIfaceTotal.rxPackets > 0) { - final long rxPacketsAcrossUnderlyingIfaces = - underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; - totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); - } - long totalTxBytes = 0; - if (tunIfaceTotal.txBytes > 0) { - final long txBytesAcrossUnderlyingIfaces = - underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; - totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); - } - long totalTxPackets = 0; - if (tunIfaceTotal.txPackets > 0) { - final long txPacketsAcrossUnderlyingIfaces = - underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; - totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); - } - long totalOperations = 0; - if (tunIfaceTotal.operations > 0) { - final long operationsAcrossUnderlyingIfaces = - underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; - totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); - } - // In a second pass, distribute these values across interfaces in the proportion that - // each interface represents of the total traffic of the underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - tmpEntry.iface = underlyingIfaces[j]; - tmpEntry.rxBytes = 0; - // Reset 'set' to correct value since it gets updated when adding debug info below. - tmpEntry.set = set[i]; - if (underlyingIfacesTotal.rxBytes > 0) { - tmpEntry.rxBytes = - totalRxBytes - * perInterfaceTotal[j].rxBytes - / underlyingIfacesTotal.rxBytes; + // the vpn app is excluded from the redistribution but all moved traffic will be + // deducted from the vpn app (see deductTrafficFromVpnApp below). + if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { + if (tunIfaceTotal.rxBytes > 0) { + tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + } else { + tmpEntry.rxBytes = 0; } - tmpEntry.rxPackets = 0; - if (underlyingIfacesTotal.rxPackets > 0) { - tmpEntry.rxPackets = - totalRxPackets - * perInterfaceTotal[j].rxPackets - / underlyingIfacesTotal.rxPackets; + if (tunIfaceTotal.rxPackets > 0) { + tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + } else { + tmpEntry.rxPackets = 0; } - tmpEntry.txBytes = 0; - if (underlyingIfacesTotal.txBytes > 0) { - tmpEntry.txBytes = - totalTxBytes - * perInterfaceTotal[j].txBytes - / underlyingIfacesTotal.txBytes; + if (tunIfaceTotal.txBytes > 0) { + tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + } else { + tmpEntry.txBytes = 0; } - tmpEntry.txPackets = 0; - if (underlyingIfacesTotal.txPackets > 0) { - tmpEntry.txPackets = - totalTxPackets - * perInterfaceTotal[j].txPackets - / underlyingIfacesTotal.txPackets; + if (tunIfaceTotal.txPackets > 0) { + tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + } else { + tmpEntry.txPackets = 0; } - tmpEntry.operations = 0; - if (underlyingIfacesTotal.operations > 0) { + if (tunIfaceTotal.operations > 0) { tmpEntry.operations = - totalOperations - * perInterfaceTotal[j].operations - / underlyingIfacesTotal.operations; + pool.operations * operations[i] / tunIfaceTotal.operations; + } else { + tmpEntry.operations = 0; } - + tmpEntry.uid = uid[i]; + tmpEntry.tag = tag[i]; + tmpEntry.set = set[i]; + tmpEntry.metered = metered[i]; + tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - moved[j].add(tmpEntry); + moved.add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; combineValues(tmpEntry); @@ -1396,45 +1311,38 @@ public class NetworkStats implements Parcelable { return moved; } - private void deductTrafficFromVpnApp( - int tunUid, - @NonNull String[] underlyingIfaces, - @NonNull Entry[] moved) { - for (int i = 0; i < underlyingIfaces.length; i++) { - // Add debug info - moved[i].uid = tunUid; - moved[i].set = SET_DBG_VPN_OUT; - moved[i].tag = TAG_NONE; - moved[i].iface = underlyingIfaces[i]; - moved[i].metered = METERED_ALL; - moved[i].roaming = ROAMING_ALL; - moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; - combineValues(moved[i]); + private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { + // Add debug info + moved.uid = tunUid; + moved.set = SET_DBG_VPN_OUT; + moved.tag = TAG_NONE; + moved.iface = underlyingIface; + moved.metered = METERED_ALL; + moved.roaming = ROAMING_ALL; + moved.defaultNetwork = DEFAULT_NETWORK_ALL; + combineValues(moved); - // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than - // the TAG_NONE traffic. - // - // Relies on the fact that the underlying traffic only has state ROAMING_NO and - // METERED_NO, which should be the case as it comes directly from the /proc file. - // We only blend in the roaming data after applying these adjustments, by checking the - // NetworkIdentity of the underlying iface. - final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, - TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnBackground != -1) { - // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed - // from foreground usage. - tunSubtract(idxVpnBackground, this, moved[i]); - } + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than + // the TAG_NONE traffic. + // + // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, + // which should be the case as it comes directly from the /proc file. We only blend in the + // roaming data after applying these adjustments, by checking the NetworkIdentity of the + // underlying iface. + int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnBackground != -1) { + tunSubtract(idxVpnBackground, this, moved); + } - final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, - TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnForeground != -1) { - tunSubtract(idxVpnForeground, this, moved[i]); - } + int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnForeground != -1) { + tunSubtract(idxVpnForeground, this, moved); } } - private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) { + private static void tunSubtract(int i, NetworkStats left, Entry right) { long rxBytes = Math.min(left.rxBytes[i], right.rxBytes); left.rxBytes[i] -= rxBytes; right.rxBytes -= rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index bdff50053f..a2e7e0cae9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import com.google.android.collect.Sets; - import libcore.io.IoUtils; +import com.google.android.collect.Sets; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -234,7 +234,7 @@ public class NetworkStatsRecorder { if (vpnArray != null) { for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); } } From 656c5eb953cfa40ff998f3f7fa392060ac492e03 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Mon, 10 Jun 2019 22:42:53 +0000 Subject: [PATCH 299/881] Revert "Addressing comments for http://ag/7700679." This reverts commit 290d5733ae066b79104da41a405596d042bcfef9. Reason for revert: This change has been implicated in 4-way deadlocks as seen in b/134244752. Bug: 134244752 Change-Id: I12ab724e2ef8a5c1b42078330ba74713ff86fdd1 Merged-In: I5fbb3443a39a21fc9d96442726cd10d20e8d61cd --- core/java/android/net/NetworkStats.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index b27b1c0578..27e0414961 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1300,8 +1300,7 @@ public class NetworkStats implements Parcelable { } final Entry tmpEntry = new Entry(); - final int origSize = size; - for (int i = 0; i < origSize; i++) { + for (int i = 0; i < size; i++) { if (!Objects.equals(iface[i], tunIface)) { // Consider only entries that go onto the VPN interface. continue; @@ -1317,9 +1316,8 @@ public class NetworkStats implements Parcelable { tmpEntry.roaming = roaming[i]; tmpEntry.defaultNetwork = defaultNetwork[i]; - // In a first pass, compute this entry's total share of data across all - // underlyingIfaces. This is computed on the basis of the share of this entry's usage - // over tunIface. + // In a first pass, compute each UID's total share of data across all underlyingIfaces. + // This is computed on the basis of the share of each UID's usage over tunIface. // TODO: Consider refactoring first pass into a separate helper method. long totalRxBytes = 0; if (tunIfaceTotal.rxBytes > 0) { @@ -1396,11 +1394,9 @@ public class NetworkStats implements Parcelable { * perInterfaceTotal[j].operations / underlyingIfacesTotal.operations; } - // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying - // interface. Add that data usage to this object. + combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - // Add the migrated data to moved so it is deducted from the VPN app later. moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; @@ -1416,8 +1412,8 @@ public class NetworkStats implements Parcelable { @NonNull String[] underlyingIfaces, @NonNull Entry[] moved) { for (int i = 0; i < underlyingIfaces.length; i++) { - moved[i].uid = tunUid; // Add debug info + moved[i].uid = tunUid; moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; moved[i].iface = underlyingIfaces[i]; From 765cb4beee817a09889c02b55f528456f50fa932 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Mon, 10 Jun 2019 22:43:52 +0000 Subject: [PATCH 300/881] Revert "NetworkStatsService: Fix getDetailedUidStats to take VPNs into account." This reverts commit 48f57628283d7cdacd831af3b5b6de8fb44c20ac. Reason for revert: This change has been implicated in 4-way deadlocks as seen in b/134244752. Bug: 134244752 Change-Id: I37f75c2b243ea548a88ef1dae88287405c6ef55f Merged-In: I0c00e8f0e30cee987b71b561079a97bf09d4dae4 --- core/java/android/net/NetworkStats.java | 29 +++----- .../server/net/NetworkStatsFactory.java | 5 -- .../server/net/NetworkStatsService.java | 70 +------------------ 3 files changed, 10 insertions(+), 94 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 27e0414961..9e79606a24 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -34,7 +34,6 @@ import libcore.util.EmptyArray; import java.io.CharArrayWriter; import java.io.PrintWriter; import java.util.Arrays; -import java.util.function.Predicate; import java.util.HashSet; import java.util.Map; import java.util.Objects; @@ -995,33 +994,23 @@ public class NetworkStats implements Parcelable { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { return; } - filter(e -> (limitUid == UID_ALL || limitUid == e.uid) - && (limitTag == TAG_ALL || limitTag == e.tag) - && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, e.iface))); - } - /** - * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. - * - *

This mutates the original structure in place. - */ - public void filterDebugEntries() { - filter(e -> e.set < SET_DEBUG_START); - } - - private void filter(Predicate predicate) { Entry entry = new Entry(); int nextOutputEntry = 0; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - if (predicate.test(entry)) { - if (nextOutputEntry != i) { - setValues(nextOutputEntry, entry); - } + final boolean matches = + (limitUid == UID_ALL || limitUid == entry.uid) + && (limitTag == TAG_ALL || limitTag == entry.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, entry.iface)); + + if (matches) { + setValues(nextOutputEntry, entry); nextOutputEntry++; } } + size = nextOutputEntry; } diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 2e64965a61..69efd02dea 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -263,11 +263,6 @@ public class NetworkStatsFactory { return stats; } - /** - * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for - * VPN traffic - */ - @Deprecated public NetworkStats readNetworkStatsDetail() throws IOException { return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 484efd6bfd..f9972dd873 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -292,22 +292,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); - /** - * Snapshot containing most recent network stats for all UIDs across all interfaces and tags - * since boot. - * - *

Maintains migrated VPN stats which are result of performing TUN migration on {@link - * #mLastUidDetailSnapshot}. - */ - @GuardedBy("mStatsLock") - private NetworkStats mTunAdjustedStats; - /** - * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot - * and latest snapshot. - */ - @GuardedBy("mStatsLock") - private NetworkStats mLastUidDetailSnapshot; - /** Must be set in factory by calling #setHandler. */ private Handler mHandler; private Handler.Callback mHandlerCallback; @@ -821,39 +805,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { - // Get the latest snapshot from NetworkStatsFactory. - // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting - // this to limited set of ifaces. - NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL); - - // Migrate traffic from VPN UID over delta and update mTunAdjustedStats. - NetworkStats result; - synchronized (mStatsLock) { - migrateTunTraffic(uidDetailStats, mVpnInfos); - result = mTunAdjustedStats.clone(); - } - - // Apply filter based on ifacesToQuery. final String[] ifacesToQuery = NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); - result.filter(UID_ALL, ifacesToQuery, TAG_ALL); - return result; + return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); return new NetworkStats(0L, 0); } } - @VisibleForTesting - NetworkStats getTunAdjustedStats() { - synchronized (mStatsLock) { - if (mTunAdjustedStats == null) { - return null; - } - return mTunAdjustedStats.clone(); - } - } - @Override public String[] getMobileIfaces() { return mMobileIfaces; @@ -1328,34 +1288,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime); - - migrateTunTraffic(uidSnapshot, vpnArray); - } - - /** - * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs. - */ - @GuardedBy("mStatsLock") - private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) { - if (mTunAdjustedStats == null) { - // Either device booted or system server restarted, hence traffic cannot be migrated - // correctly without knowing the past state of VPN's underlying networks. - mTunAdjustedStats = uidDetailStats; - mLastUidDetailSnapshot = uidDetailStats; - return; - } - // Migrate delta traffic from VPN to other apps. - NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot); - for (VpnInfo info : vpnInfoArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); - } - // Filter out debug entries as that may lead to over counting. - delta.filterDebugEntries(); - // Update #mTunAdjustedStats with migrated delta. - mTunAdjustedStats.combineAllValues(delta); - mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); - // Update last snapshot. - mLastUidDetailSnapshot = uidDetailStats; } /** From 48608ad513c64a1f7d5436b5e013d16f5319e583 Mon Sep 17 00:00:00 2001 From: Varun Anand Date: Mon, 10 Jun 2019 22:44:57 +0000 Subject: [PATCH 301/881] Revert "Take all VPN underlying networks into account when migrating traffic for" This reverts commit 2e2662fbcfe1611def7ee2055cf17cb2f39d9511. Reason for revert: This change has been implicated in 4-way deadlocks as seen in b/134244752. Bug: 134244752 Change-Id: I2f1839d7776a613ca571af8a542755ddc5fc8760 Merged-In: Ibdaad3a4cbf0d8ef1ed53cfab1e454b9b878bae9 --- core/java/android/net/NetworkStats.java | 320 +++++++----------- .../server/net/NetworkStatsRecorder.java | 6 +- 2 files changed, 117 insertions(+), 209 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9e79606a24..9cf582bef1 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,7 +18,6 @@ package android.net; import static android.os.Process.CLAT_UID; -import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -1176,217 +1175,133 @@ public class NetworkStats implements Parcelable { /** * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface. * - *

This method should only be called on delta NetworkStats. Do not call this method on a - * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change - * over time. + * This method should only be called on delta NetworkStats. Do not call this method on a + * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may + * change over time. * - *

This method performs adjustments for one active VPN package and one VPN iface at a time. + * This method performs adjustments for one active VPN package and one VPN iface at a time. + * + * It is possible for the VPN software to use multiple underlying networks. This method + * only migrates traffic for the primary underlying network. * * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel - * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param underlyingIface the primary underlying network iface used by the VPN application + * @return true if it successfully adjusts the accounting for VPN, false otherwise */ - public void migrateTun(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces) { - // Combined usage by all apps using VPN. - final Entry tunIfaceTotal = new Entry(); - // Usage by VPN, grouped by its {@code underlyingIfaces}. - final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; - // Usage by VPN, summed across all its {@code underlyingIfaces}. - final Entry underlyingIfacesTotal = new Entry(); + public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) { + Entry tunIfaceTotal = new Entry(); + Entry underlyingIfaceTotal = new Entry(); - for (int i = 0; i < perInterfaceTotal.length; i++) { - perInterfaceTotal[i] = new Entry(); - } + tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal); - tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal, - underlyingIfacesTotal); - - // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app. - // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression. + // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app. + // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression. // Negative stats should be avoided. - final Entry[] moved = - addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, - perInterfaceTotal, underlyingIfacesTotal); - deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved); + Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal); + if (pool.isEmpty()) { + return true; + } + Entry moved = + addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); + deductTrafficFromVpnApp(tunUid, underlyingIface, moved); + + if (!moved.isEmpty()) { + Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved=" + + moved); + return false; + } + return true; } /** * Initializes the data used by the migrateTun() method. * - *

This is the first pass iteration which does the following work: - * - *

    - *
  • Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and - * background). - *
  • Adds up all the traffic through tun0 excluding traffic from the vpn app itself. - *
- * - * @param tunUid uid of the VPN application - * @param tunIface iface of the vpn tunnel - * @param underlyingIfaces underlying network ifaces used by the VPN application - * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN - * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code - * underlyingIfaces} - * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its - * {@code underlyingIfaces} + * This is the first pass iteration which does the following work: + * (1) Adds up all the traffic through the tunUid's underlyingIface + * (both foreground and background). + * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. */ - private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, - @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { - final Entry recycle = new Entry(); + private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, + Entry tunIfaceTotal, Entry underlyingIfaceTotal) { + Entry recycle = new Entry(); for (int i = 0; i < size; i++) { getValues(i, recycle); if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); - } - if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { throw new IllegalStateException( "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } - if (recycle.tag != TAG_NONE) { - // TODO(b/123666283): Take all tags for tunUid into account. - continue; + + if (recycle.uid == tunUid && recycle.tag == TAG_NONE + && Objects.equals(underlyingIface, recycle.iface)) { + underlyingIfaceTotal.add(recycle); } - if (recycle.uid == tunUid) { - // Add up traffic through tunUid's underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - if (Objects.equals(underlyingIfaces[j], recycle.iface)) { - perInterfaceTotal[j].add(recycle); - underlyingIfacesTotal.add(recycle); - break; - } - } - } else if (tunIface.equals(recycle.iface)) { + if (recycle.uid != tunUid && recycle.tag == TAG_NONE + && Objects.equals(tunIface, recycle.iface)) { // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } } - /** - * Distributes traffic across apps that are using given {@code tunIface}, and returns the total - * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}. - * - * @param tunUid uid of the VPN application - * @param tunIface iface of the vpn tunnel - * @param underlyingIfaces underlying network ifaces used by the VPN application - * @param tunIfaceTotal combined data usage across all apps using {@code tunIface} - * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces} - * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code - * underlyingIfaces} - */ - private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, - @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { - // Traffic that should be moved off of each underlying interface for tunUid (see - // deductTrafficFromVpnApp below). - final Entry[] moved = new Entry[underlyingIfaces.length]; - for (int i = 0; i < underlyingIfaces.length; i++) { - moved[i] = new Entry(); - } + private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) { + Entry pool = new Entry(); + pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes); + pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets); + pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes); + pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets); + pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations); + return pool; + } - final Entry tmpEntry = new Entry(); + private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, + Entry tunIfaceTotal, Entry pool) { + Entry moved = new Entry(); + Entry tmpEntry = new Entry(); + tmpEntry.iface = underlyingIface; for (int i = 0; i < size; i++) { - if (!Objects.equals(iface[i], tunIface)) { - // Consider only entries that go onto the VPN interface. - continue; - } - if (uid[i] == tunUid) { - // Exclude VPN app from the redistribution, as it can choose to create packet - // streams by writing to itself. - continue; - } - tmpEntry.uid = uid[i]; - tmpEntry.tag = tag[i]; - tmpEntry.metered = metered[i]; - tmpEntry.roaming = roaming[i]; - tmpEntry.defaultNetwork = defaultNetwork[i]; - - // In a first pass, compute each UID's total share of data across all underlyingIfaces. - // This is computed on the basis of the share of each UID's usage over tunIface. - // TODO: Consider refactoring first pass into a separate helper method. - long totalRxBytes = 0; - if (tunIfaceTotal.rxBytes > 0) { - // Note - The multiplication below should not overflow since NetworkStatsService - // processes this every time device has transmitted/received amount equivalent to - // global threshold alert (~ 2MB) across all interfaces. - final long rxBytesAcrossUnderlyingIfaces = - underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; - // app must not be blamed for more than it consumed on tunIface - totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); - } - long totalRxPackets = 0; - if (tunIfaceTotal.rxPackets > 0) { - final long rxPacketsAcrossUnderlyingIfaces = - underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; - totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); - } - long totalTxBytes = 0; - if (tunIfaceTotal.txBytes > 0) { - final long txBytesAcrossUnderlyingIfaces = - underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; - totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); - } - long totalTxPackets = 0; - if (tunIfaceTotal.txPackets > 0) { - final long txPacketsAcrossUnderlyingIfaces = - underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; - totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); - } - long totalOperations = 0; - if (tunIfaceTotal.operations > 0) { - final long operationsAcrossUnderlyingIfaces = - underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; - totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); - } - // In a second pass, distribute these values across interfaces in the proportion that - // each interface represents of the total traffic of the underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - tmpEntry.iface = underlyingIfaces[j]; - tmpEntry.rxBytes = 0; - // Reset 'set' to correct value since it gets updated when adding debug info below. - tmpEntry.set = set[i]; - if (underlyingIfacesTotal.rxBytes > 0) { - tmpEntry.rxBytes = - totalRxBytes - * perInterfaceTotal[j].rxBytes - / underlyingIfacesTotal.rxBytes; + // the vpn app is excluded from the redistribution but all moved traffic will be + // deducted from the vpn app (see deductTrafficFromVpnApp below). + if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { + if (tunIfaceTotal.rxBytes > 0) { + tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + } else { + tmpEntry.rxBytes = 0; } - tmpEntry.rxPackets = 0; - if (underlyingIfacesTotal.rxPackets > 0) { - tmpEntry.rxPackets = - totalRxPackets - * perInterfaceTotal[j].rxPackets - / underlyingIfacesTotal.rxPackets; + if (tunIfaceTotal.rxPackets > 0) { + tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + } else { + tmpEntry.rxPackets = 0; } - tmpEntry.txBytes = 0; - if (underlyingIfacesTotal.txBytes > 0) { - tmpEntry.txBytes = - totalTxBytes - * perInterfaceTotal[j].txBytes - / underlyingIfacesTotal.txBytes; + if (tunIfaceTotal.txBytes > 0) { + tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + } else { + tmpEntry.txBytes = 0; } - tmpEntry.txPackets = 0; - if (underlyingIfacesTotal.txPackets > 0) { - tmpEntry.txPackets = - totalTxPackets - * perInterfaceTotal[j].txPackets - / underlyingIfacesTotal.txPackets; + if (tunIfaceTotal.txPackets > 0) { + tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + } else { + tmpEntry.txPackets = 0; } - tmpEntry.operations = 0; - if (underlyingIfacesTotal.operations > 0) { + if (tunIfaceTotal.operations > 0) { tmpEntry.operations = - totalOperations - * perInterfaceTotal[j].operations - / underlyingIfacesTotal.operations; + pool.operations * operations[i] / tunIfaceTotal.operations; + } else { + tmpEntry.operations = 0; } - + tmpEntry.uid = uid[i]; + tmpEntry.tag = tag[i]; + tmpEntry.set = set[i]; + tmpEntry.metered = metered[i]; + tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - moved[j].add(tmpEntry); + moved.add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; combineValues(tmpEntry); @@ -1396,45 +1311,38 @@ public class NetworkStats implements Parcelable { return moved; } - private void deductTrafficFromVpnApp( - int tunUid, - @NonNull String[] underlyingIfaces, - @NonNull Entry[] moved) { - for (int i = 0; i < underlyingIfaces.length; i++) { - // Add debug info - moved[i].uid = tunUid; - moved[i].set = SET_DBG_VPN_OUT; - moved[i].tag = TAG_NONE; - moved[i].iface = underlyingIfaces[i]; - moved[i].metered = METERED_ALL; - moved[i].roaming = ROAMING_ALL; - moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; - combineValues(moved[i]); + private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { + // Add debug info + moved.uid = tunUid; + moved.set = SET_DBG_VPN_OUT; + moved.tag = TAG_NONE; + moved.iface = underlyingIface; + moved.metered = METERED_ALL; + moved.roaming = ROAMING_ALL; + moved.defaultNetwork = DEFAULT_NETWORK_ALL; + combineValues(moved); - // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than - // the TAG_NONE traffic. - // - // Relies on the fact that the underlying traffic only has state ROAMING_NO and - // METERED_NO, which should be the case as it comes directly from the /proc file. - // We only blend in the roaming data after applying these adjustments, by checking the - // NetworkIdentity of the underlying iface. - final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, - TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnBackground != -1) { - // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed - // from foreground usage. - tunSubtract(idxVpnBackground, this, moved[i]); - } + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than + // the TAG_NONE traffic. + // + // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, + // which should be the case as it comes directly from the /proc file. We only blend in the + // roaming data after applying these adjustments, by checking the NetworkIdentity of the + // underlying iface. + int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnBackground != -1) { + tunSubtract(idxVpnBackground, this, moved); + } - final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, - TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnForeground != -1) { - tunSubtract(idxVpnForeground, this, moved[i]); - } + int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnForeground != -1) { + tunSubtract(idxVpnForeground, this, moved); } } - private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) { + private static void tunSubtract(int i, NetworkStats left, Entry right) { long rxBytes = Math.min(left.rxBytes[i], right.rxBytes); left.rxBytes[i] -= rxBytes; right.rxBytes -= rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index bdff50053f..a2e7e0cae9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import com.google.android.collect.Sets; - import libcore.io.IoUtils; +import com.google.android.collect.Sets; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -234,7 +234,7 @@ public class NetworkStatsRecorder { if (vpnArray != null) { for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); } } From 2cc14c8bed81164b2c7747f715ed57aa40dc84bc Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 12 Jun 2019 17:46:15 +0000 Subject: [PATCH 302/881] Revert "Revert "Take all VPN underlying networks into account when migrating traffic for"" This reverts commit 48608ad513c64a1f7d5436b5e013d16f5319e583. Reason for revert: Fix available for deadlocks. Bug: 134244752 Change-Id: Ib65214598837289bd39dbf040b56ab7835f893ba --- core/java/android/net/NetworkStats.java | 330 +++++++++++------- .../server/net/NetworkStatsRecorder.java | 6 +- 2 files changed, 214 insertions(+), 122 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9cf582bef1..9e79606a24 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,6 +18,7 @@ package android.net; import static android.os.Process.CLAT_UID; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -1175,133 +1176,217 @@ public class NetworkStats implements Parcelable { /** * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface. * - * This method should only be called on delta NetworkStats. Do not call this method on a - * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may - * change over time. + *

This method should only be called on delta NetworkStats. Do not call this method on a + * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change + * over time. * - * This method performs adjustments for one active VPN package and one VPN iface at a time. - * - * It is possible for the VPN software to use multiple underlying networks. This method - * only migrates traffic for the primary underlying network. + *

This method performs adjustments for one active VPN package and one VPN iface at a time. * * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel - * @param underlyingIface the primary underlying network iface used by the VPN application - * @return true if it successfully adjusts the accounting for VPN, false otherwise + * @param underlyingIfaces underlying network ifaces used by the VPN application */ - public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) { - Entry tunIfaceTotal = new Entry(); - Entry underlyingIfaceTotal = new Entry(); + public void migrateTun(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces) { + // Combined usage by all apps using VPN. + final Entry tunIfaceTotal = new Entry(); + // Usage by VPN, grouped by its {@code underlyingIfaces}. + final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; + // Usage by VPN, summed across all its {@code underlyingIfaces}. + final Entry underlyingIfacesTotal = new Entry(); - tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal); + for (int i = 0; i < perInterfaceTotal.length; i++) { + perInterfaceTotal[i] = new Entry(); + } - // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app. - // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression. + tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal, + underlyingIfacesTotal); + + // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app. + // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression. // Negative stats should be avoided. - Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal); - if (pool.isEmpty()) { - return true; - } - Entry moved = - addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); - deductTrafficFromVpnApp(tunUid, underlyingIface, moved); - - if (!moved.isEmpty()) { - Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved=" - + moved); - return false; - } - return true; + final Entry[] moved = + addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, + perInterfaceTotal, underlyingIfacesTotal); + deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved); } /** * Initializes the data used by the migrateTun() method. * - * This is the first pass iteration which does the following work: - * (1) Adds up all the traffic through the tunUid's underlyingIface - * (both foreground and background). - * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *

This is the first pass iteration which does the following work: + * + *

    + *
  • Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and + * background). + *
  • Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *
+ * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN + * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code + * underlyingIfaces} + * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its + * {@code underlyingIfaces} */ - private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry recycle = new Entry(); + private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + final Entry recycle = new Entry(); for (int i = 0; i < size; i++) { getValues(i, recycle); if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); - } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + } + if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { throw new IllegalStateException( "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } - - if (recycle.uid == tunUid && recycle.tag == TAG_NONE - && Objects.equals(underlyingIface, recycle.iface)) { - underlyingIfaceTotal.add(recycle); + if (recycle.tag != TAG_NONE) { + // TODO(b/123666283): Take all tags for tunUid into account. + continue; } - if (recycle.uid != tunUid && recycle.tag == TAG_NONE - && Objects.equals(tunIface, recycle.iface)) { + if (recycle.uid == tunUid) { + // Add up traffic through tunUid's underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + if (Objects.equals(underlyingIfaces[j], recycle.iface)) { + perInterfaceTotal[j].add(recycle); + underlyingIfacesTotal.add(recycle); + break; + } + } + } else if (tunIface.equals(recycle.iface)) { // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } } - private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry pool = new Entry(); - pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes); - pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets); - pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes); - pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets); - pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations); - return pool; - } + /** + * Distributes traffic across apps that are using given {@code tunIface}, and returns the total + * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}. + * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal combined data usage across all apps using {@code tunIface} + * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces} + * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code + * underlyingIfaces} + */ + private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + // Traffic that should be moved off of each underlying interface for tunUid (see + // deductTrafficFromVpnApp below). + final Entry[] moved = new Entry[underlyingIfaces.length]; + for (int i = 0; i < underlyingIfaces.length; i++) { + moved[i] = new Entry(); + } - private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry pool) { - Entry moved = new Entry(); - Entry tmpEntry = new Entry(); - tmpEntry.iface = underlyingIface; + final Entry tmpEntry = new Entry(); for (int i = 0; i < size; i++) { - // the vpn app is excluded from the redistribution but all moved traffic will be - // deducted from the vpn app (see deductTrafficFromVpnApp below). - if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { - if (tunIfaceTotal.rxBytes > 0) { - tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; - } else { - tmpEntry.rxBytes = 0; - } - if (tunIfaceTotal.rxPackets > 0) { - tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; - } else { - tmpEntry.rxPackets = 0; - } - if (tunIfaceTotal.txBytes > 0) { - tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes; - } else { - tmpEntry.txBytes = 0; - } - if (tunIfaceTotal.txPackets > 0) { - tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets; - } else { - tmpEntry.txPackets = 0; - } - if (tunIfaceTotal.operations > 0) { - tmpEntry.operations = - pool.operations * operations[i] / tunIfaceTotal.operations; - } else { - tmpEntry.operations = 0; - } - tmpEntry.uid = uid[i]; - tmpEntry.tag = tag[i]; + if (!Objects.equals(iface[i], tunIface)) { + // Consider only entries that go onto the VPN interface. + continue; + } + if (uid[i] == tunUid) { + // Exclude VPN app from the redistribution, as it can choose to create packet + // streams by writing to itself. + continue; + } + tmpEntry.uid = uid[i]; + tmpEntry.tag = tag[i]; + tmpEntry.metered = metered[i]; + tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; + + // In a first pass, compute each UID's total share of data across all underlyingIfaces. + // This is computed on the basis of the share of each UID's usage over tunIface. + // TODO: Consider refactoring first pass into a separate helper method. + long totalRxBytes = 0; + if (tunIfaceTotal.rxBytes > 0) { + // Note - The multiplication below should not overflow since NetworkStatsService + // processes this every time device has transmitted/received amount equivalent to + // global threshold alert (~ 2MB) across all interfaces. + final long rxBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + // app must not be blamed for more than it consumed on tunIface + totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); + } + long totalRxPackets = 0; + if (tunIfaceTotal.rxPackets > 0) { + final long rxPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); + } + long totalTxBytes = 0; + if (tunIfaceTotal.txBytes > 0) { + final long txBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); + } + long totalTxPackets = 0; + if (tunIfaceTotal.txPackets > 0) { + final long txPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); + } + long totalOperations = 0; + if (tunIfaceTotal.operations > 0) { + final long operationsAcrossUnderlyingIfaces = + underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; + totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); + } + // In a second pass, distribute these values across interfaces in the proportion that + // each interface represents of the total traffic of the underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + tmpEntry.iface = underlyingIfaces[j]; + tmpEntry.rxBytes = 0; + // Reset 'set' to correct value since it gets updated when adding debug info below. tmpEntry.set = set[i]; - tmpEntry.metered = metered[i]; - tmpEntry.roaming = roaming[i]; - tmpEntry.defaultNetwork = defaultNetwork[i]; + if (underlyingIfacesTotal.rxBytes > 0) { + tmpEntry.rxBytes = + totalRxBytes + * perInterfaceTotal[j].rxBytes + / underlyingIfacesTotal.rxBytes; + } + tmpEntry.rxPackets = 0; + if (underlyingIfacesTotal.rxPackets > 0) { + tmpEntry.rxPackets = + totalRxPackets + * perInterfaceTotal[j].rxPackets + / underlyingIfacesTotal.rxPackets; + } + tmpEntry.txBytes = 0; + if (underlyingIfacesTotal.txBytes > 0) { + tmpEntry.txBytes = + totalTxBytes + * perInterfaceTotal[j].txBytes + / underlyingIfacesTotal.txBytes; + } + tmpEntry.txPackets = 0; + if (underlyingIfacesTotal.txPackets > 0) { + tmpEntry.txPackets = + totalTxPackets + * perInterfaceTotal[j].txPackets + / underlyingIfacesTotal.txPackets; + } + tmpEntry.operations = 0; + if (underlyingIfacesTotal.operations > 0) { + tmpEntry.operations = + totalOperations + * perInterfaceTotal[j].operations + / underlyingIfacesTotal.operations; + } + combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - moved.add(tmpEntry); + moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; combineValues(tmpEntry); @@ -1311,38 +1396,45 @@ public class NetworkStats implements Parcelable { return moved; } - private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { - // Add debug info - moved.uid = tunUid; - moved.set = SET_DBG_VPN_OUT; - moved.tag = TAG_NONE; - moved.iface = underlyingIface; - moved.metered = METERED_ALL; - moved.roaming = ROAMING_ALL; - moved.defaultNetwork = DEFAULT_NETWORK_ALL; - combineValues(moved); + private void deductTrafficFromVpnApp( + int tunUid, + @NonNull String[] underlyingIfaces, + @NonNull Entry[] moved) { + for (int i = 0; i < underlyingIfaces.length; i++) { + // Add debug info + moved[i].uid = tunUid; + moved[i].set = SET_DBG_VPN_OUT; + moved[i].tag = TAG_NONE; + moved[i].iface = underlyingIfaces[i]; + moved[i].metered = METERED_ALL; + moved[i].roaming = ROAMING_ALL; + moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; + combineValues(moved[i]); - // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than - // the TAG_NONE traffic. - // - // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, - // which should be the case as it comes directly from the /proc file. We only blend in the - // roaming data after applying these adjustments, by checking the NetworkIdentity of the - // underlying iface. - int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnBackground != -1) { - tunSubtract(idxVpnBackground, this, moved); - } + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than + // the TAG_NONE traffic. + // + // Relies on the fact that the underlying traffic only has state ROAMING_NO and + // METERED_NO, which should be the case as it comes directly from the /proc file. + // We only blend in the roaming data after applying these adjustments, by checking the + // NetworkIdentity of the underlying iface. + final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnBackground != -1) { + // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed + // from foreground usage. + tunSubtract(idxVpnBackground, this, moved[i]); + } - int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnForeground != -1) { - tunSubtract(idxVpnForeground, this, moved); + final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnForeground != -1) { + tunSubtract(idxVpnForeground, this, moved[i]); + } } } - private static void tunSubtract(int i, NetworkStats left, Entry right) { + private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) { long rxBytes = Math.min(left.rxBytes[i], right.rxBytes); left.rxBytes[i] -= rxBytes; right.rxBytes -= rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a2e7e0cae9..bdff50053f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import libcore.io.IoUtils; - import com.google.android.collect.Sets; +import libcore.io.IoUtils; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -234,7 +234,7 @@ public class NetworkStatsRecorder { if (vpnArray != null) { for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); } } From d9d6958e06b75b295e8a6e5fd21d181783c7ec9d Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 11 Jun 2019 18:21:30 -0700 Subject: [PATCH 303/881] Remove unused lastStats parameter This change removes an unused parameter that is always null in getNetworkStatsUidDetail Bug: 134244752 Test: FrameworksNetTest passing Change-Id: I995b108ef30e1fbd6190131ed4db40a3d9327eb5 --- .../server/net/NetworkStatsFactory.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 69efd02dea..c118bda88c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -16,6 +16,7 @@ package com.android.server.net; +import static android.net.NetworkStats.INTERFACES_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; @@ -264,13 +265,21 @@ public class NetworkStatsFactory { } public NetworkStats readNetworkStatsDetail() throws IOException { - return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); + return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); } - public NetworkStats readNetworkStatsDetail(int limitUid, String[] limitIfaces, int limitTag, - NetworkStats lastStats) throws IOException { - final NetworkStats stats = - readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); + /** + * Reads the detailed UID stats based on the provided parameters + * + * @param limitUid the UID to limit this query to + * @param limitIfaces the interfaces to limit this query to. Use {@link + * NetworkStats.INTERFACES_ALL} to select all interfaces + * @param limitTag the tags to limit this query to + * @return the NetworkStats instance containing network statistics at the present time. + */ + public NetworkStats readNetworkStatsDetail( + int limitUid, @Nullable String[] limitIfaces, int limitTag) throws IOException { + final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. // TODO: remove this and only apply adjustments in NetworkStatsService. @@ -292,17 +301,11 @@ public class NetworkStatsFactory { } } - // TODO: delete the lastStats parameter - private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces, - int limitTag, NetworkStats lastStats) throws IOException { + private NetworkStats readNetworkStatsDetailInternal( + int limitUid, String[] limitIfaces, int limitTag) throws IOException { if (USE_NATIVE_PARSING) { - final NetworkStats stats; - if (lastStats != null) { - stats = lastStats; - stats.setElapsedRealtime(SystemClock.elapsedRealtime()); - } else { - stats = new NetworkStats(SystemClock.elapsedRealtime(), -1); - } + final NetworkStats stats = + new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */); if (mUseBpfStats) { synchronized (mPersistSnapshot) { try { From 7d5e62485b2025231a206d1833f14019a38f1bbf Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 12 Jun 2019 17:46:31 +0000 Subject: [PATCH 304/881] NetworkStatsFactory: Take VPNs into account for network/battery stats This change fixes detailed UID stats to ensure network and battery stats both take VPNs into account. NetworkStatsFactory is being made aware of VPNs enabled, and the full set of underlying networks present. Since traffic can only be migrated over a NetworkStats delta, NSF maintains a NetworkStats snapshot across all UIDs/ifaces/tags. This snapshot gets updated whenever NSF records a new snapshot (based on various hooks such as VPN updating its underlying networks, network getting lost, etc.), or NetworkStatsService's getDetailedUidStats() method being called. This change widens the scope of the existing mPersistentSnapshot lock, renaming it to mPersistentDataLock, and ensures that TUN migrations are not done in parallel. Additionally, mVpnInfos is updated via pointer-swapping, to reduce the scope of the mPersistentDataLock. The safety of this change is predicated on: 1. NetworkStatsFactory lock not held, so services cannot deadlock through the cyclical lock. 2. The broadening of the scope of the lock in NetworkStatsFactory has no threading implications, as it is always the last (leaf node) lock held, and therefore is impossible to have lock inversion. Additionally, to ensure VPNs work with 464xlat, the VPN info passed to the NetworkStatsFactory includes all underlying interfaces, instead of only passing the first one. This (partially) re-applies changes from: aosp/972848: Add one more test for VPN usage stats. aosp/972847: Addressing comments for http://ag/7700679. aosp/885338: NetworkStatsService: Fix getDetailedUidStats to take VPNs into account. Co-developed with: Varun Anand Bug: 113122541 Bug: 120145746 Bug: 129264869 Bug: 134244752 Test: FrameworksNetTest passing Test: Manual tests show data usage fixes maintained. Change-Id: I6466ec1411fc5ed6954125d27d353b6cd1be719e --- .../android/net/INetworkStatsService.aidl | 1 - core/java/android/net/NetworkStats.java | 44 ++++-- .../server/net/NetworkStatsFactory.java | 135 +++++++++++++----- .../server/net/NetworkStatsService.java | 28 ++-- 4 files changed, 140 insertions(+), 68 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 41efc50408..e5f3d26667 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -66,7 +66,6 @@ interface INetworkStatsService { /** Force update of ifaces. */ void forceUpdateIfaces( in Network[] defaultNetworks, - in VpnInfo[] vpnArray, in NetworkState[] networkStates, in String activeIface); /** Force update of statistics. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9e79606a24..14a0cbf611 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -23,7 +23,6 @@ import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; -import android.util.Slog; import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; @@ -37,6 +36,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.function.Predicate; /** * Collection of active network statistics. Can contain summary details across @@ -994,23 +994,33 @@ public class NetworkStats implements Parcelable { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { return; } + filter(e -> (limitUid == UID_ALL || limitUid == e.uid) + && (limitTag == TAG_ALL || limitTag == e.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, e.iface))); + } + /** + * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. + * + *

This mutates the original structure in place. + */ + public void filterDebugEntries() { + filter(e -> e.set < SET_DEBUG_START); + } + + private void filter(Predicate predicate) { Entry entry = new Entry(); int nextOutputEntry = 0; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - final boolean matches = - (limitUid == UID_ALL || limitUid == entry.uid) - && (limitTag == TAG_ALL || limitTag == entry.tag) - && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, entry.iface)); - - if (matches) { - setValues(nextOutputEntry, entry); + if (predicate.test(entry)) { + if (nextOutputEntry != i) { + setValues(nextOutputEntry, entry); + } nextOutputEntry++; } } - size = nextOutputEntry; } @@ -1289,7 +1299,8 @@ public class NetworkStats implements Parcelable { } final Entry tmpEntry = new Entry(); - for (int i = 0; i < size; i++) { + final int origSize = size; + for (int i = 0; i < origSize; i++) { if (!Objects.equals(iface[i], tunIface)) { // Consider only entries that go onto the VPN interface. continue; @@ -1305,8 +1316,9 @@ public class NetworkStats implements Parcelable { tmpEntry.roaming = roaming[i]; tmpEntry.defaultNetwork = defaultNetwork[i]; - // In a first pass, compute each UID's total share of data across all underlyingIfaces. - // This is computed on the basis of the share of each UID's usage over tunIface. + // In a first pass, compute this entry's total share of data across all + // underlyingIfaces. This is computed on the basis of the share of this entry's usage + // over tunIface. // TODO: Consider refactoring first pass into a separate helper method. long totalRxBytes = 0; if (tunIfaceTotal.rxBytes > 0) { @@ -1383,9 +1395,11 @@ public class NetworkStats implements Parcelable { * perInterfaceTotal[j].operations / underlyingIfacesTotal.operations; } - + // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying + // interface. Add that data usage to this object. combineValues(tmpEntry); if (tag[i] == TAG_NONE) { + // Add the migrated data to moved so it is deducted from the VPN app later. moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; @@ -1401,8 +1415,8 @@ public class NetworkStats implements Parcelable { @NonNull String[] underlyingIfaces, @NonNull Entry[] moved) { for (int i = 0; i < underlyingIfaces.length; i++) { - // Add debug info moved[i].uid = tunUid; + // Add debug info moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; moved[i].iface = underlyingIfaces[i]; diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index c118bda88c..2d3c66d68f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -34,6 +34,7 @@ import android.os.SystemClock; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; @@ -71,11 +72,25 @@ public class NetworkStatsFactory { private INetd mNetdService; - // A persistent Snapshot since device start for eBPF stats - @GuardedBy("mPersistSnapshot") - private final NetworkStats mPersistSnapshot; + /** + * Guards persistent data access in this class + * + *

In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out + * to other code that will acquire other locks within the system server. See b/134244752. + */ + private static final Object sPersistentDataLock = new Object(); + + /** Set containing info about active VPNs and their underlying networks. */ + private static volatile VpnInfo[] sVpnInfos = new VpnInfo[0]; + + // A persistent snapshot of cumulative stats since device start + @GuardedBy("sPersistentDataLock") + private NetworkStats mPersistSnapshot; + + // The persistent snapshot of tun and 464xlat adjusted stats since device start + @GuardedBy("sPersistentDataLock") + private NetworkStats mTunAnd464xlatAdjustedStats; - // TODO: only do adjustments in NetworkStatsService and remove this. /** * (Stacked interface) -> (base interface) association for all connected ifaces since boot. * @@ -91,6 +106,24 @@ public class NetworkStatsFactory { } } + /** + * Set active VPN information for data usage migration purposes + * + *

Traffic on TUN-based VPNs inherently all appear to be originated from the VPN providing + * app's UID. This method is used to support migration of VPN data usage, ensuring data is + * accurately billed to the real owner of the traffic. + * + * @param vpnArray The snapshot of the currently-running VPNs. + */ + public static void updateVpnInfos(VpnInfo[] vpnArray) { + sVpnInfos = vpnArray.clone(); + } + + @VisibleForTesting + public static VpnInfo[] getVpnInfos() { + return sVpnInfos.clone(); + } + /** * Get a set of interfaces containing specified ifaces and stacked interfaces. * @@ -147,6 +180,7 @@ public class NetworkStatsFactory { mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); + mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } public NetworkStats readBpfNetworkStatsDev() throws IOException { @@ -279,16 +313,10 @@ public class NetworkStatsFactory { */ public NetworkStats readNetworkStatsDetail( int limitUid, @Nullable String[] limitIfaces, int limitTag) throws IOException { - final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); - - // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. - // TODO: remove this and only apply adjustments in NetworkStatsService. - stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); - - return stats; + return readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); } - @GuardedBy("mPersistSnapshot") + @GuardedBy("sPersistentDataLock") private void requestSwapActiveStatsMapLocked() throws RemoteException { // Ask netd to do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map @@ -303,11 +331,18 @@ public class NetworkStatsFactory { private NetworkStats readNetworkStatsDetailInternal( int limitUid, String[] limitIfaces, int limitTag) throws IOException { - if (USE_NATIVE_PARSING) { - final NetworkStats stats = - new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */); - if (mUseBpfStats) { - synchronized (mPersistSnapshot) { + // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other + // code that will acquire other locks within the system server. See b/134244752. + synchronized (sPersistentDataLock) { + // Take a reference. If this gets swapped out, we still have the old reference. + final VpnInfo[] vpnArray = sVpnInfos; + // Take a defensive copy. mPersistSnapshot is mutated in some cases below + final NetworkStats prev = mPersistSnapshot.clone(); + + if (USE_NATIVE_PARSING) { + final NetworkStats stats = + new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */); + if (mUseBpfStats) { try { requestSwapActiveStatsMapLocked(); } catch (RemoteException e) { @@ -316,32 +351,66 @@ public class NetworkStatsFactory { // Stats are always read from the inactive map, so they must be read after the // swap if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, - null, TAG_ALL, mUseBpfStats) != 0) { + INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) { throw new IOException("Failed to parse network stats"); } + + // BPF stats are incremental; fold into mPersistSnapshot. mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime()); mPersistSnapshot.combineAllValues(stats); - NetworkStats result = mPersistSnapshot.clone(); - result.filter(limitUid, limitIfaces, limitTag); - return result; + } else { + if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, + INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) { + throw new IOException("Failed to parse network stats"); + } + if (SANITY_CHECK_NATIVE) { + final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, + UID_ALL, INTERFACES_ALL, TAG_ALL); + assertEquals(javaStats, stats); + } + + mPersistSnapshot = stats; } } else { - if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, - limitIfaces, limitTag, mUseBpfStats) != 0) { - throw new IOException("Failed to parse network stats"); - } - if (SANITY_CHECK_NATIVE) { - final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid, - limitIfaces, limitTag); - assertEquals(javaStats, stats); - } - return stats; + mPersistSnapshot = javaReadNetworkStatsDetail(mStatsXtUid, UID_ALL, INTERFACES_ALL, + TAG_ALL); } - } else { - return javaReadNetworkStatsDetail(mStatsXtUid, limitUid, limitIfaces, limitTag); + + NetworkStats adjustedStats = adjustForTunAnd464Xlat(mPersistSnapshot, prev, vpnArray); + + // Filter return values + adjustedStats.filter(limitUid, limitIfaces, limitTag); + return adjustedStats; } } + @GuardedBy("sPersistentDataLock") + private NetworkStats adjustForTunAnd464Xlat( + NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) { + // Calculate delta from last snapshot + final NetworkStats delta = uidDetailStats.subtract(previousStats); + + // Apply 464xlat adjustments before VPN adjustments. If VPNs are using v4 on a v6 only + // network, the overhead is their fault. + // No locking here: apply464xlatAdjustments behaves fine with an add-only + // ConcurrentHashMap. + delta.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); + + // Migrate data usage over a VPN to the TUN network. + for (VpnInfo info : vpnArray) { + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + } + + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); + + // Update mTunAnd464xlatAdjustedStats with migrated delta. + mTunAnd464xlatAdjustedStats.combineAllValues(delta); + mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); + + return mTunAnd464xlatAdjustedStats.clone(); + } + /** * Parse and return {@link NetworkStats} with UID-level details. Values are * expected to monotonically increase since device boot. diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index f9972dd873..6ca3e38d69 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -130,7 +130,6 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; @@ -266,10 +265,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; - /** Set containing info about active VPNs and their underlying networks. */ - @GuardedBy("mStatsLock") - private VpnInfo[] mVpnInfos = new VpnInfo[0]; - private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -857,7 +852,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void forceUpdateIfaces( Network[] defaultNetworks, - VpnInfo[] vpnArray, NetworkState[] networkStates, String activeIface) { checkNetworkStackPermission(mContext); @@ -865,7 +859,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks, vpnArray, networkStates, activeIface); + updateIfaces(defaultNetworks, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1131,13 +1125,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void updateIfaces( Network[] defaultNetworks, - VpnInfo[] vpnArray, NetworkState[] networkStates, String activeIface) { synchronized (mStatsLock) { mWakeLock.acquire(); try { - mVpnInfos = vpnArray; mActiveIface = activeIface; updateIfacesLocked(defaultNetworks, networkStates); } finally { @@ -1147,10 +1139,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Inspect all current {@link NetworkState} to derive mapping from {@code - * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo} - * are active on a single {@code iface}, they are combined under a single - * {@link NetworkIdentitySet}. + * Inspect all current {@link NetworkState} to derive mapping from {@code iface} to {@link + * NetworkStatsHistory}. When multiple {@link NetworkInfo} are active on a single {@code iface}, + * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { @@ -1276,18 +1267,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. - VpnInfo[] vpnArray = mVpnInfos; Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); - mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); + mUidRecorder.recordSnapshotLocked( + uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag"); - mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); + mUidTagRecorder.recordSnapshotLocked( + uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); // We need to make copies of member fields that are sent to the observer to avoid // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), - new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime); + new ArrayMap<>(mActiveUidIfaces), null /* vpnArray */, currentTime); } /** @@ -1660,8 +1652,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ private NetworkStats getNetworkStatsUidDetail(String[] ifaces) throws RemoteException { - - // TODO: remove 464xlat adjustments from NetworkStatsFactory and apply all at once here. final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL, ifaces); From f2465f87c20c7618b2727a9e8eab2a4d4559c2ff Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 13 Jun 2019 10:54:38 -0700 Subject: [PATCH 305/881] Remove VPN info arrays from NetworkStats(Observer|Recorder) This change removes the now-unused VPN arrays in the network stats observer and recorder classes. These are always null values in every call site. Bug: 113122541 Bug: 120145746 Bug: 129264869 Bug: 134244752 Test: FrameworksNetTest passing Test: Manual tests show data usage fixes maintained. Change-Id: Ieb8645acc400fdaeb0df7092c5369b96f9f35af9 --- .../server/net/NetworkStatsObservers.java | 13 +++++------ .../server/net/NetworkStatsRecorder.java | 22 ++++--------------- .../server/net/NetworkStatsService.java | 14 +++++------- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java index d8408730dd..2564daeaa1 100644 --- a/services/core/java/com/android/server/net/NetworkStatsObservers.java +++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java @@ -39,7 +39,6 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.VpnInfo; import java.util.concurrent.atomic.AtomicInteger; @@ -104,9 +103,9 @@ class NetworkStatsObservers { public void updateStats(NetworkStats xtSnapshot, NetworkStats uidSnapshot, ArrayMap activeIfaces, ArrayMap activeUidIfaces, - VpnInfo[] vpnArray, long currentTime) { + long currentTime) { StatsContext statsContext = new StatsContext(xtSnapshot, uidSnapshot, activeIfaces, - activeUidIfaces, vpnArray, currentTime); + activeUidIfaces, currentTime); getHandler().sendMessage(mHandler.obtainMessage(MSG_UPDATE_STATS, statsContext)); } @@ -354,7 +353,7 @@ class NetworkStatsObservers { // thread will update it. We pass a null VPN array because usage is aggregated by uid // for this snapshot, so VPN traffic can't be reattributed to responsible apps. mRecorder.recordSnapshotLocked(statsContext.mXtSnapshot, statsContext.mActiveIfaces, - null /* vpnArray */, statsContext.mCurrentTime); + statsContext.mCurrentTime); } /** @@ -396,7 +395,7 @@ class NetworkStatsObservers { // thread will update it. We pass the VPN info so VPN traffic is reattributed to // responsible apps. mRecorder.recordSnapshotLocked(statsContext.mUidSnapshot, statsContext.mActiveUidIfaces, - statsContext.mVpnArray, statsContext.mCurrentTime); + statsContext.mCurrentTime); } /** @@ -427,18 +426,16 @@ class NetworkStatsObservers { NetworkStats mUidSnapshot; ArrayMap mActiveIfaces; ArrayMap mActiveUidIfaces; - VpnInfo[] mVpnArray; long mCurrentTime; StatsContext(NetworkStats xtSnapshot, NetworkStats uidSnapshot, ArrayMap activeIfaces, ArrayMap activeUidIfaces, - VpnInfo[] vpnArray, long currentTime) { + long currentTime) { mXtSnapshot = xtSnapshot; mUidSnapshot = uidSnapshot; mActiveIfaces = activeIfaces; mActiveUidIfaces = activeUidIfaces; - mVpnArray = vpnArray; mCurrentTime = currentTime; } } diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index bdff50053f..06ec341d9e 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -23,7 +23,6 @@ import static android.text.format.DateUtils.YEAR_IN_MILLIS; import static com.android.internal.util.Preconditions.checkNotNull; -import android.annotation.Nullable; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; @@ -37,7 +36,6 @@ import android.util.MathUtils; import android.util.Slog; import android.util.proto.ProtoOutputStream; -import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; @@ -202,18 +200,12 @@ public class NetworkStatsRecorder { } /** - * Record any delta that occurred since last {@link NetworkStats} snapshot, - * using the given {@link Map} to identify network interfaces. First - * snapshot is considered bootstrap, and is not counted as delta. - * - * @param vpnArray Optional info about the currently active VPN, if any. This is used to - * redistribute traffic from the VPN app to the underlying responsible apps. - * This should always be set to null if the provided snapshot is aggregated - * across all UIDs (e.g. contains UID_ALL buckets), regardless of VPN state. + * Record any delta that occurred since last {@link NetworkStats} snapshot, using the given + * {@link Map} to identify network interfaces. First snapshot is considered bootstrap, and is + * not counted as delta. */ public void recordSnapshotLocked(NetworkStats snapshot, - Map ifaceIdent, @Nullable VpnInfo[] vpnArray, - long currentTimeMillis) { + Map ifaceIdent, long currentTimeMillis) { final HashSet unknownIfaces = Sets.newHashSet(); // skip recording when snapshot missing @@ -232,12 +224,6 @@ public class NetworkStatsRecorder { final long end = currentTimeMillis; final long start = end - delta.getElapsedRealtime(); - if (vpnArray != null) { - for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); - } - } - NetworkStats.Entry entry = null; for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 6ca3e38d69..2fc78d6f47 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1258,28 +1258,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev"); - mDevRecorder.recordSnapshotLocked( - devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime); + mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt"); - mXtRecorder.recordSnapshotLocked( - xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime); + mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); - mUidRecorder.recordSnapshotLocked( - uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); + mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag"); - mUidTagRecorder.recordSnapshotLocked( - uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); + mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); // We need to make copies of member fields that are sent to the observer to avoid // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), - new ArrayMap<>(mActiveUidIfaces), null /* vpnArray */, currentTime); + new ArrayMap<>(mActiveUidIfaces), currentTime); } /** From 82a1e493b112ea64588a1ce5bca349f3386348b1 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 30 May 2019 17:11:14 +0900 Subject: [PATCH 306/881] Factorize custom asserts. Also a few utilities that were in the way, and some opportunistic cleanups. Test: FrameworksNetTest NetworkStackTest Change-Id: I385070e2044fd967cb18f1ffea9a86a4627b742e --- core/java/android/net/IpSecConfig.java | 41 ++++++++++++----------- core/java/android/net/IpSecTransform.java | 14 ++++---- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java index 3552655983..43c8ff2335 100644 --- a/core/java/android/net/IpSecConfig.java +++ b/core/java/android/net/IpSecConfig.java @@ -15,6 +15,7 @@ */ package android.net; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; @@ -333,25 +334,25 @@ public final class IpSecConfig implements Parcelable { } }; - @VisibleForTesting - /** Equals method used for testing */ - public static boolean equals(IpSecConfig lhs, IpSecConfig rhs) { - if (lhs == null || rhs == null) return (lhs == rhs); - return (lhs.mMode == rhs.mMode - && lhs.mSourceAddress.equals(rhs.mSourceAddress) - && lhs.mDestinationAddress.equals(rhs.mDestinationAddress) - && ((lhs.mNetwork != null && lhs.mNetwork.equals(rhs.mNetwork)) - || (lhs.mNetwork == rhs.mNetwork)) - && lhs.mEncapType == rhs.mEncapType - && lhs.mEncapSocketResourceId == rhs.mEncapSocketResourceId - && lhs.mEncapRemotePort == rhs.mEncapRemotePort - && lhs.mNattKeepaliveInterval == rhs.mNattKeepaliveInterval - && lhs.mSpiResourceId == rhs.mSpiResourceId - && IpSecAlgorithm.equals(lhs.mEncryption, rhs.mEncryption) - && IpSecAlgorithm.equals(lhs.mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) - && IpSecAlgorithm.equals(lhs.mAuthentication, rhs.mAuthentication) - && lhs.mMarkValue == rhs.mMarkValue - && lhs.mMarkMask == rhs.mMarkMask - && lhs.mXfrmInterfaceId == rhs.mXfrmInterfaceId); + @Override + public boolean equals(@Nullable Object other) { + if (!(other instanceof IpSecConfig)) return false; + final IpSecConfig rhs = (IpSecConfig) other; + return (mMode == rhs.mMode + && mSourceAddress.equals(rhs.mSourceAddress) + && mDestinationAddress.equals(rhs.mDestinationAddress) + && ((mNetwork != null && mNetwork.equals(rhs.mNetwork)) + || (mNetwork == rhs.mNetwork)) + && mEncapType == rhs.mEncapType + && mEncapSocketResourceId == rhs.mEncapSocketResourceId + && mEncapRemotePort == rhs.mEncapRemotePort + && mNattKeepaliveInterval == rhs.mNattKeepaliveInterval + && mSpiResourceId == rhs.mSpiResourceId + && IpSecAlgorithm.equals(mEncryption, rhs.mEncryption) + && IpSecAlgorithm.equals(mAuthenticatedEncryption, rhs.mAuthenticatedEncryption) + && IpSecAlgorithm.equals(mAuthentication, rhs.mAuthentication) + && mMarkValue == rhs.mMarkValue + && mMarkMask == rhs.mMarkMask + && mXfrmInterfaceId == rhs.mXfrmInterfaceId); } } diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index a12df28eac..93ae4f1188 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -148,15 +148,13 @@ public final class IpSecTransform implements AutoCloseable { } /** - * Equals method used for testing - * - * @hide + * Standard equals. */ - @VisibleForTesting - public static boolean equals(IpSecTransform lhs, IpSecTransform rhs) { - if (lhs == null || rhs == null) return (lhs == rhs); - return IpSecConfig.equals(lhs.getConfig(), rhs.getConfig()) - && lhs.mResourceId == rhs.mResourceId; + public boolean equals(Object other) { + if (this == other) return true; + if (!(other instanceof IpSecTransform)) return false; + final IpSecTransform rhs = (IpSecTransform) other; + return getConfig().equals(rhs.getConfig()) && mResourceId == rhs.mResourceId; } /** From 2cb570ff3651d721d7e8d50504759f04923d5767 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Fri, 14 Jun 2019 11:54:49 -0700 Subject: [PATCH 307/881] Inline readNetworkStatsDetailInternal, make mUseBpfStats final This change inlines the logic from readNetworkStatsDetailInternal, and reduces reundant checks in mUseBpfStats Bug: 113122541 Test: atest FrameworksNetTests run, passing Change-Id: If2ef8d8f038f32c8cf974aa02cfc1dc7e44dbad3 --- .../server/net/NetworkStatsFactory.java | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 2d3c66d68f..7687718b06 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -68,7 +68,7 @@ public class NetworkStatsFactory { /** Path to {@code /proc/net/xt_qtaguid/stats}. */ private final File mStatsXtUid; - private boolean mUseBpfStats; + private final boolean mUseBpfStats; private INetd mNetdService; @@ -302,6 +302,17 @@ public class NetworkStatsFactory { return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); } + @GuardedBy("sPersistentDataLock") + private void requestSwapActiveStatsMapLocked() throws RemoteException { + // Ask netd to do a active map stats swap. When the binder call successfully returns, + // the system server should be able to safely read and clean the inactive map + // without race problem. + if (mNetdService == null) { + mNetdService = NetdService.getInstance(); + } + mNetdService.trafficSwapActiveStatsMap(); + } + /** * Reads the detailed UID stats based on the provided parameters * @@ -312,24 +323,6 @@ public class NetworkStatsFactory { * @return the NetworkStats instance containing network statistics at the present time. */ public NetworkStats readNetworkStatsDetail( - int limitUid, @Nullable String[] limitIfaces, int limitTag) throws IOException { - return readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); - } - - @GuardedBy("sPersistentDataLock") - private void requestSwapActiveStatsMapLocked() throws RemoteException { - // Ask netd to do a active map stats swap. When the binder call successfully returns, - // the system server should be able to safely read and clean the inactive map - // without race problem. - if (mUseBpfStats) { - if (mNetdService == null) { - mNetdService = NetdService.getInstance(); - } - mNetdService.trafficSwapActiveStatsMap(); - } - } - - private NetworkStats readNetworkStatsDetailInternal( int limitUid, String[] limitIfaces, int limitTag) throws IOException { // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other // code that will acquire other locks within the system server. See b/134244752. From 43fc79efce5f1ebf84ca7fc757874a9532a68ef3 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 12 Jun 2019 17:46:15 +0000 Subject: [PATCH 308/881] Revert "Revert "Take all VPN underlying networks into account when migrating traffic for"" This reverts commit 48608ad513c64a1f7d5436b5e013d16f5319e583. Reason for revert: Fix available for deadlocks. Bug: 113122541 Bug: 134244752 Merged-In: Ib65214598837289bd39dbf040b56ab7835f893ba Change-Id: Ia90bf2c72ef686e80800d113d03548e0efcadb66 (cherry picked from commit 2cc14c8bed81164b2c7747f715ed57aa40dc84bc) --- core/java/android/net/NetworkStats.java | 330 +++++++++++------- .../server/net/NetworkStatsRecorder.java | 6 +- 2 files changed, 214 insertions(+), 122 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index e892b650bf..f09f2ee223 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,6 +18,7 @@ package android.net; import static android.os.Process.CLAT_UID; +import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; @@ -1175,133 +1176,217 @@ public class NetworkStats implements Parcelable { /** * VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface. * - * This method should only be called on delta NetworkStats. Do not call this method on a - * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may - * change over time. + *

This method should only be called on delta NetworkStats. Do not call this method on a + * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change + * over time. * - * This method performs adjustments for one active VPN package and one VPN iface at a time. - * - * It is possible for the VPN software to use multiple underlying networks. This method - * only migrates traffic for the primary underlying network. + *

This method performs adjustments for one active VPN package and one VPN iface at a time. * * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel - * @param underlyingIface the primary underlying network iface used by the VPN application - * @return true if it successfully adjusts the accounting for VPN, false otherwise + * @param underlyingIfaces underlying network ifaces used by the VPN application */ - public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) { - Entry tunIfaceTotal = new Entry(); - Entry underlyingIfaceTotal = new Entry(); + public void migrateTun(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces) { + // Combined usage by all apps using VPN. + final Entry tunIfaceTotal = new Entry(); + // Usage by VPN, grouped by its {@code underlyingIfaces}. + final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; + // Usage by VPN, summed across all its {@code underlyingIfaces}. + final Entry underlyingIfacesTotal = new Entry(); - tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal); + for (int i = 0; i < perInterfaceTotal.length; i++) { + perInterfaceTotal[i] = new Entry(); + } - // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app. - // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression. + tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal, + underlyingIfacesTotal); + + // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app. + // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression. // Negative stats should be avoided. - Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal); - if (pool.isEmpty()) { - return true; - } - Entry moved = - addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool); - deductTrafficFromVpnApp(tunUid, underlyingIface, moved); - - if (!moved.isEmpty()) { - Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved=" - + moved); - return false; - } - return true; + final Entry[] moved = + addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, + perInterfaceTotal, underlyingIfacesTotal); + deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved); } /** * Initializes the data used by the migrateTun() method. * - * This is the first pass iteration which does the following work: - * (1) Adds up all the traffic through the tunUid's underlyingIface - * (both foreground and background). - * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *

This is the first pass iteration which does the following work: + * + *

    + *
  • Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and + * background). + *
  • Adds up all the traffic through tun0 excluding traffic from the vpn app itself. + *
+ * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN + * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code + * underlyingIfaces} + * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its + * {@code underlyingIfaces} */ - private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry recycle = new Entry(); + private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + final Entry recycle = new Entry(); for (int i = 0; i < size; i++) { getValues(i, recycle); if (recycle.uid == UID_ALL) { throw new IllegalStateException( "Cannot adjust VPN accounting on an iface aggregated NetworkStats."); - } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { + } + if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) { throw new IllegalStateException( "Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*"); } - - if (recycle.uid == tunUid && recycle.tag == TAG_NONE - && Objects.equals(underlyingIface, recycle.iface)) { - underlyingIfaceTotal.add(recycle); + if (recycle.tag != TAG_NONE) { + // TODO(b/123666283): Take all tags for tunUid into account. + continue; } - if (recycle.uid != tunUid && recycle.tag == TAG_NONE - && Objects.equals(tunIface, recycle.iface)) { + if (recycle.uid == tunUid) { + // Add up traffic through tunUid's underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + if (Objects.equals(underlyingIfaces[j], recycle.iface)) { + perInterfaceTotal[j].add(recycle); + underlyingIfacesTotal.add(recycle); + break; + } + } + } else if (tunIface.equals(recycle.iface)) { // Add up all tunIface traffic excluding traffic from the vpn app itself. tunIfaceTotal.add(recycle); } } } - private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) { - Entry pool = new Entry(); - pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes); - pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets); - pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes); - pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets); - pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations); - return pool; - } + /** + * Distributes traffic across apps that are using given {@code tunIface}, and returns the total + * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}. + * + * @param tunUid uid of the VPN application + * @param tunIface iface of the vpn tunnel + * @param underlyingIfaces underlying network ifaces used by the VPN application + * @param tunIfaceTotal combined data usage across all apps using {@code tunIface} + * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces} + * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code + * underlyingIfaces} + */ + private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, + @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { + // Traffic that should be moved off of each underlying interface for tunUid (see + // deductTrafficFromVpnApp below). + final Entry[] moved = new Entry[underlyingIfaces.length]; + for (int i = 0; i < underlyingIfaces.length; i++) { + moved[i] = new Entry(); + } - private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface, - Entry tunIfaceTotal, Entry pool) { - Entry moved = new Entry(); - Entry tmpEntry = new Entry(); - tmpEntry.iface = underlyingIface; + final Entry tmpEntry = new Entry(); for (int i = 0; i < size; i++) { - // the vpn app is excluded from the redistribution but all moved traffic will be - // deducted from the vpn app (see deductTrafficFromVpnApp below). - if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) { - if (tunIfaceTotal.rxBytes > 0) { - tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; - } else { - tmpEntry.rxBytes = 0; - } - if (tunIfaceTotal.rxPackets > 0) { - tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; - } else { - tmpEntry.rxPackets = 0; - } - if (tunIfaceTotal.txBytes > 0) { - tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes; - } else { - tmpEntry.txBytes = 0; - } - if (tunIfaceTotal.txPackets > 0) { - tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets; - } else { - tmpEntry.txPackets = 0; - } - if (tunIfaceTotal.operations > 0) { - tmpEntry.operations = - pool.operations * operations[i] / tunIfaceTotal.operations; - } else { - tmpEntry.operations = 0; - } - tmpEntry.uid = uid[i]; - tmpEntry.tag = tag[i]; + if (!Objects.equals(iface[i], tunIface)) { + // Consider only entries that go onto the VPN interface. + continue; + } + if (uid[i] == tunUid) { + // Exclude VPN app from the redistribution, as it can choose to create packet + // streams by writing to itself. + continue; + } + tmpEntry.uid = uid[i]; + tmpEntry.tag = tag[i]; + tmpEntry.metered = metered[i]; + tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; + + // In a first pass, compute each UID's total share of data across all underlyingIfaces. + // This is computed on the basis of the share of each UID's usage over tunIface. + // TODO: Consider refactoring first pass into a separate helper method. + long totalRxBytes = 0; + if (tunIfaceTotal.rxBytes > 0) { + // Note - The multiplication below should not overflow since NetworkStatsService + // processes this every time device has transmitted/received amount equivalent to + // global threshold alert (~ 2MB) across all interfaces. + final long rxBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + // app must not be blamed for more than it consumed on tunIface + totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); + } + long totalRxPackets = 0; + if (tunIfaceTotal.rxPackets > 0) { + final long rxPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); + } + long totalTxBytes = 0; + if (tunIfaceTotal.txBytes > 0) { + final long txBytesAcrossUnderlyingIfaces = + underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); + } + long totalTxPackets = 0; + if (tunIfaceTotal.txPackets > 0) { + final long txPacketsAcrossUnderlyingIfaces = + underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); + } + long totalOperations = 0; + if (tunIfaceTotal.operations > 0) { + final long operationsAcrossUnderlyingIfaces = + underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; + totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); + } + // In a second pass, distribute these values across interfaces in the proportion that + // each interface represents of the total traffic of the underlying interfaces. + for (int j = 0; j < underlyingIfaces.length; j++) { + tmpEntry.iface = underlyingIfaces[j]; + tmpEntry.rxBytes = 0; + // Reset 'set' to correct value since it gets updated when adding debug info below. tmpEntry.set = set[i]; - tmpEntry.metered = metered[i]; - tmpEntry.roaming = roaming[i]; - tmpEntry.defaultNetwork = defaultNetwork[i]; + if (underlyingIfacesTotal.rxBytes > 0) { + tmpEntry.rxBytes = + totalRxBytes + * perInterfaceTotal[j].rxBytes + / underlyingIfacesTotal.rxBytes; + } + tmpEntry.rxPackets = 0; + if (underlyingIfacesTotal.rxPackets > 0) { + tmpEntry.rxPackets = + totalRxPackets + * perInterfaceTotal[j].rxPackets + / underlyingIfacesTotal.rxPackets; + } + tmpEntry.txBytes = 0; + if (underlyingIfacesTotal.txBytes > 0) { + tmpEntry.txBytes = + totalTxBytes + * perInterfaceTotal[j].txBytes + / underlyingIfacesTotal.txBytes; + } + tmpEntry.txPackets = 0; + if (underlyingIfacesTotal.txPackets > 0) { + tmpEntry.txPackets = + totalTxPackets + * perInterfaceTotal[j].txPackets + / underlyingIfacesTotal.txPackets; + } + tmpEntry.operations = 0; + if (underlyingIfacesTotal.operations > 0) { + tmpEntry.operations = + totalOperations + * perInterfaceTotal[j].operations + / underlyingIfacesTotal.operations; + } + combineValues(tmpEntry); if (tag[i] == TAG_NONE) { - moved.add(tmpEntry); + moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; combineValues(tmpEntry); @@ -1311,38 +1396,45 @@ public class NetworkStats implements Parcelable { return moved; } - private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) { - // Add debug info - moved.uid = tunUid; - moved.set = SET_DBG_VPN_OUT; - moved.tag = TAG_NONE; - moved.iface = underlyingIface; - moved.metered = METERED_ALL; - moved.roaming = ROAMING_ALL; - moved.defaultNetwork = DEFAULT_NETWORK_ALL; - combineValues(moved); + private void deductTrafficFromVpnApp( + int tunUid, + @NonNull String[] underlyingIfaces, + @NonNull Entry[] moved) { + for (int i = 0; i < underlyingIfaces.length; i++) { + // Add debug info + moved[i].uid = tunUid; + moved[i].set = SET_DBG_VPN_OUT; + moved[i].tag = TAG_NONE; + moved[i].iface = underlyingIfaces[i]; + moved[i].metered = METERED_ALL; + moved[i].roaming = ROAMING_ALL; + moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; + combineValues(moved[i]); - // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than - // the TAG_NONE traffic. - // - // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO, - // which should be the case as it comes directly from the /proc file. We only blend in the - // roaming data after applying these adjustments, by checking the NetworkIdentity of the - // underlying iface. - int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnBackground != -1) { - tunSubtract(idxVpnBackground, this, moved); - } + // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than + // the TAG_NONE traffic. + // + // Relies on the fact that the underlying traffic only has state ROAMING_NO and + // METERED_NO, which should be the case as it comes directly from the /proc file. + // We only blend in the roaming data after applying these adjustments, by checking the + // NetworkIdentity of the underlying iface. + final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnBackground != -1) { + // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed + // from foreground usage. + tunSubtract(idxVpnBackground, this, moved[i]); + } - int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); - if (idxVpnForeground != -1) { - tunSubtract(idxVpnForeground, this, moved); + final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, + TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); + if (idxVpnForeground != -1) { + tunSubtract(idxVpnForeground, this, moved[i]); + } } } - private static void tunSubtract(int i, NetworkStats left, Entry right) { + private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) { long rxBytes = Math.min(left.rxBytes[i], right.rxBytes); left.rxBytes[i] -= rxBytes; right.rxBytes -= rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a2e7e0cae9..bdff50053f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import libcore.io.IoUtils; - import com.google.android.collect.Sets; +import libcore.io.IoUtils; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.File; @@ -234,7 +234,7 @@ public class NetworkStatsRecorder { if (vpnArray != null) { for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface); + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); } } From a2a478128ef90407a5a94c2826222a53c01839cc Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 11 Jun 2019 18:21:30 -0700 Subject: [PATCH 309/881] Remove unused lastStats parameter This change removes an unused parameter that is always null in getNetworkStatsUidDetail Bug: 113122541 Bug: 134244752 Test: FrameworksNetTest passing Merged-In: I995b108ef30e1fbd6190131ed4db40a3d9327eb5 Change-Id: I575a7e4fa145f2c93537f33a2bfe952aeafd0e69 (cherry picked from commit d9d6958e06b75b295e8a6e5fd21d181783c7ec9d) --- .../server/net/NetworkStatsFactory.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 69efd02dea..c118bda88c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -16,6 +16,7 @@ package com.android.server.net; +import static android.net.NetworkStats.INTERFACES_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; @@ -264,13 +265,21 @@ public class NetworkStatsFactory { } public NetworkStats readNetworkStatsDetail() throws IOException { - return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); + return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); } - public NetworkStats readNetworkStatsDetail(int limitUid, String[] limitIfaces, int limitTag, - NetworkStats lastStats) throws IOException { - final NetworkStats stats = - readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag, lastStats); + /** + * Reads the detailed UID stats based on the provided parameters + * + * @param limitUid the UID to limit this query to + * @param limitIfaces the interfaces to limit this query to. Use {@link + * NetworkStats.INTERFACES_ALL} to select all interfaces + * @param limitTag the tags to limit this query to + * @return the NetworkStats instance containing network statistics at the present time. + */ + public NetworkStats readNetworkStatsDetail( + int limitUid, @Nullable String[] limitIfaces, int limitTag) throws IOException { + final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. // TODO: remove this and only apply adjustments in NetworkStatsService. @@ -292,17 +301,11 @@ public class NetworkStatsFactory { } } - // TODO: delete the lastStats parameter - private NetworkStats readNetworkStatsDetailInternal(int limitUid, String[] limitIfaces, - int limitTag, NetworkStats lastStats) throws IOException { + private NetworkStats readNetworkStatsDetailInternal( + int limitUid, String[] limitIfaces, int limitTag) throws IOException { if (USE_NATIVE_PARSING) { - final NetworkStats stats; - if (lastStats != null) { - stats = lastStats; - stats.setElapsedRealtime(SystemClock.elapsedRealtime()); - } else { - stats = new NetworkStats(SystemClock.elapsedRealtime(), -1); - } + final NetworkStats stats = + new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */); if (mUseBpfStats) { synchronized (mPersistSnapshot) { try { From b0a112857aa259909b7d15fa3233c1df2b4cb5ce Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 12 Jun 2019 17:46:31 +0000 Subject: [PATCH 310/881] NetworkStatsFactory: Take VPNs into account for network/battery stats This change fixes detailed UID stats to ensure network and battery stats both take VPNs into account. NetworkStatsFactory is being made aware of VPNs enabled, and the full set of underlying networks present. Since traffic can only be migrated over a NetworkStats delta, NSF maintains a NetworkStats snapshot across all UIDs/ifaces/tags. This snapshot gets updated whenever NSF records a new snapshot (based on various hooks such as VPN updating its underlying networks, network getting lost, etc.), or NetworkStatsService's getDetailedUidStats() method being called. This change widens the scope of the existing mPersistentSnapshot lock, renaming it to mPersistentDataLock, and ensures that TUN migrations are not done in parallel. Additionally, mVpnInfos is updated via pointer-swapping, to reduce the scope of the mPersistentDataLock. The safety of this change is predicated on: 1. NetworkStatsFactory lock not held, so services cannot deadlock through the cyclical lock. 2. The broadening of the scope of the lock in NetworkStatsFactory has no threading implications, as it is always the last (leaf node) lock held, and therefore is impossible to have lock inversion. Additionally, to ensure VPNs work with 464xlat, the VPN info passed to the NetworkStatsFactory includes all underlying interfaces, instead of only passing the first one. This (partially) re-applies changes from: aosp/972848: Add one more test for VPN usage stats. aosp/972847: Addressing comments for http://ag/7700679. aosp/885338: NetworkStatsService: Fix getDetailedUidStats to take VPNs into account. Co-developed with: Varun Anand Bug: 113122541 Bug: 120145746 Bug: 129264869 Bug: 134244752 Test: FrameworksNetTest passing Test: Manual tests show data usage fixes maintained. Merged-In: I6466ec1411fc5ed6954125d27d353b6cd1be719e Change-Id: Id45ae956ad7165be346ecc010e17d260563ac1c0 (cherry picked from commit 7d5e62485b2025231a206d1833f14019a38f1bbf) --- .../android/net/INetworkStatsService.aidl | 1 - core/java/android/net/NetworkStats.java | 44 ++++-- .../server/net/NetworkStatsFactory.java | 135 +++++++++++++----- .../server/net/NetworkStatsService.java | 28 ++-- 4 files changed, 140 insertions(+), 68 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 41efc50408..e5f3d26667 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -66,7 +66,6 @@ interface INetworkStatsService { /** Force update of ifaces. */ void forceUpdateIfaces( in Network[] defaultNetworks, - in VpnInfo[] vpnArray, in NetworkState[] networkStates, in String activeIface); /** Force update of statistics. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index f09f2ee223..6c7aa1379f 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -23,7 +23,6 @@ import android.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; -import android.util.Slog; import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; @@ -37,6 +36,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.function.Predicate; /** * Collection of active network statistics. Can contain summary details across @@ -994,23 +994,33 @@ public class NetworkStats implements Parcelable { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { return; } + filter(e -> (limitUid == UID_ALL || limitUid == e.uid) + && (limitTag == TAG_ALL || limitTag == e.tag) + && (limitIfaces == INTERFACES_ALL + || ArrayUtils.contains(limitIfaces, e.iface))); + } + /** + * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. + * + *

This mutates the original structure in place. + */ + public void filterDebugEntries() { + filter(e -> e.set < SET_DEBUG_START); + } + + private void filter(Predicate predicate) { Entry entry = new Entry(); int nextOutputEntry = 0; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - final boolean matches = - (limitUid == UID_ALL || limitUid == entry.uid) - && (limitTag == TAG_ALL || limitTag == entry.tag) - && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, entry.iface)); - - if (matches) { - setValues(nextOutputEntry, entry); + if (predicate.test(entry)) { + if (nextOutputEntry != i) { + setValues(nextOutputEntry, entry); + } nextOutputEntry++; } } - size = nextOutputEntry; } @@ -1289,7 +1299,8 @@ public class NetworkStats implements Parcelable { } final Entry tmpEntry = new Entry(); - for (int i = 0; i < size; i++) { + final int origSize = size; + for (int i = 0; i < origSize; i++) { if (!Objects.equals(iface[i], tunIface)) { // Consider only entries that go onto the VPN interface. continue; @@ -1305,8 +1316,9 @@ public class NetworkStats implements Parcelable { tmpEntry.roaming = roaming[i]; tmpEntry.defaultNetwork = defaultNetwork[i]; - // In a first pass, compute each UID's total share of data across all underlyingIfaces. - // This is computed on the basis of the share of each UID's usage over tunIface. + // In a first pass, compute this entry's total share of data across all + // underlyingIfaces. This is computed on the basis of the share of this entry's usage + // over tunIface. // TODO: Consider refactoring first pass into a separate helper method. long totalRxBytes = 0; if (tunIfaceTotal.rxBytes > 0) { @@ -1383,9 +1395,11 @@ public class NetworkStats implements Parcelable { * perInterfaceTotal[j].operations / underlyingIfacesTotal.operations; } - + // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying + // interface. Add that data usage to this object. combineValues(tmpEntry); if (tag[i] == TAG_NONE) { + // Add the migrated data to moved so it is deducted from the VPN app later. moved[j].add(tmpEntry); // Add debug info tmpEntry.set = SET_DBG_VPN_IN; @@ -1401,8 +1415,8 @@ public class NetworkStats implements Parcelable { @NonNull String[] underlyingIfaces, @NonNull Entry[] moved) { for (int i = 0; i < underlyingIfaces.length; i++) { - // Add debug info moved[i].uid = tunUid; + // Add debug info moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; moved[i].iface = underlyingIfaces[i]; diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index c118bda88c..2d3c66d68f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -34,6 +34,7 @@ import android.os.SystemClock; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; @@ -71,11 +72,25 @@ public class NetworkStatsFactory { private INetd mNetdService; - // A persistent Snapshot since device start for eBPF stats - @GuardedBy("mPersistSnapshot") - private final NetworkStats mPersistSnapshot; + /** + * Guards persistent data access in this class + * + *

In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out + * to other code that will acquire other locks within the system server. See b/134244752. + */ + private static final Object sPersistentDataLock = new Object(); + + /** Set containing info about active VPNs and their underlying networks. */ + private static volatile VpnInfo[] sVpnInfos = new VpnInfo[0]; + + // A persistent snapshot of cumulative stats since device start + @GuardedBy("sPersistentDataLock") + private NetworkStats mPersistSnapshot; + + // The persistent snapshot of tun and 464xlat adjusted stats since device start + @GuardedBy("sPersistentDataLock") + private NetworkStats mTunAnd464xlatAdjustedStats; - // TODO: only do adjustments in NetworkStatsService and remove this. /** * (Stacked interface) -> (base interface) association for all connected ifaces since boot. * @@ -91,6 +106,24 @@ public class NetworkStatsFactory { } } + /** + * Set active VPN information for data usage migration purposes + * + *

Traffic on TUN-based VPNs inherently all appear to be originated from the VPN providing + * app's UID. This method is used to support migration of VPN data usage, ensuring data is + * accurately billed to the real owner of the traffic. + * + * @param vpnArray The snapshot of the currently-running VPNs. + */ + public static void updateVpnInfos(VpnInfo[] vpnArray) { + sVpnInfos = vpnArray.clone(); + } + + @VisibleForTesting + public static VpnInfo[] getVpnInfos() { + return sVpnInfos.clone(); + } + /** * Get a set of interfaces containing specified ifaces and stacked interfaces. * @@ -147,6 +180,7 @@ public class NetworkStatsFactory { mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); + mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } public NetworkStats readBpfNetworkStatsDev() throws IOException { @@ -279,16 +313,10 @@ public class NetworkStatsFactory { */ public NetworkStats readNetworkStatsDetail( int limitUid, @Nullable String[] limitIfaces, int limitTag) throws IOException { - final NetworkStats stats = readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); - - // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap. - // TODO: remove this and only apply adjustments in NetworkStatsService. - stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); - - return stats; + return readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); } - @GuardedBy("mPersistSnapshot") + @GuardedBy("sPersistentDataLock") private void requestSwapActiveStatsMapLocked() throws RemoteException { // Ask netd to do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map @@ -303,11 +331,18 @@ public class NetworkStatsFactory { private NetworkStats readNetworkStatsDetailInternal( int limitUid, String[] limitIfaces, int limitTag) throws IOException { - if (USE_NATIVE_PARSING) { - final NetworkStats stats = - new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */); - if (mUseBpfStats) { - synchronized (mPersistSnapshot) { + // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other + // code that will acquire other locks within the system server. See b/134244752. + synchronized (sPersistentDataLock) { + // Take a reference. If this gets swapped out, we still have the old reference. + final VpnInfo[] vpnArray = sVpnInfos; + // Take a defensive copy. mPersistSnapshot is mutated in some cases below + final NetworkStats prev = mPersistSnapshot.clone(); + + if (USE_NATIVE_PARSING) { + final NetworkStats stats = + new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */); + if (mUseBpfStats) { try { requestSwapActiveStatsMapLocked(); } catch (RemoteException e) { @@ -316,32 +351,66 @@ public class NetworkStatsFactory { // Stats are always read from the inactive map, so they must be read after the // swap if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, - null, TAG_ALL, mUseBpfStats) != 0) { + INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) { throw new IOException("Failed to parse network stats"); } + + // BPF stats are incremental; fold into mPersistSnapshot. mPersistSnapshot.setElapsedRealtime(stats.getElapsedRealtime()); mPersistSnapshot.combineAllValues(stats); - NetworkStats result = mPersistSnapshot.clone(); - result.filter(limitUid, limitIfaces, limitTag); - return result; + } else { + if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, + INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) { + throw new IOException("Failed to parse network stats"); + } + if (SANITY_CHECK_NATIVE) { + final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, + UID_ALL, INTERFACES_ALL, TAG_ALL); + assertEquals(javaStats, stats); + } + + mPersistSnapshot = stats; } } else { - if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid, - limitIfaces, limitTag, mUseBpfStats) != 0) { - throw new IOException("Failed to parse network stats"); - } - if (SANITY_CHECK_NATIVE) { - final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid, - limitIfaces, limitTag); - assertEquals(javaStats, stats); - } - return stats; + mPersistSnapshot = javaReadNetworkStatsDetail(mStatsXtUid, UID_ALL, INTERFACES_ALL, + TAG_ALL); } - } else { - return javaReadNetworkStatsDetail(mStatsXtUid, limitUid, limitIfaces, limitTag); + + NetworkStats adjustedStats = adjustForTunAnd464Xlat(mPersistSnapshot, prev, vpnArray); + + // Filter return values + adjustedStats.filter(limitUid, limitIfaces, limitTag); + return adjustedStats; } } + @GuardedBy("sPersistentDataLock") + private NetworkStats adjustForTunAnd464Xlat( + NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) { + // Calculate delta from last snapshot + final NetworkStats delta = uidDetailStats.subtract(previousStats); + + // Apply 464xlat adjustments before VPN adjustments. If VPNs are using v4 on a v6 only + // network, the overhead is their fault. + // No locking here: apply464xlatAdjustments behaves fine with an add-only + // ConcurrentHashMap. + delta.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); + + // Migrate data usage over a VPN to the TUN network. + for (VpnInfo info : vpnArray) { + delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + } + + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); + + // Update mTunAnd464xlatAdjustedStats with migrated delta. + mTunAnd464xlatAdjustedStats.combineAllValues(delta); + mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); + + return mTunAnd464xlatAdjustedStats.clone(); + } + /** * Parse and return {@link NetworkStats} with UID-level details. Values are * expected to monotonically increase since device boot. diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index f34ace55a7..34ce8199a6 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -131,7 +131,6 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; @@ -267,10 +266,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; - /** Set containing info about active VPNs and their underlying networks. */ - @GuardedBy("mStatsLock") - private VpnInfo[] mVpnInfos = new VpnInfo[0]; - private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -864,7 +859,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void forceUpdateIfaces( Network[] defaultNetworks, - VpnInfo[] vpnArray, NetworkState[] networkStates, String activeIface) { checkNetworkStackPermission(mContext); @@ -872,7 +866,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks, vpnArray, networkStates, activeIface); + updateIfaces(defaultNetworks, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1138,13 +1132,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void updateIfaces( Network[] defaultNetworks, - VpnInfo[] vpnArray, NetworkState[] networkStates, String activeIface) { synchronized (mStatsLock) { mWakeLock.acquire(); try { - mVpnInfos = vpnArray; mActiveIface = activeIface; updateIfacesLocked(defaultNetworks, networkStates); } finally { @@ -1154,10 +1146,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Inspect all current {@link NetworkState} to derive mapping from {@code - * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo} - * are active on a single {@code iface}, they are combined under a single - * {@link NetworkIdentitySet}. + * Inspect all current {@link NetworkState} to derive mapping from {@code iface} to {@link + * NetworkStatsHistory}. When multiple {@link NetworkInfo} are active on a single {@code iface}, + * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { @@ -1283,18 +1274,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. - VpnInfo[] vpnArray = mVpnInfos; Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); - mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); + mUidRecorder.recordSnapshotLocked( + uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag"); - mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime); + mUidTagRecorder.recordSnapshotLocked( + uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); // We need to make copies of member fields that are sent to the observer to avoid // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), - new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime); + new ArrayMap<>(mActiveUidIfaces), null /* vpnArray */, currentTime); } /** @@ -1667,8 +1659,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ private NetworkStats getNetworkStatsUidDetail(String[] ifaces) throws RemoteException { - - // TODO: remove 464xlat adjustments from NetworkStatsFactory and apply all at once here. final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL, ifaces); From 6cdb7a879060cdb7df1ef25c8ddcbb34e811bfd8 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 13 Jun 2019 10:54:38 -0700 Subject: [PATCH 311/881] Remove VPN info arrays from NetworkStats(Observer|Recorder) This change removes the now-unused VPN arrays in the network stats observer and recorder classes. These are always null values in every call site. Bug: 113122541 Bug: 120145746 Bug: 129264869 Bug: 134244752 Test: FrameworksNetTest passing Test: Manual tests show data usage fixes maintained. Merged-In: Ieb8645acc400fdaeb0df7092c5369b96f9f35af9 Change-Id: I66f263d7e12bce7668901306c0c2ecdda634abaf (cherry picked from commit f2465f87c20c7618b2727a9e8eab2a4d4559c2ff) --- .../server/net/NetworkStatsObservers.java | 13 +++++------ .../server/net/NetworkStatsRecorder.java | 22 ++++--------------- .../server/net/NetworkStatsService.java | 14 +++++------- 3 files changed, 14 insertions(+), 35 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/services/core/java/com/android/server/net/NetworkStatsObservers.java index d8408730dd..2564daeaa1 100644 --- a/services/core/java/com/android/server/net/NetworkStatsObservers.java +++ b/services/core/java/com/android/server/net/NetworkStatsObservers.java @@ -39,7 +39,6 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.VpnInfo; import java.util.concurrent.atomic.AtomicInteger; @@ -104,9 +103,9 @@ class NetworkStatsObservers { public void updateStats(NetworkStats xtSnapshot, NetworkStats uidSnapshot, ArrayMap activeIfaces, ArrayMap activeUidIfaces, - VpnInfo[] vpnArray, long currentTime) { + long currentTime) { StatsContext statsContext = new StatsContext(xtSnapshot, uidSnapshot, activeIfaces, - activeUidIfaces, vpnArray, currentTime); + activeUidIfaces, currentTime); getHandler().sendMessage(mHandler.obtainMessage(MSG_UPDATE_STATS, statsContext)); } @@ -354,7 +353,7 @@ class NetworkStatsObservers { // thread will update it. We pass a null VPN array because usage is aggregated by uid // for this snapshot, so VPN traffic can't be reattributed to responsible apps. mRecorder.recordSnapshotLocked(statsContext.mXtSnapshot, statsContext.mActiveIfaces, - null /* vpnArray */, statsContext.mCurrentTime); + statsContext.mCurrentTime); } /** @@ -396,7 +395,7 @@ class NetworkStatsObservers { // thread will update it. We pass the VPN info so VPN traffic is reattributed to // responsible apps. mRecorder.recordSnapshotLocked(statsContext.mUidSnapshot, statsContext.mActiveUidIfaces, - statsContext.mVpnArray, statsContext.mCurrentTime); + statsContext.mCurrentTime); } /** @@ -427,18 +426,16 @@ class NetworkStatsObservers { NetworkStats mUidSnapshot; ArrayMap mActiveIfaces; ArrayMap mActiveUidIfaces; - VpnInfo[] mVpnArray; long mCurrentTime; StatsContext(NetworkStats xtSnapshot, NetworkStats uidSnapshot, ArrayMap activeIfaces, ArrayMap activeUidIfaces, - VpnInfo[] vpnArray, long currentTime) { + long currentTime) { mXtSnapshot = xtSnapshot; mUidSnapshot = uidSnapshot; mActiveIfaces = activeIfaces; mActiveUidIfaces = activeUidIfaces; - mVpnArray = vpnArray; mCurrentTime = currentTime; } } diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index bdff50053f..06ec341d9e 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -23,7 +23,6 @@ import static android.text.format.DateUtils.YEAR_IN_MILLIS; import static com.android.internal.util.Preconditions.checkNotNull; -import android.annotation.Nullable; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; @@ -37,7 +36,6 @@ import android.util.MathUtils; import android.util.Slog; import android.util.proto.ProtoOutputStream; -import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; @@ -202,18 +200,12 @@ public class NetworkStatsRecorder { } /** - * Record any delta that occurred since last {@link NetworkStats} snapshot, - * using the given {@link Map} to identify network interfaces. First - * snapshot is considered bootstrap, and is not counted as delta. - * - * @param vpnArray Optional info about the currently active VPN, if any. This is used to - * redistribute traffic from the VPN app to the underlying responsible apps. - * This should always be set to null if the provided snapshot is aggregated - * across all UIDs (e.g. contains UID_ALL buckets), regardless of VPN state. + * Record any delta that occurred since last {@link NetworkStats} snapshot, using the given + * {@link Map} to identify network interfaces. First snapshot is considered bootstrap, and is + * not counted as delta. */ public void recordSnapshotLocked(NetworkStats snapshot, - Map ifaceIdent, @Nullable VpnInfo[] vpnArray, - long currentTimeMillis) { + Map ifaceIdent, long currentTimeMillis) { final HashSet unknownIfaces = Sets.newHashSet(); // skip recording when snapshot missing @@ -232,12 +224,6 @@ public class NetworkStatsRecorder { final long end = currentTimeMillis; final long start = end - delta.getElapsedRealtime(); - if (vpnArray != null) { - for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); - } - } - NetworkStats.Entry entry = null; for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 34ce8199a6..42802f6c3c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1265,28 +1265,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev"); - mDevRecorder.recordSnapshotLocked( - devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime); + mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt"); - mXtRecorder.recordSnapshotLocked( - xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime); + mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); - mUidRecorder.recordSnapshotLocked( - uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); + mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag"); - mUidTagRecorder.recordSnapshotLocked( - uidSnapshot, mActiveUidIfaces, null /* vpnArray */, currentTime); + mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime); Trace.traceEnd(TRACE_TAG_NETWORK); // We need to make copies of member fields that are sent to the observer to avoid // a race condition between the service handler thread and the observer's mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), - new ArrayMap<>(mActiveUidIfaces), null /* vpnArray */, currentTime); + new ArrayMap<>(mActiveUidIfaces), currentTime); } /** From b26dfe9274f2a335ee6e8b1d60c9c16f4eb94a0d Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 20 Jun 2019 14:46:35 -0700 Subject: [PATCH 312/881] Inline readNetworkStatsDetailInternal, make mUseBpfStats final This change inlines the logic from readNetworkStatsDetailInternal, and reduces reundant checks in mUseBpfStats Bug: 113122541 Test: atest FrameworksNetTests run, passing Merged-In: If2ef8d8f038f32c8cf974aa02cfc1dc7e44dbad3 Change-Id: If7d41052115ed145da8a610d676f6ed33c8d5e63 (cherry picked from commit 2cb570ff3651d721d7e8d50504759f04923d5767) --- .../server/net/NetworkStatsFactory.java | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 2d3c66d68f..7687718b06 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -68,7 +68,7 @@ public class NetworkStatsFactory { /** Path to {@code /proc/net/xt_qtaguid/stats}. */ private final File mStatsXtUid; - private boolean mUseBpfStats; + private final boolean mUseBpfStats; private INetd mNetdService; @@ -302,6 +302,17 @@ public class NetworkStatsFactory { return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); } + @GuardedBy("sPersistentDataLock") + private void requestSwapActiveStatsMapLocked() throws RemoteException { + // Ask netd to do a active map stats swap. When the binder call successfully returns, + // the system server should be able to safely read and clean the inactive map + // without race problem. + if (mNetdService == null) { + mNetdService = NetdService.getInstance(); + } + mNetdService.trafficSwapActiveStatsMap(); + } + /** * Reads the detailed UID stats based on the provided parameters * @@ -312,24 +323,6 @@ public class NetworkStatsFactory { * @return the NetworkStats instance containing network statistics at the present time. */ public NetworkStats readNetworkStatsDetail( - int limitUid, @Nullable String[] limitIfaces, int limitTag) throws IOException { - return readNetworkStatsDetailInternal(limitUid, limitIfaces, limitTag); - } - - @GuardedBy("sPersistentDataLock") - private void requestSwapActiveStatsMapLocked() throws RemoteException { - // Ask netd to do a active map stats swap. When the binder call successfully returns, - // the system server should be able to safely read and clean the inactive map - // without race problem. - if (mUseBpfStats) { - if (mNetdService == null) { - mNetdService = NetdService.getInstance(); - } - mNetdService.trafficSwapActiveStatsMap(); - } - } - - private NetworkStats readNetworkStatsDetailInternal( int limitUid, String[] limitIfaces, int limitTag) throws IOException { // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other // code that will acquire other locks within the system server. See b/134244752. From 9d2ff01d46ee408086cd8bab9a285158bb3d4e8d Mon Sep 17 00:00:00 2001 From: Hugo Benichi Date: Wed, 15 May 2019 23:38:43 +0900 Subject: [PATCH 313/881] NetworkStats: Fix race condition causing system server crashes NetworkStatsService uses an internal boolean to know when it has started for the purpose of preventing access to other internal variables before they are initialized. However that boolean is set to true in systemReady() non-atomically with respect to the initialization of the other variables it guards, which can cause the system server to crash. This patch fixes this concurrency bug by moving setting the internal boolean flag and the variable it guards in one atomic synchronized block. This patch also removes code checking if bandwidth control is enabled, because this is now always true. Bug: 132767673 Test: Compiled. Change-Id: Ia089b5767ce271d669879c975508654d4dd03429 --- .../server/net/NetworkStatsService.java | 62 +++---------------- 1 file changed, 10 insertions(+), 52 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 2fc78d6f47..5505828063 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -373,14 +373,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } public void systemReady() { - mSystemReady = true; - - if (!isBandwidthControlEnabled()) { - Slog.w(TAG, "bandwidth controls disabled, unable to track stats"); - return; - } - synchronized (mStatsLock) { + mSystemReady = true; + // create data recorders along with historical rotators mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false); mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false); @@ -426,7 +421,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // ignored; service lives in system_server } - registerPollAlarmLocked(); + // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}. + final PendingIntent pollIntent = + PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); + + final long currentRealtime = SystemClock.elapsedRealtime(); + mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, + mSettings.getPollInterval(), pollIntent); + registerGlobalAlert(); } @@ -486,23 +488,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - /** - * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and - * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}. - */ - private void registerPollAlarmLocked() { - if (mPollIntent != null) { - mAlarmManager.cancel(mPollIntent); - } - - mPollIntent = PendingIntent.getBroadcast( - mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); - - final long currentRealtime = SystemClock.elapsedRealtime(); - mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, - mSettings.getPollInterval(), mPollIntent); - } - /** * Register for a global alert that is delivered through * {@link INetworkManagementEventObserver} once a threshold amount of data @@ -548,8 +533,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { - assertBandwidthControlEnabled(); - final int callingUid = Binder.getCallingUid(); final int usedFlags = isRateLimitedForPoll(callingUid) ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN) @@ -742,7 +725,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { assertSystemReady(); - assertBandwidthControlEnabled(); // NOTE: if callers want to get non-augmented data, they should go // through the public API @@ -753,7 +735,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { assertSystemReady(); - assertBandwidthControlEnabled(); final NetworkStatsCollection uidComplete; synchronized (mStatsLock) { @@ -768,7 +749,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (Binder.getCallingUid() != uid) { mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); } - assertBandwidthControlEnabled(); // TODO: switch to data layer stats once kernel exports // for now, read network layer stats and flatten across all ifaces @@ -855,7 +835,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkState[] networkStates, String activeIface) { checkNetworkStackPermission(mContext); - assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { @@ -868,7 +847,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void forceUpdate() { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); - assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { @@ -879,8 +857,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private void advisePersistThreshold(long thresholdBytes) { - assertBandwidthControlEnabled(); - // clamp threshold into safe range mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES); if (LOGV) { @@ -1739,24 +1715,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - private void assertBandwidthControlEnabled() { - if (!isBandwidthControlEnabled()) { - throw new IllegalStateException("Bandwidth module disabled"); - } - } - - private boolean isBandwidthControlEnabled() { - final long token = Binder.clearCallingIdentity(); - try { - return mNetworkManager.isBandwidthControlEnabled(); - } catch (RemoteException e) { - // ignored; service lives in system_server - return false; - } finally { - Binder.restoreCallingIdentity(token); - } - } - private class DropBoxNonMonotonicObserver implements NonMonotonicObserver { @Override public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right, From 2d876790ebc48e6470172251802bdf7d50950f75 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 24 Jun 2019 12:42:24 +0900 Subject: [PATCH 314/881] Synchronize the NetworkStatsFactory constructor. This ensures the constructor takes the necessary lock before accessing memmber variables. Bug: 113122541 Test: atest FrameworksNetTests Change-Id: Ibd324ed922c738b8d77d4eb74f45b75c6645bdc7 --- .../java/com/android/server/net/NetworkStatsFactory.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 7687718b06..9344ef71c9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -179,8 +179,10 @@ public class NetworkStatsFactory { mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; - mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); - mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); + synchronized (sPersistentDataLock) { + mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); + mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); + } } public NetworkStats readBpfNetworkStatsDev() throws IOException { From e698f37ad27c8157d6e872e03dd8f28a8cf92ae5 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 24 Jun 2019 13:28:04 +0900 Subject: [PATCH 315/881] Transfer ownership of NetworkStatsFactory to NetworkStatsService. NetworkStatsService is the only consumer of the data coming from NetworkStatsFactory, but the factory itself is instantiated and owned by NetworkManagementService. Move it into NetworkStatsService instead. Test: atest FrameworksNetTests Change-Id: I52df1e545c646927952579da22845a12d1d7563b --- .../server/net/NetworkStatsService.java | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 5505828063..e67b39137a 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -180,6 +180,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final Context mContext; private final INetworkManagementService mNetworkManager; + private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; private final Clock mClock; private final TelephonyManager mTeleManager; @@ -329,8 +330,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, wakeLock, getDefaultClock(), TelephonyManager.getDefault(), - new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(), - getDefaultSystemDir(), getDefaultBaseDir()); + new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), + new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); service.registerLocalService(); HandlerThread handlerThread = new HandlerThread(TAG); @@ -347,7 +348,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, TelephonyManager teleManager, NetworkStatsSettings settings, - NetworkStatsObservers statsObservers, File systemDir, File baseDir) { + NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, + File baseDir) { mContext = checkNotNull(context, "missing Context"); mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService"); mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager"); @@ -355,6 +357,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSettings = checkNotNull(settings, "missing NetworkStatsSettings"); mTeleManager = checkNotNull(teleManager, "missing TelephonyManager"); mWakeLock = checkNotNull(wakeLock, "missing WakeLock"); + mStatsFactory = checkNotNull(factory, "missing factory"); mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers"); mSystemDir = checkNotNull(systemDir, "missing systemDir"); mBaseDir = checkNotNull(baseDir, "missing baseDir"); @@ -752,14 +755,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // TODO: switch to data layer stats once kernel exports // for now, read network layer stats and flatten across all ifaces - final long token = Binder.clearCallingIdentity(); - final NetworkStats networkLayer; - try { - networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid, - NetworkStats.INTERFACES_ALL); - } finally { - Binder.restoreCallingIdentity(token); - } + final NetworkStats networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL); // splice in operation counts networkLayer.spliceOperationsFrom(mUidOperations); @@ -1190,7 +1186,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mobileIfaces.add(stackedIface); } - NetworkStatsFactory.noteStackedIface(stackedIface, baseIface); + mStatsFactory.noteStackedIface(stackedIface, baseIface); } } } @@ -1220,7 +1216,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats xtSnapshot = getNetworkStatsXt(); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev"); - final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); + final NetworkStats devSnapshot = readNetworkStatsSummaryDev(); Trace.traceEnd(TRACE_TAG_NETWORK); // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats @@ -1614,6 +1610,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + private NetworkStats readNetworkStatsSummaryDev() { + try { + return mStatsFactory.readNetworkStatsSummaryDev(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + private NetworkStats readNetworkStatsSummaryXt() { + try { + return mStatsFactory.readNetworkStatsSummaryXt(); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + + private NetworkStats readNetworkStatsUidDetail(int uid, String[] ifaces, int tag) { + try { + return mStatsFactory.readNetworkStatsDetail(uid, ifaces, tag); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + /** * Return snapshot of current UID statistics, including any * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations} @@ -1624,8 +1644,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ private NetworkStats getNetworkStatsUidDetail(String[] ifaces) throws RemoteException { - final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL, - ifaces); + final NetworkStats uidSnapshot = readNetworkStatsUidDetail(UID_ALL, ifaces, TAG_ALL); // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); @@ -1655,7 +1674,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Return snapshot of current XT statistics with video calling data usage statistics. */ private NetworkStats getNetworkStatsXt() throws RemoteException { - final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt(); + final NetworkStats xtSnapshot = readNetworkStatsSummaryXt(); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); From 0d09928534a3ff7b57828cdb8b2453d28f18fd38 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 24 Jun 2019 13:50:45 +0900 Subject: [PATCH 316/881] Remove all static members from NetworkStatsFactory. NetworkStatsFactory is owned by NetworkStatsService, and any accesses to NSF data should go through NSS. Test: atest FrameworksNetTests Change-Id: Idbd0dbbaeb11313f63474e7ec0e01f974349fc89 --- .../android/net/INetworkStatsService.aidl | 3 +- .../server/net/NetworkStatsFactory.java | 49 ++++++++----------- .../server/net/NetworkStatsService.java | 15 ++++-- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index e5f3d26667..9994f9f82b 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -67,7 +67,8 @@ interface INetworkStatsService { void forceUpdateIfaces( in Network[] defaultNetworks, in NetworkState[] networkStates, - in String activeIface); + in String activeIface, + in VpnInfo[] vpnInfos); /** Force update of statistics. */ @UnsupportedAppUsage void forceUpdate(); diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 9344ef71c9..3ca1803262 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -78,17 +78,17 @@ public class NetworkStatsFactory { *

In order to prevent deadlocks, critical sections protected by this lock SHALL NOT call out * to other code that will acquire other locks within the system server. See b/134244752. */ - private static final Object sPersistentDataLock = new Object(); + private final Object mPersistentDataLock = new Object(); /** Set containing info about active VPNs and their underlying networks. */ - private static volatile VpnInfo[] sVpnInfos = new VpnInfo[0]; + private volatile VpnInfo[] mVpnInfos = new VpnInfo[0]; // A persistent snapshot of cumulative stats since device start - @GuardedBy("sPersistentDataLock") + @GuardedBy("mPersistentDataLock") private NetworkStats mPersistSnapshot; // The persistent snapshot of tun and 464xlat adjusted stats since device start - @GuardedBy("sPersistentDataLock") + @GuardedBy("mPersistentDataLock") private NetworkStats mTunAnd464xlatAdjustedStats; /** @@ -97,12 +97,13 @@ public class NetworkStatsFactory { * Because counters must never roll backwards, once a given interface is stacked on top of an * underlying interface, the stacked interface can never be stacked on top of * another interface. */ - private static final ConcurrentHashMap sStackedIfaces + private final ConcurrentHashMap mStackedIfaces = new ConcurrentHashMap<>(); - public static void noteStackedIface(String stackedIface, String baseIface) { + /** Informs the factory of a new stacked interface. */ + public void noteStackedIface(String stackedIface, String baseIface) { if (stackedIface != null && baseIface != null) { - sStackedIfaces.put(stackedIface, baseIface); + mStackedIfaces.put(stackedIface, baseIface); } } @@ -115,13 +116,8 @@ public class NetworkStatsFactory { * * @param vpnArray The snapshot of the currently-running VPNs. */ - public static void updateVpnInfos(VpnInfo[] vpnArray) { - sVpnInfos = vpnArray.clone(); - } - - @VisibleForTesting - public static VpnInfo[] getVpnInfos() { - return sVpnInfos.clone(); + public void updateVpnInfos(VpnInfo[] vpnArray) { + mVpnInfos = vpnArray.clone(); } /** @@ -132,7 +128,7 @@ public class NetworkStatsFactory { * {@link #noteStackedIface(String, String)}, but only interfaces noted before this method * is called are guaranteed to be included. */ - public static String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { + public String[] augmentWithStackedInterfaces(@Nullable String[] requiredIfaces) { if (requiredIfaces == NetworkStats.INTERFACES_ALL) { return null; } @@ -142,7 +138,7 @@ public class NetworkStatsFactory { // elements as they existed upon construction exactly once, and may // (but are not guaranteed to) reflect any modifications subsequent to construction". // This is enough here. - for (Map.Entry entry : sStackedIfaces.entrySet()) { + for (Map.Entry entry : mStackedIfaces.entrySet()) { if (relatedIfaces.contains(entry.getKey())) { relatedIfaces.add(entry.getValue()); } else if (relatedIfaces.contains(entry.getValue())) { @@ -158,17 +154,12 @@ public class NetworkStatsFactory { * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) */ - public static void apply464xlatAdjustments(NetworkStats baseTraffic, + public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic, boolean useBpfStats) { - NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces, + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces, useBpfStats); } - @VisibleForTesting - public static void clearStackedIfaces() { - sStackedIfaces.clear(); - } - public NetworkStatsFactory() { this(new File("/proc/"), new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists()); } @@ -179,7 +170,7 @@ public class NetworkStatsFactory { mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; - synchronized (sPersistentDataLock) { + synchronized (mPersistentDataLock) { mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } @@ -304,7 +295,7 @@ public class NetworkStatsFactory { return readNetworkStatsDetail(UID_ALL, INTERFACES_ALL, TAG_ALL); } - @GuardedBy("sPersistentDataLock") + @GuardedBy("mPersistentDataLock") private void requestSwapActiveStatsMapLocked() throws RemoteException { // Ask netd to do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map @@ -328,9 +319,9 @@ public class NetworkStatsFactory { int limitUid, String[] limitIfaces, int limitTag) throws IOException { // In order to prevent deadlocks, anything protected by this lock MUST NOT call out to other // code that will acquire other locks within the system server. See b/134244752. - synchronized (sPersistentDataLock) { + synchronized (mPersistentDataLock) { // Take a reference. If this gets swapped out, we still have the old reference. - final VpnInfo[] vpnArray = sVpnInfos; + final VpnInfo[] vpnArray = mVpnInfos; // Take a defensive copy. mPersistSnapshot is mutated in some cases below final NetworkStats prev = mPersistSnapshot.clone(); @@ -379,7 +370,7 @@ public class NetworkStatsFactory { } } - @GuardedBy("sPersistentDataLock") + @GuardedBy("mPersistentDataLock") private NetworkStats adjustForTunAnd464Xlat( NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) { // Calculate delta from last snapshot @@ -389,7 +380,7 @@ public class NetworkStatsFactory { // network, the overhead is their fault. // No locking here: apply464xlatAdjustments behaves fine with an add-only // ConcurrentHashMap. - delta.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats); + delta.apply464xlatAdjustments(mStackedIfaces, mUseBpfStats); // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index e67b39137a..4f4377df09 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -130,6 +130,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; @@ -777,7 +778,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStats getDetailedUidStats(String[] requiredIfaces) { try { final String[] ifacesToQuery = - NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces); + mStatsFactory.augmentWithStackedInterfaces(requiredIfaces); return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); @@ -829,7 +830,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void forceUpdateIfaces( Network[] defaultNetworks, NetworkState[] networkStates, - String activeIface) { + String activeIface, + VpnInfo[] vpnInfos) { checkNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); @@ -838,6 +840,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } finally { Binder.restoreCallingIdentity(token); } + + // Update the VPN underlying interfaces only after the poll is made and tun data has been + // migrated. Otherwise the migration would use the new interfaces instead of the ones that + // were current when the polled data was transferred. + mStatsFactory.updateVpnInfos(vpnInfos); } @Override @@ -1649,7 +1656,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, + mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, mUseBpfTrafficStats); uidSnapshot.combineAllValues(tetherSnapshot); @@ -1660,7 +1667,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { vtStats.filter(UID_ALL, ifaces, TAG_ALL); - NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, + mStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, mUseBpfTrafficStats); uidSnapshot.combineAllValues(vtStats); } From 1c2d5c79e5ccd63ecba008a9bb34bc2262aba521 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 28 Jun 2019 16:47:49 +0800 Subject: [PATCH 317/881] Fix mobile data usage didn't get increased for xlat464 traffic Interface stats on stacked interfaces is usually clatd. For xt_qtaguid supported device, the stats is already accounted against its final egress interface by the kernel. Framework side does not need to handle stats on statcked interface at all. However, on devices that support BPF offload, xlat464 packets are seen by the iptables rules as arriving on stack interface only. Thus, add stack interface into accounting is needed. Bug: 136193260 Test: 1. atest FrameworksNetTests 2. atest android.app.usage.cts.NetworkUsageStatsTest 3. manual test on ipv6-only wifi network Change-Id: I8ebbefbe4df00e40f4896a17fa52c8438d41286e --- .../android/server/net/NetworkStatsService.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4f4377df09..90dc700e7d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1180,14 +1180,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - // Traffic occurring on stacked interfaces is usually clatd, - // which is already accounted against its final egress interface - // by the kernel. Thus, we only need to collect stacked - // interface stats at the UID level. + // Traffic occurring on stacked interfaces is usually clatd. + // UID stats are always counted on the stacked interface and never + // on the base interface, because the packets on the base interface + // do not actually match application sockets until they are translated. + // + // Interface stats are more complicated. Packets subject to BPF offload + // never appear on the base interface and only appear on the stacked + // interface, so to ensure those packets increment interface stats, interface + // stats from stacked interfaces must be collected. final List stackedLinks = state.linkProperties.getStackedLinks(); for (LinkProperties stackedLink : stackedLinks) { final String stackedIface = stackedLink.getInterfaceName(); if (stackedIface != null) { + if (mUseBpfTrafficStats) { + findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); + } findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); if (isMobile) { mobileIfaces.add(stackedIface); From c873970a8850b8cb981bd4bd93075b59a11dc1dc Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 28 Jun 2019 16:47:49 +0800 Subject: [PATCH 318/881] Fix mobile data usage didn't get increased for xlat464 traffic Interface stats on stacked interfaces is usually clatd. For xt_qtaguid supported device, the stats is already accounted against its final egress interface by the kernel. Framework side does not need to handle stats on statcked interface at all. However, on devices that support BPF offload, xlat464 packets are seen by the iptables rules as arriving on stack interface only. Thus, add stack interface into accounting is needed. Bug: 136193260 Test: 1. atest FrameworksNetTests 2. atest android.app.usage.cts.NetworkUsageStatsTest 3. manual test on ipv6-only wifi network Merged-In: I8ebbefbe4df00e40f4896a17fa52c8438d41286e Change-Id: I8ebbefbe4df00e40f4896a17fa52c8438d41286e (cherry-pick from aosp/1009306) --- .../android/server/net/NetworkStatsService.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 42802f6c3c..d1b5534e37 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1208,14 +1208,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - // Traffic occurring on stacked interfaces is usually clatd, - // which is already accounted against its final egress interface - // by the kernel. Thus, we only need to collect stacked - // interface stats at the UID level. + // Traffic occurring on stacked interfaces is usually clatd. + // UID stats are always counted on the stacked interface and never + // on the base interface, because the packets on the base interface + // do not actually match application sockets until they are translated. + // + // Interface stats are more complicated. Packets subject to BPF offload + // never appear on the base interface and only appear on the stacked + // interface, so to ensure those packets increment interface stats, interface + // stats from stacked interfaces must be collected. final List stackedLinks = state.linkProperties.getStackedLinks(); for (LinkProperties stackedLink : stackedLinks) { final String stackedIface = stackedLink.getInterfaceName(); if (stackedIface != null) { + if (mUseBpfTrafficStats) { + findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); + } findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); if (isMobile) { mobileIfaces.add(stackedIface); From 7d62dacad0bb324be3bd0ebde8370e3da4672520 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 28 Jun 2019 16:47:49 +0800 Subject: [PATCH 319/881] Fix mobile data usage didn't get increased for xlat464 traffic Interface stats on stacked interfaces is usually clatd. For xt_qtaguid supported device, the stats is already accounted against its final egress interface by the kernel. Framework side does not need to handle stats on statcked interface at all. However, on devices that support BPF offload, xlat464 packets are seen by the iptables rules as arriving on stack interface only. Thus, add stack interface into accounting is needed. Bug: 136193260 Test: 1. atest FrameworksNetTests 2. atest android.app.usage.cts.NetworkUsageStatsTest 3. manual test on ipv6-only wifi network Merged-In: I8ebbefbe4df00e40f4896a17fa52c8438d41286e Change-Id: I8ebbefbe4df00e40f4896a17fa52c8438d41286e (cherry-pick from aosp/1009306) (cherry picked from commit feb79bd0d7c5ecc7ac5ba9f54ed2d51ee9fd7e74) --- .../android/server/net/NetworkStatsService.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index f34ace55a7..e0692f698b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1217,14 +1217,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - // Traffic occurring on stacked interfaces is usually clatd, - // which is already accounted against its final egress interface - // by the kernel. Thus, we only need to collect stacked - // interface stats at the UID level. + // Traffic occurring on stacked interfaces is usually clatd. + // UID stats are always counted on the stacked interface and never + // on the base interface, because the packets on the base interface + // do not actually match application sockets until they are translated. + // + // Interface stats are more complicated. Packets subject to BPF offload + // never appear on the base interface and only appear on the stacked + // interface, so to ensure those packets increment interface stats, interface + // stats from stacked interfaces must be collected. final List stackedLinks = state.linkProperties.getStackedLinks(); for (LinkProperties stackedLink : stackedLinks) { final String stackedIface = stackedLink.getInterfaceName(); if (stackedIface != null) { + if (mUseBpfTrafficStats) { + findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); + } findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); if (isMobile) { mobileIfaces.add(stackedIface); From c42bd04cae6b5b494bdcca490070783749dd8114 Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Tue, 2 Jul 2019 22:29:35 -0700 Subject: [PATCH 320/881] Use new API to get mergedSubscriberIds based on grouping. In addition, make mMergedSubscriberIds a list to fit usage of multi-SIM devices. Bug: 135105735 Bug: 137137221 Test: manual Change-Id: I364262559789112f35b88f4c298463bf4af2e82a --- core/java/android/net/NetworkTemplate.java | 37 ++++++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index ae421a4991..87c7118c0e 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -48,6 +48,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; +import java.util.List; import java.util.Objects; /** @@ -481,17 +482,39 @@ public class NetworkTemplate implements Parcelable { * For example, given an incoming template matching B, and the currently * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. + * TODO: remove and use {@link #normalize(NetworkTemplate, List)}. */ @UnsupportedAppUsage public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { - if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) { - // Requested template subscriber is part of the merge group; return - // a template that matches all merged subscribers. - return new NetworkTemplate(template.mMatchRule, merged[0], merged, - template.mNetworkId); - } else { - return template; + return normalize(template, Arrays.asList(merged)); + } + + /** + * Examine the given template and normalize if it refers to a "merged" + * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * for key purposes, and expand the template to match all other merged + * subscribers. + * + * There can be multiple merged subscriberIds for multi-SIM devices. + * + *

+ * For example, given an incoming template matching B, and the currently + * active merge set [A,B], we'd return a new template that primarily matches + * A, but also matches B. + */ + public static NetworkTemplate normalize(NetworkTemplate template, List mergedList) { + if (!template.isMatchRuleMobile()) return template; + + for (String[] merged : mergedList) { + if (ArrayUtils.contains(merged, template.mSubscriberId)) { + // Requested template subscriber is part of the merge group; return + // a template that matches all merged subscribers. + return new NetworkTemplate(template.mMatchRule, merged[0], merged, + template.mNetworkId); + } } + + return template; } @UnsupportedAppUsage From 3f5be3d04a218d40cd2eaeb4803739a1641b2a94 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 13 Jun 2019 16:12:02 +0900 Subject: [PATCH 321/881] Extract test utilities for ConnectivityService The utilities help using ConnectivityService in tests, and will be used to write integration tests for ConnectivityService. Test: atest FrameworksNetTests Change-Id: Ie895ad05139cd5768d3d8a9bd5589d72571f47e6 --- services/core/java/com/android/server/IpSecService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index b4e1c32f25..a0946a0d22 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -750,10 +750,10 @@ public class IpSecService extends IIpSecService.Stub { } } - // These values have been reserved in ConnectivityService + // These values have been reserved in NetIdManager @VisibleForTesting static final int TUN_INTF_NETID_START = 0xFC00; - @VisibleForTesting static final int TUN_INTF_NETID_RANGE = 0x0400; + public static final int TUN_INTF_NETID_RANGE = 0x0400; private final SparseBooleanArray mTunnelNetIds = new SparseBooleanArray(); private int mNextTunnelNetIdIndex = 0; From 561d712f8645d872f355deb014c806e3511fb02b Mon Sep 17 00:00:00 2001 From: paulhu Date: Thu, 22 Aug 2019 16:03:59 +0800 Subject: [PATCH 322/881] [Ethernet] Replace internal connectivity checks permission A number of connectivity checks that protect system-only methods check for CONNECTIVITY_INTERNAL, but CONNECTIVITY_INTERNAL is a signature|privileged permission. We should audit the permissions checks, and convert checks that protect code that should not be called outside the system to a signature permission. So replace the permission to NETWORK_STACK. Bug: 32963470 Test: atest EthernetServiceTests Change-Id: I2a88d04bbdcd7e7e624b9065372a6603d2bb45a2 --- .../com/android/server/ethernet/EthernetServiceImpl.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index d5beec1cb4..fda3c3c2f9 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -21,6 +21,7 @@ import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; import android.net.IpConfiguration; +import android.net.NetworkStack; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; @@ -57,12 +58,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { "EthernetService"); } - private void enforceConnectivityInternalPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_INTERNAL, - "ConnectivityService"); - } - private void enforceUseRestrictedNetworksPermission() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS, @@ -117,7 +112,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Log.w(TAG, "System isn't ready enough to change ethernet configuration"); } - enforceConnectivityInternalPermission(); + NetworkStack.checkNetworkStackPermission(mContext); if (mTracker.isRestrictedInterface(iface)) { enforceUseRestrictedNetworksPermission(); From e0073b10536002306eef2050cf67755a104bc0bb Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Wed, 28 Aug 2019 13:01:05 -0700 Subject: [PATCH 323/881] Add missing nullability annotations. To prepare for enabling MissingNullability Metalava check this CL works on adding missing nullability issues that metalava flags if we tell it to flag new things since API 29. This is not a complete CL, mostly addresses public api and toString/equals for @SystemApi Exempt-From-Owner-Approval: Large scale nullability clean up Bug: 124515653 Test: make -j checkapi Merged-In: I109260842cfc25f06e40694997fcbb4afa02c867 Change-Id: I109260842cfc25f06e40694997fcbb4afa02c867 --- core/java/android/net/IpSecManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 83813da80c..45d0c7313f 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -861,6 +861,7 @@ public final class IpSecManager { return mResourceId; } + @NonNull @Override public String toString() { return new StringBuilder() From 925cff0b81877398764c24e81f3db433b6f055d6 Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Wed, 28 Aug 2019 13:01:05 -0700 Subject: [PATCH 324/881] Add missing nullability annotations. To prepare for enabling MissingNullability Metalava check this CL works on adding missing nullability issues that metalava flags if we tell it to flag new things since API 29. This is not a complete CL, mostly addresses public api and toString/equals for @SystemApi Exempt-From-Owner-Approval: Large scale nullability clean up Bug: 124515653 Test: make -j checkapi Change-Id: I109260842cfc25f06e40694997fcbb4afa02c867 --- core/java/android/net/IpSecManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 83813da80c..45d0c7313f 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -861,6 +861,7 @@ public final class IpSecManager { return mResourceId; } + @NonNull @Override public String toString() { return new StringBuilder() From d8d521aeeeb12aec148f58d198ccadaaf7c0ab83 Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Wed, 28 Aug 2019 13:01:05 -0700 Subject: [PATCH 325/881] Add missing nullability annotations. To prepare for enabling MissingNullability Metalava check this CL works on adding missing nullability issues that metalava flags if we tell it to flag new things since API 29. This is not a complete CL, mostly addresses public api and toString/equals for @SystemApi Exempt-From-Owner-Approval: Large scale nullability clean up Bug: 124515653 Test: make -j checkapi Merged-In: I109260842cfc25f06e40694997fcbb4afa02c867 Change-Id: I109260842cfc25f06e40694997fcbb4afa02c867 --- core/java/android/net/IpSecManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 889e9bc787..2262a04647 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -853,6 +853,7 @@ public final class IpSecManager { return mResourceId; } + @NonNull @Override public String toString() { return new StringBuilder() From a184f6e4b85ec87bd276ec004aa8de6b1b0ecbc8 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 2 May 2018 21:36:12 +0900 Subject: [PATCH 326/881] Update Ethernet code for the NetworkFactory serial number. See aosp/708790 Bug: 18637384 Bug: 29030667 Test: manual cts runtest framework-net atest frameworks/opt/net/ethernet/tests Change-Id: I5caa4cb89ca1441f3c84b5675ceede6ecacfd132 --- .../android/server/ethernet/EthernetNetworkFactory.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index e3f114ed21..3cda13f330 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -157,7 +157,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } NetworkInterfaceState iface = new NetworkInterfaceState( - ifaceName, hwAddress, mHandler, mContext, capabilities); + ifaceName, hwAddress, mHandler, mContext, capabilities, this); iface.setIpConfig(ipConfiguration); mTrackingInterfaces.put(ifaceName, iface); @@ -248,6 +248,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private final Handler mHandler; private final Context mContext; private final NetworkInfo mNetworkInfo; + private final NetworkFactory mNetworkFactory; private static String sTcpBufferSizes = null; // Lazy initialized. @@ -356,13 +357,15 @@ public class EthernetNetworkFactory extends NetworkFactory { } NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, - @NonNull NetworkCapabilities capabilities) { + @NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory) { name = ifaceName; mCapabilities = checkNotNull(capabilities); mHandler = handler; mContext = context; + mNetworkFactory = networkFactory; int legacyType = ConnectivityManager.TYPE_NONE; int[] transportTypes = mCapabilities.getTransportTypes(); + if (transportTypes.length > 0) { legacyType = getLegacyType(transportTypes[0]); } else { @@ -471,7 +474,7 @@ public class EthernetNetworkFactory extends NetworkFactory { // Create our NetworkAgent. mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties, - getNetworkScore()) { + getNetworkScore(), mNetworkFactory.getSerialNumber()) { public void unwanted() { if (this == mNetworkAgent) { stop(); From 1678614ca751a1574609150901278573fd3824fd Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 3 Oct 2019 11:09:00 -0700 Subject: [PATCH 327/881] Use TransformRecord to get SPI instead of SpiRecord IpSecService.applyTunnelModeTransform() currently does not take an SpiRecord instance, yet implicitly requires that the SpiRecord instance is still alive based on the stored SpiRecord resourceId in the TransformRecord's IpSecConfig. This check is unnecessary, as the SpiRecord has been subsumed into the TransformRecord, and the kernel resources are kept alive whether or not the SpiRecord is still held by the user. This allows users of the IpSecManager API to allocate short-lived SPIs during the creation of an IpSecTransform, without having to keep track of both of them (even though the SPI is no longer usable). The TransformRecord.getSpiRecord() call is already used in multiple other places in the same method. Bug: 142072071 Test: New tests added, passing. Change-Id: I1959f3080946267243564459ff4207647922566e --- services/core/java/com/android/server/IpSecService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index a629b3fbb8..3964b39970 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1761,7 +1761,7 @@ public class IpSecService extends IIpSecService.Stub { socketRecord = userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId()); } - SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId()); + SpiRecord spiRecord = transformInfo.getSpiRecord(); int mark = (direction == IpSecManager.DIRECTION_OUT) @@ -1794,7 +1794,7 @@ public class IpSecService extends IIpSecService.Stub { // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys, // but want to guarantee outbound packets are sent over the new SA. - spi = transformInfo.getSpiRecord().getSpi(); + spi = spiRecord.getSpi(); } // Always update the policy with the relevant XFRM_IF_ID From df6e0241b4eee35ac720591bb506d1f699d48547 Mon Sep 17 00:00:00 2001 From: kevinwk_lee Date: Fri, 18 Oct 2019 11:25:29 +0800 Subject: [PATCH 328/881] Avoid creating IpClient if ethernet cable is unplugged. This change avoids calling start() on needNetworkFor() if ethernet cable is unplugged. Fixed by adding isLinkUp validation. Test: ./cts-tradefed run cts-dev -d -m CtsSecurityTestCases -t \ android.security.cts.ListeningPortsTest#testNoRemotelyAccessibleListeningUdpPorts adb shell netstat -lnup Change-Id: I2debd7367a20b665249f9c19d2d8a61737435803 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 3cda13f330..090dd13f4f 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -226,7 +226,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } } else { for (NetworkInterfaceState n : mTrackingInterfaces.values()) { - if (n.statisified(request.networkCapabilities)) { + if (n.statisified(request.networkCapabilities) && n.mLinkUp) { network = n; break; } From 504a98af330ee5a632705ea1822abd579709aac1 Mon Sep 17 00:00:00 2001 From: Joshua Baxter Date: Wed, 6 Nov 2019 00:05:24 +0000 Subject: [PATCH 329/881] docs: fix a couple of minor typos test: make ds-docs Change-Id: Ia68f66980e447209efb8102a156f78314c199f56 bug: 36979979 Exempt-From-Owner-Approval: docs-only change --- core/java/android/net/nsd/NsdManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 535bf675cd..64f20b839a 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -49,8 +49,8 @@ import java.util.concurrent.CountDownLatch; * limited to a local network over Multicast DNS. DNS service discovery is described at * http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt * - *

The API is asynchronous and responses to requests from an application are on listener - * callbacks on a seperate internal thread. + *

The API is asynchronous, and responses to requests from an application are on listener + * callbacks on a separate internal thread. * *

There are three main operations the API supports - registration, discovery and resolution. *


From fead53a3a5df976a14a4ae5b6ea2b5c1a021bfde Mon Sep 17 00:00:00 2001
From: Artur Satayev 
Date: Mon, 4 Nov 2019 11:16:45 +0000
Subject: [PATCH 330/881] Add @UnsupportedAppUsage to test apis that are known
 to be used by apps.

go/testapi-enforcement

Bug: 133832325
Test: m
Change-Id: Ifc8db120640a1554dcbf1722e61e09c7ddc65dd6
Merged-In: Ifc8db120640a1554dcbf1722e61e09c7ddc65dd6
---
 core/java/android/app/usage/NetworkStatsManager.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 8e40449fa5..6bade90182 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -146,6 +146,7 @@ public class NetworkStatsManager {
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     @TestApi
     public void setPollForce(boolean pollForce) {
         if (pollForce) {

From 39b880fb0859dbdf9055882367a1a9ada91c2c17 Mon Sep 17 00:00:00 2001
From: Artur Satayev 
Date: Thu, 31 Oct 2019 15:15:50 +0000
Subject: [PATCH 331/881] Add @UnsupportedAppUsage to test apis that are known
 to be used by apps.

go/testapi-enforcement

Bug: 133832325
Test: m
Change-Id: Ifc8db120640a1554dcbf1722e61e09c7ddc65dd6
Merged-In: Ifc8db120640a1554dcbf1722e61e09c7ddc65dd6
---
 core/java/android/app/usage/NetworkStatsManager.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 8e40449fa5..6bade90182 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -146,6 +146,7 @@ public class NetworkStatsManager {
     }
 
     /** @hide */
+    @UnsupportedAppUsage
     @TestApi
     public void setPollForce(boolean pollForce) {
         if (pollForce) {

From 3e5af51f7c3b6036c4fb73a6c780b0bdaec673f2 Mon Sep 17 00:00:00 2001
From: Jayachandran C 
Date: Fri, 15 Nov 2019 09:58:04 -0800
Subject: [PATCH 332/881] Remove usage of Telephonymanager getDefault() and
 from() hidden APIs

This CL replaces with getSystemService(TelephonyManager.class)

Bug: 140768340
Test: atest frameworks/base/tests/net
Change-Id: I0f14cc5440fa85c81ab90f3199e9e91c1b00f5e1
---
 .../core/java/com/android/server/net/NetworkStatsService.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 41806cabef..08c94267e9 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -337,7 +337,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
                 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
 
         NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
-                wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
+                wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class),
                 new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(),
                 new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir());
         service.registerLocalService();

From ada48c4ecd5ff70bcea4f38d99750297bd45c31e Mon Sep 17 00:00:00 2001
From: Jayachandran C 
Date: Mon, 25 Nov 2019 15:16:05 -0800
Subject: [PATCH 333/881] Remove usage of hidden API
 TelephonyManager.getNetworkTypeName(int)

This CL deletes the reference to this API as its used in a dead code
which is used for debugging only.

Bug: 140908357
Test: Build
Change-Id: I9fa1996ab5fdb5ab884128d06c2e92bab164dea7
---
 core/java/android/net/NetworkIdentity.java | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index ce2de8554d..febc730480 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -25,7 +25,6 @@ import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Build;
 import android.service.NetworkIdentityProto;
-import android.telephony.TelephonyManager;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
@@ -98,8 +97,6 @@ public class NetworkIdentity implements Comparable {
         builder.append(", subType=");
         if (COMBINE_SUBTYPE_ENABLED) {
             builder.append("COMBINED");
-        } else if (ConnectivityManager.isNetworkTypeMobile(mType)) {
-            builder.append(TelephonyManager.getNetworkTypeName(mSubType));
         } else {
             builder.append(mSubType);
         }

From 904f511b91ce2b179692c32c2cc9f484ec07c4c1 Mon Sep 17 00:00:00 2001
From: markchien 
Date: Mon, 30 Sep 2019 14:40:57 +0800
Subject: [PATCH 334/881] [Tether07] Migrate Tethering into module

Now tethering would be run in dedicated service.
TetheringManager is the interface used to communicate with
TetheringService. The new call flow would be: ConnectivityManager
-> ConnectivityService -> TetheringManager -> TetheringService.
Note: the return value of #tether(), #untether() and #setUsbTethering()
APIs would always be no error. Client can use #getLastTetherError()
or #getTetheredIfaces or listen tether state change to check
status of corresponding interface.

Bug: 136040414
Bug: 144742179
Test: -build, flash, boot
      -atest TetheringTests
      -atest FrameworksNetTests

Change-Id: I7e78c0e0a3e70f940a749ba2a39ece7c7ec5b9b3
---
 .../core/java/com/android/server/net/NetworkStatsService.java    | 1 -
 1 file changed, 1 deletion(-)

diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 08c94267e9..e473c96980 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -138,7 +138,6 @@ import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
-import com.android.server.connectivity.Tethering;
 
 import java.io.File;
 import java.io.FileDescriptor;

From a2f6c26b7dda29a10193ecfe1e5bc6553ed74174 Mon Sep 17 00:00:00 2001
From: markchien 
Date: Mon, 30 Sep 2019 14:40:57 +0800
Subject: [PATCH 335/881] [Tether07] Migrate Tethering into module

Now tethering would be run in dedicated service.
TetheringManager is the interface used to communicate with
TetheringService. The new call flow would be: ConnectivityManager
-> ConnectivityService -> TetheringManager -> TetheringService.
Note: the return value of #tether(), #untether() and #setUsbTethering()
APIs would always be no error. Client can use #getLastTetherError()
or #getTetheredIfaces or listen tether state change to check
status of corresponding interface.

Bug: 136040414
Bug: 144742179
Test: -build, flash, boot
      -atest TetheringTests
      -atest FrameworksNetTests

Change-Id: I7e78c0e0a3e70f940a749ba2a39ece7c7ec5b9b3
Merged-In: I7e78c0e0a3e70f940a749ba2a39ece7c7ec5b9b3
---
 .../core/java/com/android/server/net/NetworkStatsService.java    | 1 -
 1 file changed, 1 deletion(-)

diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 08c94267e9..e473c96980 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -138,7 +138,6 @@ import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
-import com.android.server.connectivity.Tethering;
 
 import java.io.File;
 import java.io.FileDescriptor;

From 912724932c0ec2cd8d839fb6e7f03c24c5f63be7 Mon Sep 17 00:00:00 2001
From: paulhu 
Date: Mon, 12 Aug 2019 16:25:11 +0800
Subject: [PATCH 336/881] Replace the permission of internal connectivity
 checks

A number of connectivity checks that protect system-only methods
check for CONNECTIVITY_INTERNAL, but CONNECTIVITY_INTERNAL is a
signature|privileged permission. We should audit the permission
checks, and convert checks that protect code that should not be
called outside the system to a signature permission. So replace
all CONNECTIVITY_INTERNAL to other proper permissions.

Bug: 32963470
Test: atest FrameworksNetTests NetworkPolicyManagerServiceTest
Change-Id: I8f2dd1cd0609056494eaf612d39820e273ae093f
Merged-In: I8f2dd1cd0609056494eaf612d39820e273ae093f
---
 .../java/com/android/server/NsdService.java   | 25 ++++++++-----------
 .../server/net/NetworkStatsService.java       |  6 ++---
 2 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 3efef017d2..b9b7bf73c1 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -16,19 +16,18 @@
 
 package com.android.server;
 
-import android.content.Context;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.database.ContentObserver;
+import android.net.NetworkStack;
 import android.net.Uri;
-import android.net.nsd.NsdServiceInfo;
 import android.net.nsd.DnsSdTxtRecord;
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
-import android.os.Binder;
-import android.os.HandlerThread;
+import android.net.nsd.NsdServiceInfo;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.UserHandle;
@@ -38,6 +37,12 @@ import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.net.InetAddress;
@@ -45,13 +50,6 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.concurrent.CountDownLatch;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Protocol;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
 /**
  * Network Service Discovery Service handles remote service discovery operation requests by
  * implementing the INsdManager interface.
@@ -565,8 +563,7 @@ public class NsdService extends INsdManager.Stub {
     }
 
     public void setEnabled(boolean isEnabled) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL,
-                "NsdService");
+        NetworkStack.checkNetworkStackPermission(mContext);
         mNsdSettings.putEnabledStatus(isEnabled);
         notifyEnabled(isEnabled);
     }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index e473c96980..16424f2fef 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -17,7 +17,6 @@
 package com.android.server.net;
 
 import static android.Manifest.permission.ACCESS_NETWORK_STATE;
-import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.content.Intent.ACTION_SHUTDOWN;
 import static android.content.Intent.ACTION_UID_REMOVED;
@@ -91,6 +90,7 @@ import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkIdentity;
 import android.net.NetworkInfo;
+import android.net.NetworkStack;
 import android.net.NetworkState;
 import android.net.NetworkStats;
 import android.net.NetworkStats.NonMonotonicObserver;
@@ -1020,8 +1020,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
     private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and verified CONNECTIVITY_INTERNAL
-            // permission above.
             performPoll(FLAG_PERSIST_NETWORK);
         }
     };
@@ -1095,7 +1093,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
         @Override
         public void limitReached(String limitName, String iface) {
             // only someone like NMS should be calling us
-            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+            NetworkStack.checkNetworkStackPermission(mContext);
 
             if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
                 // kick off background poll to collect network stats unless there is already

From 4d138ce23347aed3e2c39fed6ce553d2c8b97d39 Mon Sep 17 00:00:00 2001
From: paulhu 
Date: Mon, 12 Aug 2019 16:25:11 +0800
Subject: [PATCH 337/881] Replace the permission of internal connectivity
 checks

A number of connectivity checks that protect system-only methods
check for CONNECTIVITY_INTERNAL, but CONNECTIVITY_INTERNAL is a
signature|privileged permission. We should audit the permission
checks, and convert checks that protect code that should not be
called outside the system to a signature permission. So replace
all CONNECTIVITY_INTERNAL to other proper permissions.

Bug: 32963470
Test: atest FrameworksNetTests NetworkPolicyManagerServiceTest
Change-Id: I8f2dd1cd0609056494eaf612d39820e273ae093f
---
 .../java/com/android/server/NsdService.java   | 25 ++++++++-----------
 .../server/net/NetworkStatsService.java       |  6 ++---
 2 files changed, 13 insertions(+), 18 deletions(-)

diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 3efef017d2..b9b7bf73c1 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -16,19 +16,18 @@
 
 package com.android.server;
 
-import android.content.Context;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.database.ContentObserver;
+import android.net.NetworkStack;
 import android.net.Uri;
-import android.net.nsd.NsdServiceInfo;
 import android.net.nsd.DnsSdTxtRecord;
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
-import android.os.Binder;
-import android.os.HandlerThread;
+import android.net.nsd.NsdServiceInfo;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.UserHandle;
@@ -38,6 +37,12 @@ import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.net.InetAddress;
@@ -45,13 +50,6 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.concurrent.CountDownLatch;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
-import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Protocol;
-import com.android.internal.util.State;
-import com.android.internal.util.StateMachine;
-
 /**
  * Network Service Discovery Service handles remote service discovery operation requests by
  * implementing the INsdManager interface.
@@ -565,8 +563,7 @@ public class NsdService extends INsdManager.Stub {
     }
 
     public void setEnabled(boolean isEnabled) {
-        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL,
-                "NsdService");
+        NetworkStack.checkNetworkStackPermission(mContext);
         mNsdSettings.putEnabledStatus(isEnabled);
         notifyEnabled(isEnabled);
     }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index e473c96980..16424f2fef 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -17,7 +17,6 @@
 package com.android.server.net;
 
 import static android.Manifest.permission.ACCESS_NETWORK_STATE;
-import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
 import static android.content.Intent.ACTION_SHUTDOWN;
 import static android.content.Intent.ACTION_UID_REMOVED;
@@ -91,6 +90,7 @@ import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkIdentity;
 import android.net.NetworkInfo;
+import android.net.NetworkStack;
 import android.net.NetworkState;
 import android.net.NetworkStats;
 import android.net.NetworkStats.NonMonotonicObserver;
@@ -1020,8 +1020,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
     private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // on background handler thread, and verified CONNECTIVITY_INTERNAL
-            // permission above.
             performPoll(FLAG_PERSIST_NETWORK);
         }
     };
@@ -1095,7 +1093,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
         @Override
         public void limitReached(String limitName, String iface) {
             // only someone like NMS should be calling us
-            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+            NetworkStack.checkNetworkStackPermission(mContext);
 
             if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
                 // kick off background poll to collect network stats unless there is already

From 5d4c651bdf7f08ce5955a9d94bd29772a74f05ef Mon Sep 17 00:00:00 2001
From: Jeffrey Huang 
Date: Thu, 5 Dec 2019 11:28:11 -0800
Subject: [PATCH 338/881] Rename writeToProto to be dumpDebug

We want to eventually migrate some of these APIs to be @SystemApi for mainline modules.
The #dumpDebug name is more appropriate than #writeToProto.

Bug: 142279786
Test: Manual
Change-Id: I60793e91cedf6b720d4ecef6a8484f4fed4ff30f
---
 core/java/android/net/NetworkIdentity.java         |  2 +-
 core/java/android/net/NetworkStatsHistory.java     | 14 +++++++-------
 .../com/android/server/net/NetworkIdentitySet.java |  4 ++--
 .../android/server/net/NetworkStatsCollection.java |  6 +++---
 .../android/server/net/NetworkStatsRecorder.java   |  4 ++--
 .../android/server/net/NetworkStatsService.java    | 10 +++++-----
 6 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index febc730480..c1198aac27 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -114,7 +114,7 @@ public class NetworkIdentity implements Comparable {
         return builder.append("}").toString();
     }
 
-    public void writeToProto(ProtoOutputStream proto, long tag) {
+    public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
 
         proto.write(NetworkIdentityProto.TYPE, mType);
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index f61260ee3e..d96d2ee481 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -684,7 +684,7 @@ public class NetworkStatsHistory implements Parcelable {
         }
     }
 
-    public void writeToProto(ProtoOutputStream proto, long tag) {
+    public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
 
         proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration);
@@ -693,11 +693,11 @@ public class NetworkStatsHistory implements Parcelable {
             final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS);
 
             proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS, bucketStart[i]);
-            writeToProto(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i);
-            writeToProto(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i);
-            writeToProto(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i);
-            writeToProto(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i);
-            writeToProto(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i);
+            dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i);
+            dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i);
+            dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i);
+            dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i);
+            dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i);
 
             proto.end(startBucket);
         }
@@ -705,7 +705,7 @@ public class NetworkStatsHistory implements Parcelable {
         proto.end(start);
     }
 
-    private static void writeToProto(ProtoOutputStream proto, long tag, long[] array, int index) {
+    private static void dumpDebug(ProtoOutputStream proto, long tag, long[] array, int index) {
         if (array != null) {
             proto.write(tag, array[index]);
         }
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
index 68cd5e7aed..2326ad39fd 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java
@@ -170,11 +170,11 @@ public class NetworkIdentitySet extends HashSet implements
         return ident.compareTo(anotherIdent);
     }
 
-    public void writeToProto(ProtoOutputStream proto, long tag) {
+    public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
 
         for (NetworkIdentity ident : this) {
-            ident.writeToProto(proto, NetworkIdentitySetProto.IDENTITIES);
+            ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES);
         }
 
         proto.end(start);
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index ab525237db..05ab2ae87a 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -687,7 +687,7 @@ public class NetworkStatsCollection implements FileRotator.Reader {
         }
     }
 
-    public void writeToProto(ProtoOutputStream proto, long tag) {
+    public void dumpDebug(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
 
         for (Key key : getSortedKeys()) {
@@ -695,7 +695,7 @@ public class NetworkStatsCollection implements FileRotator.Reader {
 
             // Key
             final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY);
-            key.ident.writeToProto(proto, NetworkStatsCollectionKeyProto.IDENTITY);
+            key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY);
             proto.write(NetworkStatsCollectionKeyProto.UID, key.uid);
             proto.write(NetworkStatsCollectionKeyProto.SET, key.set);
             proto.write(NetworkStatsCollectionKeyProto.TAG, key.tag);
@@ -703,7 +703,7 @@ public class NetworkStatsCollection implements FileRotator.Reader {
 
             // Value
             final NetworkStatsHistory history = mStats.get(key);
-            history.writeToProto(proto, NetworkStatsCollectionStatsProto.HISTORY);
+            history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY);
             proto.end(startStats);
         }
 
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 06ec341d9e..6af962bbcc 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -470,12 +470,12 @@ public class NetworkStatsRecorder {
         }
     }
 
-    public void writeToProtoLocked(ProtoOutputStream proto, long tag) {
+    public void dumpDebugLocked(ProtoOutputStream proto, long tag) {
         final long start = proto.start(tag);
         if (mPending != null) {
             proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES, mPending.getTotalBytes());
         }
-        getOrLoadCompleteLocked().writeToProto(proto, NetworkStatsRecorderProto.COMPLETE_HISTORY);
+        getOrLoadCompleteLocked().dumpDebug(proto, NetworkStatsRecorderProto.COMPLETE_HISTORY);
         proto.end(start);
     }
 
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 16424f2fef..673e8302a4 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1609,10 +1609,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
 
         dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces);
         dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces);
-        mDevRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
-        mXtRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
-        mUidRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
-        mUidTagRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS);
+        mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
+        mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
+        mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
+        mUidTagRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS);
 
         proto.flush();
     }
@@ -1623,7 +1623,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
             final long start = proto.start(tag);
 
             proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i));
-            ifaces.valueAt(i).writeToProto(proto, NetworkInterfaceProto.IDENTITIES);
+            ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES);
 
             proto.end(start);
         }

From b0db4fdb6543812fb0bb4af3bf0f98d89bb646bf Mon Sep 17 00:00:00 2001
From: Aaron Huang 
Date: Fri, 27 Sep 2019 22:31:22 +0800
Subject: [PATCH 339/881] Add TrafficStats methods to public APIs

Add methods to public APIs for mainline support.

Bug: 139268426
Bug: 135998869
Test: atest FrameworksNetTests
      ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh
      atest android.net.cts
      atest android.net.wifi.cts

Change-Id: I21a9c0dbdc79b1f1041fc9e23c6a4e1e97ecde92
---
 core/java/android/net/TrafficStats.java | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 1c6a48434a..bf4884aa96 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -595,8 +596,15 @@ public class TrafficStats {
         return total;
     }
 
-    /** {@hide} */
-    public static long getTxPackets(String iface) {
+    /**
+     * Return the number of packets transmitted on the specified interface since
+     * device boot. Statistics are measured at the network layer, so both TCP and
+     * UDP usage are included.
+     *
+     * @param iface The name of the interface.
+     * @return The number of transmitted packets.
+     */
+    public static long getTxPackets(@NonNull String iface) {
         try {
             return getStatsService().getIfaceStats(iface, TYPE_TX_PACKETS);
         } catch (RemoteException e) {
@@ -604,8 +612,15 @@ public class TrafficStats {
         }
     }
 
-    /** {@hide} */
-    public static long getRxPackets(String iface) {
+    /**
+     * Return the number of packets received on the specified interface since
+     * device boot. Statistics are measured at the network layer, so both TCP
+     * and UDP usage are included.
+     *
+     * @param iface The name of the interface.
+     * @return The number of received packets.
+     */
+    public static long getRxPackets(@NonNull String iface) {
         try {
             return getStatsService().getIfaceStats(iface, TYPE_RX_PACKETS);
         } catch (RemoteException e) {

From e5f206dc0fde56a231f146b3613286a7258d4917 Mon Sep 17 00:00:00 2001
From: Junaid Babu 
Date: Tue, 17 Dec 2019 13:56:26 +0900
Subject: [PATCH 340/881] Fix refCount check at releaseNetworkFor

When releaseNetworkFor is called, refCount should be equal to 1 for
network.stop() to be called. This is the same logic that is followed by
WifiNetworkFactory also.
In the current code, when refCount is 2 and releaseNetworkFor() is called,
network.stop() will be executed and will stop Ethernet

Bug: 146089778
Test: build and boot OK
Change-Id: Ib7d1b488a2943364a8ba4a89eec5de4c33cf1d5a
---
 .../com/android/server/ethernet/EthernetNetworkFactory.java   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index 3cda13f330..11c991d408 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -120,11 +120,11 @@ public class EthernetNetworkFactory extends NetworkFactory {
     protected void releaseNetworkFor(NetworkRequest networkRequest) {
         NetworkInterfaceState network = networkForRequest(networkRequest);
         if (network == null) {
-            Log.e(TAG, "needNetworkFor, failed to get a network for " + networkRequest);
+            Log.e(TAG, "releaseNetworkFor, failed to get a network for " + networkRequest);
             return;
         }
 
-        if (--network.refCount == 1) {
+        if (--network.refCount == 0) {
             network.stop();
         }
     }

From e5eb786c463f8c78898e6663ae7debe7c92d774c Mon Sep 17 00:00:00 2001
From: junyulai 
Date: Fri, 6 Dec 2019 18:50:41 +0800
Subject: [PATCH 341/881] Update interface quota limit when network stats
 updated

In previous design, interface quota limit does not changed
when network stats are updated. However, this is incorrect
today since there are some offloaded traffic that cannot
be seen by kernel. If the limit is not updated, the offloaded
traffic might still be able to use whole quota as if there is
no embedded traffic.

This change also removes the re-arm global alert after
advising persist threshold if not changed, given that it will
cause an additional alert while updating interface quota limit.

Bug: 145792619
Test: 1. atest NetworkStatsServiceTest
      2. atest NetworkPolicyManagerServiceTest
      3. manual test: run speedtest, check dumpsys netd

Change-Id: I8d2203e713730d536430a234b1aa8b2468badee3
---
 .../java/com/android/server/net/NetworkStatsService.java   | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 16424f2fef..a943e77284 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -873,6 +873,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
                     + mPersistThreshold);
         }
 
+        final long oldGlobalAlertBytes = mGlobalAlertBytes;
+
         // update and persist if beyond new thresholds
         final long currentTime = mClock.millis();
         synchronized (mStatsLock) {
@@ -886,8 +888,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
             mUidTagRecorder.maybePersistLocked(currentTime);
         }
 
-        // re-arm global alert
-        registerGlobalAlert();
+        if (oldGlobalAlertBytes != mGlobalAlertBytes) {
+            registerGlobalAlert();
+        }
     }
 
     @Override

From efd5607e471ac023fedc94033f10fdc234dfcaff Mon Sep 17 00:00:00 2001
From: Artur Satayev 
Date: Tue, 10 Dec 2019 17:47:51 +0000
Subject: [PATCH 342/881] Use new UnsupportedAppUsage annotation.

Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library.

Bug: 145132366
Test: m && diff unsupportedappusage_index.csv
Change-Id: I8789f8499d4dca08580672e9e45ed9a7026dd686
---
 core/java/android/app/usage/NetworkStatsManager.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 6bade90182..74129702b4 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -21,8 +21,8 @@ import static com.android.internal.util.Preconditions.checkNotNull;
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
 import android.app.usage.NetworkStats.Bucket;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.DataUsageRequest;

From d70aacdd3bfc85a71caf2d80689173df1872fe68 Mon Sep 17 00:00:00 2001
From: Artur Satayev 
Date: Tue, 10 Dec 2019 17:47:53 +0000
Subject: [PATCH 343/881] Use new UnsupportedAppUsage annotation.

Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library.

Bug: 145132366
Test: m && diff unsupportedappusage_index.csv
Change-Id: I534e3fd1305e2f4af076986770033478448a665c
---
 core/java/android/net/nsd/NsdServiceInfo.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 459b140980..0946499f16 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -17,13 +17,13 @@
 package android.net.nsd;
 
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
-import android.os.Parcelable;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Base64;
 import android.util.Log;
-import android.util.ArrayMap;
 
 import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;

From b874007169a536c58de0f53ee5063fa78c571ed7 Mon Sep 17 00:00:00 2001
From: Daulet Zhanguzin 
Date: Mon, 30 Dec 2019 15:41:28 +0000
Subject: [PATCH 344/881] Replace
 com.android.internal.util.Preconditions.checkNotNull with
 java.util.Objects.requireNonNull

Bug: 126528330

Test: Treehugger
Change-Id: I42117ebfb640e3b0b133183e5e146860bed8471a
---
 core/java/android/app/usage/NetworkStatsManager.java | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 74129702b4..4346d9738e 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -16,8 +16,6 @@
 
 package android.app.usage;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -42,6 +40,8 @@ import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.util.Objects;
+
 /**
  * Provides access to network usage history and statistics. Usage data is collected in
  * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
@@ -418,7 +418,7 @@ public class NetworkStatsManager {
     /** @hide */
     public void registerUsageCallback(NetworkTemplate template, int networkType,
             long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
-        checkNotNull(callback, "UsageCallback cannot be null");
+        Objects.requireNonNull(callback, "UsageCallback cannot be null");
 
         final Looper looper;
         if (handler == null) {

From 4c1c7d1a8d52c121becc6939e252341a4775383c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= 
Date: Mon, 30 Dec 2019 07:51:27 -0800
Subject: [PATCH 345/881] remove spurious 'struct' on Stats
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Test: builds, atest
Bug: 146787904
Signed-off-by: Maciej Żenczykowski 
Change-Id: I824daf0ebdddbac1b11cabfcb248ee4134586768
---
 .../com_android_server_net_NetworkStatsService.cpp   | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 4d4a7b4164..740c618317 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -54,7 +54,7 @@ enum StatsType {
     TCP_TX_PACKETS = 5
 };
 
-static uint64_t getStatsType(struct Stats* stats, StatsType type) {
+static uint64_t getStatsType(Stats* stats, StatsType type) {
     switch (type) {
         case RX_BYTES:
             return stats->rxBytes;
@@ -73,7 +73,7 @@ static uint64_t getStatsType(struct Stats* stats, StatsType type) {
     }
 }
 
-static int parseIfaceStats(const char* iface, struct Stats* stats) {
+static int parseIfaceStats(const char* iface, Stats* stats) {
     FILE *fp = fopen(QTAGUID_IFACE_STATS, "r");
     if (fp == NULL) {
         return -1;
@@ -117,7 +117,7 @@ static int parseIfaceStats(const char* iface, struct Stats* stats) {
     return 0;
 }
 
-static int parseUidStats(const uint32_t uid, struct Stats* stats) {
+static int parseUidStats(const uint32_t uid, Stats* stats) {
     FILE *fp = fopen(QTAGUID_UID_STATS, "r");
     if (fp == NULL) {
         return -1;
@@ -150,7 +150,7 @@ static int parseUidStats(const uint32_t uid, struct Stats* stats) {
 }
 
 static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
-    struct Stats stats;
+    Stats stats;
     memset(&stats, 0, sizeof(Stats));
 
     if (useBpfStats) {
@@ -175,7 +175,7 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
         return UNKNOWN;
     }
 
-    struct Stats stats;
+    Stats stats;
     memset(&stats, 0, sizeof(Stats));
 
     if (useBpfStats) {
@@ -194,7 +194,7 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
 }
 
 static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
-    struct Stats stats;
+    Stats stats;
     memset(&stats, 0, sizeof(Stats));
 
     if (useBpfStats) {

From 0f8521ff0afbad1b303e34f77dbcf10422b9d0c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= 
Date: Mon, 30 Dec 2019 07:54:22 -0800
Subject: [PATCH 346/881] convert 'Stats stats; memset(&stats, 0,
 sizeof(Stats));' to 'Stats stats = {};'
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Not only is it more concise, but it's also just a tad more correct:
since it really should have been 'sizeof(stats)' not 'sizeof(Stats)'.

Test: builds, atest
Bug: 146787904
Signed-off-by: Maciej Żenczykowski 
Change-Id: I6cf0295878c7b34cedfe3ae44ff7410ef419f8b9
---
 .../jni/com_android_server_net_NetworkStatsService.cpp   | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 740c618317..4696dd0bb8 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -150,8 +150,7 @@ static int parseUidStats(const uint32_t uid, Stats* stats) {
 }
 
 static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
-    Stats stats;
-    memset(&stats, 0, sizeof(Stats));
+    Stats stats = {};
 
     if (useBpfStats) {
         if (bpfGetIfaceStats(NULL, &stats) == 0) {
@@ -175,8 +174,7 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
         return UNKNOWN;
     }
 
-    Stats stats;
-    memset(&stats, 0, sizeof(Stats));
+    Stats stats = {};
 
     if (useBpfStats) {
         if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
@@ -194,8 +192,7 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
 }
 
 static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
-    Stats stats;
-    memset(&stats, 0, sizeof(Stats));
+    Stats stats = {};
 
     if (useBpfStats) {
         if (bpfGetUidStats(uid, &stats) == 0) {

From f1cf57d37fa98a52a018f7fd0a2d0a76b9e4c104 Mon Sep 17 00:00:00 2001
From: Daulet Zhanguzin 
Date: Fri, 3 Jan 2020 13:37:24 +0000
Subject: [PATCH 347/881] Replace
 com.android.internal.util.Preconditions.checkNotNull with
 java.util.Objects.requireNonNull

Bug: 126528330

Test: Treehugger
Change-Id: I978d5d0959f7800e859bfb384458ba52adc0c2b0
---
 .../server/net/NetworkStatsRecorder.java      | 23 ++++++-----
 .../server/net/NetworkStatsService.java       | 39 ++++++++++---------
 2 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 06ec341d9e..a94a2f79ab 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -21,8 +21,6 @@ import static android.net.TrafficStats.KB_IN_BYTES;
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.text.format.DateUtils.YEAR_IN_MILLIS;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.net.NetworkStats;
 import android.net.NetworkStats.NonMonotonicObserver;
 import android.net.NetworkStatsHistory;
@@ -54,6 +52,7 @@ import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Logic to record deltas between periodic {@link NetworkStats} snapshots into
@@ -116,9 +115,9 @@ public class NetworkStatsRecorder {
      */
     public NetworkStatsRecorder(FileRotator rotator, NonMonotonicObserver observer,
             DropBoxManager dropBox, String cookie, long bucketDuration, boolean onlyTags) {
-        mRotator = checkNotNull(rotator, "missing FileRotator");
-        mObserver = checkNotNull(observer, "missing NonMonotonicObserver");
-        mDropBox = checkNotNull(dropBox, "missing DropBoxManager");
+        mRotator = Objects.requireNonNull(rotator, "missing FileRotator");
+        mObserver = Objects.requireNonNull(observer, "missing NonMonotonicObserver");
+        mDropBox = Objects.requireNonNull(dropBox, "missing DropBoxManager");
         mCookie = cookie;
 
         mBucketDuration = bucketDuration;
@@ -165,7 +164,7 @@ public class NetworkStatsRecorder {
      * as reference is valid.
      */
     public NetworkStatsCollection getOrLoadCompleteLocked() {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
         if (res == null) {
             res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE);
@@ -175,7 +174,7 @@ public class NetworkStatsRecorder {
     }
 
     public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         NetworkStatsCollection res = mComplete != null ? mComplete.get() : null;
         if (res == null) {
             res = loadLocked(start, end);
@@ -280,7 +279,7 @@ public class NetworkStatsRecorder {
      * {@link #mPersistThresholdBytes}.
      */
     public void maybePersistLocked(long currentTimeMillis) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         final long pendingBytes = mPending.getTotalBytes();
         if (pendingBytes >= mPersistThresholdBytes) {
             forcePersistLocked(currentTimeMillis);
@@ -293,7 +292,7 @@ public class NetworkStatsRecorder {
      * Force persisting any pending deltas.
      */
     public void forcePersistLocked(long currentTimeMillis) {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
         if (mPending.isDirty()) {
             if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie);
             try {
@@ -356,7 +355,7 @@ public class NetworkStatsRecorder {
         private final NetworkStatsCollection mCollection;
 
         public CombiningRewriter(NetworkStatsCollection collection) {
-            mCollection = checkNotNull(collection, "missing NetworkStatsCollection");
+            mCollection = Objects.requireNonNull(collection, "missing NetworkStatsCollection");
         }
 
         @Override
@@ -418,7 +417,7 @@ public class NetworkStatsRecorder {
     }
 
     public void importLegacyNetworkLocked(File file) throws IOException {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
 
         // legacy file still exists; start empty to avoid double importing
         mRotator.deleteAll();
@@ -438,7 +437,7 @@ public class NetworkStatsRecorder {
     }
 
     public void importLegacyUidLocked(File file) throws IOException {
-        checkNotNull(mRotator, "missing FileRotator");
+        Objects.requireNonNull(mRotator, "missing FileRotator");
 
         // legacy file still exists; start empty to avoid double importing
         mRotator.deleteAll();
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index a943e77284..a41fb7d327 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -65,7 +65,6 @@ import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
@@ -148,6 +147,7 @@ import java.time.ZoneOffset;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Collect and persist detailed network statistics, and provide this data to
@@ -357,17 +357,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
             TelephonyManager teleManager, NetworkStatsSettings settings,
             NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
             File baseDir) {
-        mContext = checkNotNull(context, "missing Context");
-        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
-        mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
-        mClock = checkNotNull(clock, "missing Clock");
-        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
-        mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
-        mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
-        mStatsFactory = checkNotNull(factory, "missing factory");
-        mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers");
-        mSystemDir = checkNotNull(systemDir, "missing systemDir");
-        mBaseDir = checkNotNull(baseDir, "missing baseDir");
+        mContext = Objects.requireNonNull(context, "missing Context");
+        mNetworkManager = Objects.requireNonNull(networkManager,
+            "missing INetworkManagementService");
+        mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
+        mClock = Objects.requireNonNull(clock, "missing Clock");
+        mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
+        mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager");
+        mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
+        mStatsFactory = Objects.requireNonNull(factory, "missing factory");
+        mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
+        mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
+        mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
         mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists();
     }
 
@@ -896,11 +897,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
     @Override
     public DataUsageRequest registerUsageCallback(String callingPackage,
                 DataUsageRequest request, Messenger messenger, IBinder binder) {
-        checkNotNull(callingPackage, "calling package is null");
-        checkNotNull(request, "DataUsageRequest is null");
-        checkNotNull(request.template, "NetworkTemplate is null");
-        checkNotNull(messenger, "messenger is null");
-        checkNotNull(binder, "binder is null");
+        Objects.requireNonNull(callingPackage, "calling package is null");
+        Objects.requireNonNull(request, "DataUsageRequest is null");
+        Objects.requireNonNull(request.template, "NetworkTemplate is null");
+        Objects.requireNonNull(messenger, "messenger is null");
+        Objects.requireNonNull(binder, "binder is null");
 
         int callingUid = Binder.getCallingUid();
         @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
@@ -921,7 +922,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
 
     @Override
     public void unregisterUsageRequest(DataUsageRequest request) {
-        checkNotNull(request, "DataUsageRequest is null");
+        Objects.requireNonNull(request, "DataUsageRequest is null");
 
         int callingUid = Binder.getCallingUid();
         final long token = Binder.clearCallingIdentity();
@@ -1795,7 +1796,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
         private final ContentResolver mResolver;
 
         public DefaultNetworkStatsSettings(Context context) {
-            mResolver = checkNotNull(context.getContentResolver());
+            mResolver = Objects.requireNonNull(context.getContentResolver());
             // TODO: adjust these timings for production builds
         }
 

From d482d27a8d4240b0276c9346098aa0837e5a74ff Mon Sep 17 00:00:00 2001
From: Daulet Zhanguzin 
Date: Fri, 3 Jan 2020 09:46:50 +0000
Subject: [PATCH 348/881] Replace
 com.android.internal.util.Preconditions.checkNotNull with
 java.util.Objects.requireNonNull

Bug: 126528330

Test: Treehugger
Exempt-From-Owner-Approval: Global refactoring.
Change-Id: Idb1b6ba41af3b52f3376b1157259af3c30328c4e
---
 .../java/com/android/server/IpSecService.java | 19 +++++++++----------
 .../android/server/NativeDaemonConnector.java |  3 ++-
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index a629b3fbb8..c98762074b 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -25,8 +25,6 @@ import static android.system.OsConstants.EINVAL;
 import static android.system.OsConstants.IPPROTO_UDP;
 import static android.system.OsConstants.SOCK_DGRAM;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.Context;
@@ -76,6 +74,7 @@ import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * A service to manage multiple clients that want to access the IpSec API. The service is
@@ -566,7 +565,7 @@ public class IpSecService extends IIpSecService.Stub {
         }
 
         void put(int key, RefcountedResource obj) {
-            checkNotNull(obj, "Null resources cannot be added");
+            Objects.requireNonNull(obj, "Null resources cannot be added");
             mArray.put(key, obj);
         }
 
@@ -1101,7 +1100,7 @@ public class IpSecService extends IIpSecService.Stub {
         if (requestedSpi > 0 && requestedSpi < 256) {
             throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255.");
         }
-        checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
+        Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex");
 
         int callingUid = Binder.getCallingUid();
         UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
@@ -1218,7 +1217,7 @@ public class IpSecService extends IIpSecService.Stub {
             throw new IllegalArgumentException(
                     "Specified port number must be a valid non-reserved UDP port");
         }
-        checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
+        Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket");
 
         int callingUid = Binder.getCallingUid();
         UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid);
@@ -1278,8 +1277,8 @@ public class IpSecService extends IIpSecService.Stub {
             String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder,
             String callingPackage) {
         enforceTunnelFeatureAndPermissions(callingPackage);
-        checkNotNull(binder, "Null Binder passed to createTunnelInterface");
-        checkNotNull(underlyingNetwork, "No underlying network was specified");
+        Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface");
+        Objects.requireNonNull(underlyingNetwork, "No underlying network was specified");
         checkInetAddress(localAddr);
         checkInetAddress(remoteAddr);
 
@@ -1556,7 +1555,7 @@ public class IpSecService extends IIpSecService.Stub {
                     "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS");
         }
 
-        checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
+        Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels");
         switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
             case AppOpsManager.MODE_DEFAULT:
                 mContext.enforceCallingOrSelfPermission(
@@ -1625,12 +1624,12 @@ public class IpSecService extends IIpSecService.Stub {
     @Override
     public synchronized IpSecTransformResponse createTransform(
             IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException {
-        checkNotNull(c);
+        Objects.requireNonNull(c);
         if (c.getMode() == IpSecTransform.MODE_TUNNEL) {
             enforceTunnelFeatureAndPermissions(callingPackage);
         }
         checkIpSecConfig(c);
-        checkNotNull(binder, "Null Binder passed to createTransform");
+        Objects.requireNonNull(binder, "Null Binder passed to createTransform");
         final int resourceId = mNextResourceId++;
 
         UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid());
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index ad02aad6e4..eac767f735 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -46,6 +46,7 @@ import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.LinkedList;
+import java.util.Objects;
 
 /**
  * Generic connector class for interfacing with a native daemon which uses the
@@ -126,7 +127,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
      */
     public void setWarnIfHeld(Object warnIfHeld) {
         Preconditions.checkState(mWarnIfHeld == null);
-        mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld);
+        mWarnIfHeld = Objects.requireNonNull(warnIfHeld);
     }
 
     @Override

From 725ce2f6c62b59d911e92ae430602f4c3a0443a4 Mon Sep 17 00:00:00 2001
From: Artur Satayev 
Date: Tue, 10 Dec 2019 17:47:52 +0000
Subject: [PATCH 349/881] Use new UnsupportedAppUsage annotation.

Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library.

Bug: 145132366
Test: m && diff unsupportedappusage_index.csv
Change-Id: I0c336de56bc4a041dc97ff9b7927f62f0b44b457
---
 core/java/android/net/EthernetManager.java     | 2 +-
 core/java/android/net/NetworkStats.java        | 2 +-
 core/java/android/net/NetworkStatsHistory.java | 2 +-
 core/java/android/net/NetworkTemplate.java     | 2 +-
 core/java/android/net/TrafficStats.java        | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 72565024d3..fd015b4fe5 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -17,7 +17,7 @@
 package android.net;
 
 import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 6c7aa1379f..45bf4d2e13 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -19,7 +19,7 @@ package android.net;
 import static android.os.Process.CLAT_UID;
 
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index d96d2ee481..6d46c205b2 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -30,7 +30,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
 import static com.android.internal.util.ArrayUtils.total;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.NetworkStatsHistoryBucketProto;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 87c7118c0e..5e6c47a47a 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,7 +34,7 @@ import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.wifi.WifiInfo.removeDoubleQuotes;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.BackupUtils;
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index bf4884aa96..162d6e27bd 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -20,10 +20,10 @@ import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
 import android.app.DownloadManager;
 import android.app.backup.BackupManager;
 import android.app.usage.NetworkStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.MediaPlayer;
 import android.os.Build;

From 2b30a23147d134924c7c23d91dce5669cda8ae76 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= 
Date: Mon, 30 Dec 2019 11:41:41 -0800
Subject: [PATCH 350/881] minor change to keep it building
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is part of 3 commits in 3 diff git repos, the main one is:
  https://android-review.googlesource.com/c/platform/system/netd/+/1200479
  "share eBPF struct definitions between ebpf and C++ netd"

as a side effect of which 'android::bpf::Stats' becomes simply '::Stats'

Test: builds
Bug: 146787904
Signed-off-by: Maciej Żenczykowski 
Change-Id: I8548b27d1d8a7938f96c9fd9a185dae882e406f6
---
 services/core/jni/com_android_server_net_NetworkStatsService.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 4696dd0bb8..0275f3ea32 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -33,7 +33,6 @@
 #include "bpf/BpfUtils.h"
 #include "netdbpf/BpfNetworkStats.h"
 
-using android::bpf::Stats;
 using android::bpf::bpfGetUidStats;
 using android::bpf::bpfGetIfaceStats;
 

From fb65456372ecc114eaefef4ef338119f1c6154c0 Mon Sep 17 00:00:00 2001
From: markchien 
Date: Fri, 6 Dec 2019 15:24:53 +0800
Subject: [PATCH 351/881] Fix some @hide usage in Tethering

Using alternative way to replace some @hide API.

Bug: 144814072
Test: build, flash, boot
      atest TetheringTests

Change-Id: I1e12d69db1ad91dff553e142e17c6a70808e1639
---
 .../net/util/TetheringMessageBase.java        | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 packages/Tethering/src/android/net/util/TetheringMessageBase.java

diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
new file mode 100644
index 0000000000..1b763ce920
--- /dev/null
+++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.util;
+
+/**
+ * This class defines Message.what base addresses for various state machine.
+ */
+public class TetheringMessageBase {
+    public static final int BASE_MASTER   = 0;
+    public static final int BASE_IPSERVER = 100;
+
+}

From af1eb472bf2ec4d91a3efdcdb5475b02e3ca0f7b Mon Sep 17 00:00:00 2001
From: Artur Satayev 
Date: Tue, 10 Dec 2019 17:47:52 +0000
Subject: [PATCH 352/881] Use new UnsupportedAppUsage annotation.

Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library.

Bug: 145132366
Test: m && diff unsupportedappusage_index.csv
Change-Id: I0c336de56bc4a041dc97ff9b7927f62f0b44b457
Merged-In: I0c336de56bc4a041dc97ff9b7927f62f0b44b457
---
 core/java/android/net/EthernetManager.java     | 2 +-
 core/java/android/net/NetworkStats.java        | 2 +-
 core/java/android/net/NetworkStatsHistory.java | 2 +-
 core/java/android/net/NetworkTemplate.java     | 2 +-
 core/java/android/net/TrafficStats.java        | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 72565024d3..fd015b4fe5 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -17,7 +17,7 @@
 package android.net;
 
 import android.annotation.SystemService;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 6c7aa1379f..45bf4d2e13 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -19,7 +19,7 @@ package android.net;
 import static android.os.Process.CLAT_UID;
 
 import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemClock;
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index f61260ee3e..7b799e2624 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -30,7 +30,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS;
 
 import static com.android.internal.util.ArrayUtils.total;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.service.NetworkStatsHistoryBucketProto;
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 87c7118c0e..5e6c47a47a 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -34,7 +34,7 @@ import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.ROAMING_YES;
 import static android.net.wifi.WifiInfo.removeDoubleQuotes;
 
-import android.annotation.UnsupportedAppUsage;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.BackupUtils;
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index bf4884aa96..162d6e27bd 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -20,10 +20,10 @@ import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
-import android.annotation.UnsupportedAppUsage;
 import android.app.DownloadManager;
 import android.app.backup.BackupManager;
 import android.app.usage.NetworkStatsManager;
+import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.MediaPlayer;
 import android.os.Build;

From 5fa370c470095bba7ba1fb882bd398484261cd83 Mon Sep 17 00:00:00 2001
From: evitayan 
Date: Mon, 30 Dec 2019 16:05:38 -0800
Subject: [PATCH 353/881] Allow mainline IPsec(IKE) to statically include
 @PolicyDirection

@PolicyDirection was hidden API defined in IpSecManager and
mainline module IPsec(IKE) needs to depend on it.

To remove this hidden API dependency, this commit:
- Moves definition of @PolicyDirection to a separate class
- Creates sharing filegroup framework-ike-shared-srcs for mainline
  IKE and include PolicyDirection.java

Bug: 146360859
Test: build, flash, boot
Test: atest FrameworksIkeTests
Change-Id: Ic6d7c06d4b92e16a9a65430365c9acc73932147b
---
 core/java/android/net/IpSecManager.java | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 45d0c7313f..09ec6c35fc 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -17,7 +17,6 @@ package android.net;
 
 import static com.android.internal.util.Preconditions.checkNotNull;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
@@ -26,6 +25,7 @@ import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.net.annotations.PolicyDirection;
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -41,8 +41,6 @@ import dalvik.system.CloseGuard;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.Socket;
@@ -78,11 +76,6 @@ public final class IpSecManager {
      */
     public static final int DIRECTION_OUT = 1;
 
-    /** @hide */
-    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface PolicyDirection {}
-
     /**
      * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
      *

From 10a00a2819ba7d371eea50d7ece07d20275c85c9 Mon Sep 17 00:00:00 2001
From: junyulai 
Date: Fri, 15 Nov 2019 17:15:01 +0800
Subject: [PATCH 354/881] [SP01] Add NetworkStats to system API

In order to let external module report their network stats,
expose necessary APIs to construct NetworkStats object.

Test: atest FrameworksNetTests CtsUsageStatsTestCases
Test: m doc-comment-check-docs
Bug: 130855321
Change-Id: Id3ec8aaff3df67948c25eac2319a74cf33a27979
---
 core/java/android/net/NetworkStats.java       | 221 +++++++++++++++---
 core/java/android/net/TrafficStats.java       |   2 +-
 .../server/net/NetworkStatsFactory.java       |   6 +-
 .../server/net/NetworkStatsService.java       |  10 +-
 4 files changed, 194 insertions(+), 45 deletions(-)

diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 45bf4d2e13..96d7a80886 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -19,6 +19,9 @@ package android.net;
 import static android.os.Process.CLAT_UID;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -48,59 +51,104 @@ import java.util.function.Predicate;
  * @hide
  */
 // @NotThreadSafe
-public class NetworkStats implements Parcelable {
+@SystemApi
+public final class NetworkStats implements Parcelable {
     private static final String TAG = "NetworkStats";
+
     /** {@link #iface} value when interface details unavailable. */
-    public static final String IFACE_ALL = null;
+    @SuppressLint("CompileTimeConstant")
+    @Nullable public static final String IFACE_ALL = null;
+    /**
+     * Virtual network interface for video telephony. This is for VT data usage counting
+     * purpose.
+     */
+    public static final String IFACE_VT = "vt_data0";
+
     /** {@link #uid} value when UID details unavailable. */
     public static final int UID_ALL = -1;
-    /** {@link #tag} value matching any tag. */
+    /** Special UID value for data usage by tethering. */
+    public static final int UID_TETHERING = -5;
+
+    /**
+     * {@link #tag} value matching any tag.
+     * @hide
+     */
     // TODO: Rename TAG_ALL to TAG_ANY.
     public static final int TAG_ALL = -1;
-    /** {@link #set} value for all sets combined, not including debug sets. */
+    /**
+     * {@link #set} value for all sets combined, not including debug sets.
+     * @hide
+     */
     public static final int SET_ALL = -1;
     /** {@link #set} value where background data is accounted. */
     public static final int SET_DEFAULT = 0;
     /** {@link #set} value where foreground data is accounted. */
     public static final int SET_FOREGROUND = 1;
-    /** All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values. */
+    /**
+     * All {@link #set} value greater than SET_DEBUG_START are debug {@link #set} values.
+     * @hide
+     */
     public static final int SET_DEBUG_START = 1000;
-    /** Debug {@link #set} value when the VPN stats are moved in. */
+    /**
+     * Debug {@link #set} value when the VPN stats are moved in.
+     * @hide
+     */
     public static final int SET_DBG_VPN_IN = 1001;
-    /** Debug {@link #set} value when the VPN stats are moved out of a vpn UID. */
+    /**
+     * Debug {@link #set} value when the VPN stats are moved out of a vpn UID.
+     * @hide
+     */
     public static final int SET_DBG_VPN_OUT = 1002;
 
-    /** Include all interfaces when filtering */
-    public static final String[] INTERFACES_ALL = null;
+    /**
+     * Include all interfaces when filtering
+     * @hide
+     */
+    public @Nullable static final String[] INTERFACES_ALL = null;
 
     /** {@link #tag} value for total data across all tags. */
     // TODO: Rename TAG_NONE to TAG_ALL.
     public static final int TAG_NONE = 0;
 
-    /** {@link #metered} value to account for all metered states. */
+    /**
+     * {@link #metered} value to account for all metered states.
+     * @hide
+     */
     public static final int METERED_ALL = -1;
     /** {@link #metered} value where native, unmetered data is accounted. */
     public static final int METERED_NO = 0;
     /** {@link #metered} value where metered data is accounted. */
     public static final int METERED_YES = 1;
 
-    /** {@link #roaming} value to account for all roaming states. */
+    /**
+     * {@link #roaming} value to account for all roaming states.
+     * @hide
+     */
     public static final int ROAMING_ALL = -1;
     /** {@link #roaming} value where native, non-roaming data is accounted. */
     public static final int ROAMING_NO = 0;
     /** {@link #roaming} value where roaming data is accounted. */
     public static final int ROAMING_YES = 1;
 
-    /** {@link #onDefaultNetwork} value to account for all default network states. */
+    /**
+     * {@link #onDefaultNetwork} value to account for all default network states.
+     * @hide
+     */
     public static final int DEFAULT_NETWORK_ALL = -1;
     /** {@link #onDefaultNetwork} value to account for usage while not the default network. */
     public static final int DEFAULT_NETWORK_NO = 0;
     /** {@link #onDefaultNetwork} value to account for usage while the default network. */
     public static final int DEFAULT_NETWORK_YES = 1;
 
-    /** Denotes a request for stats at the interface level. */
+    /**
+     * Denotes a request for stats at the interface level.
+     * @hide
+     */
     public static final int STATS_PER_IFACE = 0;
-    /** Denotes a request for stats at the interface and UID level. */
+    /**
+     * Denotes a request for stats at the interface and UID level.
+     * @hide
+     */
     public static final int STATS_PER_UID = 1;
 
     private static final String CLATD_INTERFACE_PREFIX = "v4-";
@@ -144,60 +192,78 @@ public class NetworkStats implements Parcelable {
     @UnsupportedAppUsage
     private long[] operations;
 
+    /** @hide */
+    @SystemApi
     public static class Entry {
+        /** @hide */
         @UnsupportedAppUsage
         public String iface;
+        /** @hide */
         @UnsupportedAppUsage
         public int uid;
+        /** @hide */
         @UnsupportedAppUsage
         public int set;
+        /** @hide */
         @UnsupportedAppUsage
         public int tag;
         /**
          * Note that this is only populated w/ the default value when read from /proc or written
          * to disk. We merge in the correct value when reporting this value to clients of
          * getSummary().
+         * @hide
          */
         public int metered;
         /**
          * Note that this is only populated w/ the default value when read from /proc or written
          * to disk. We merge in the correct value when reporting this value to clients of
          * getSummary().
+         * @hide
          */
         public int roaming;
         /**
          * Note that this is only populated w/ the default value when read from /proc or written
          * to disk. We merge in the correct value when reporting this value to clients of
          * getSummary().
+         * @hide
          */
         public int defaultNetwork;
+        /** @hide */
         @UnsupportedAppUsage
         public long rxBytes;
+        /** @hide */
         @UnsupportedAppUsage
         public long rxPackets;
+        /** @hide */
         @UnsupportedAppUsage
         public long txBytes;
+        /** @hide */
         @UnsupportedAppUsage
         public long txPackets;
+        /** @hide */
+        @UnsupportedAppUsage
         public long operations;
 
+        /** @hide */
         @UnsupportedAppUsage
         public Entry() {
             this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
         }
 
+        /** @hide */
         public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
             this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
                     operations);
         }
 
+        /** @hide */
         public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
                 long txBytes, long txPackets, long operations) {
             this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
                     rxBytes, rxPackets, txBytes, txPackets, operations);
         }
 
-        public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
+        public Entry(@Nullable String iface, int uid, int set, int tag, int metered, int roaming,
                  int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
                  long operations) {
             this.iface = iface;
@@ -214,15 +280,18 @@ public class NetworkStats implements Parcelable {
             this.operations = operations;
         }
 
+        /** @hide */
         public boolean isNegative() {
             return rxBytes < 0 || rxPackets < 0 || txBytes < 0 || txPackets < 0 || operations < 0;
         }
 
+        /** @hide */
         public boolean isEmpty() {
             return rxBytes == 0 && rxPackets == 0 && txBytes == 0 && txPackets == 0
                     && operations == 0;
         }
 
+        /** @hide */
         public void add(Entry another) {
             this.rxBytes += another.rxBytes;
             this.rxPackets += another.rxPackets;
@@ -249,6 +318,7 @@ public class NetworkStats implements Parcelable {
             return builder.toString();
         }
 
+        /** @hide */
         @Override
         public boolean equals(Object o) {
             if (o instanceof Entry) {
@@ -262,13 +332,13 @@ public class NetworkStats implements Parcelable {
             return false;
         }
 
+        /** @hide */
         @Override
         public int hashCode() {
             return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface);
         }
     }
 
-    @UnsupportedAppUsage
     public NetworkStats(long elapsedRealtime, int initialSize) {
         this.elapsedRealtime = elapsedRealtime;
         this.size = 0;
@@ -292,6 +362,7 @@ public class NetworkStats implements Parcelable {
         }
     }
 
+    /** @hide */
     @UnsupportedAppUsage
     public NetworkStats(Parcel parcel) {
         elapsedRealtime = parcel.readLong();
@@ -312,7 +383,7 @@ public class NetworkStats implements Parcelable {
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeLong(elapsedRealtime);
         dest.writeInt(size);
         dest.writeInt(capacity);
@@ -330,19 +401,23 @@ public class NetworkStats implements Parcelable {
         dest.writeLongArray(operations);
     }
 
+    /**
+     * @hide
+     */
     @Override
     public NetworkStats clone() {
         final NetworkStats clone = new NetworkStats(elapsedRealtime, size);
         NetworkStats.Entry entry = null;
         for (int i = 0; i < size; i++) {
             entry = getValues(i, entry);
-            clone.addValues(entry);
+            clone.addEntry(entry);
         }
         return clone;
     }
 
     /**
      * Clear all data stored in this object.
+     * @hide
      */
     public void clear() {
         this.capacity = 0;
@@ -360,25 +435,28 @@ public class NetworkStats implements Parcelable {
         this.operations = EmptyArray.LONG;
     }
 
+    /** @hide */
     @VisibleForTesting
     public NetworkStats addIfaceValues(
             String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
-        return addValues(
+        return addEntry(
                 iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
     }
 
+    /** @hide */
     @VisibleForTesting
-    public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
+    public NetworkStats addEntry(String iface, int uid, int set, int tag, long rxBytes,
             long rxPackets, long txBytes, long txPackets, long operations) {
-        return addValues(new Entry(
+        return addEntry(new Entry(
                 iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
     }
 
+    /** @hide */
     @VisibleForTesting
-    public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming,
+    public NetworkStats addEntry(String iface, int uid, int set, int tag, int metered, int roaming,
             int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
             long operations) {
-        return addValues(new Entry(
+        return addEntry(new Entry(
                 iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
                 txBytes, txPackets, operations));
     }
@@ -386,8 +464,9 @@ public class NetworkStats implements Parcelable {
     /**
      * Add new stats entry, copying from given {@link Entry}. The {@link Entry}
      * object can be recycled across multiple calls.
+     * @hide
      */
-    public NetworkStats addValues(Entry entry) {
+    public NetworkStats addEntry(Entry entry) {
         if (size >= capacity) {
             final int newLength = Math.max(size, 10) * 3 / 2;
             iface = Arrays.copyOf(iface, newLength);
@@ -428,6 +507,7 @@ public class NetworkStats implements Parcelable {
 
     /**
      * Return specific stats entry.
+     * @hide
      */
     @UnsupportedAppUsage
     public Entry getValues(int i, Entry recycle) {
@@ -467,10 +547,12 @@ public class NetworkStats implements Parcelable {
         operations[dest] = operations[src];
     }
 
+    /** @hide */
     public long getElapsedRealtime() {
         return elapsedRealtime;
     }
 
+    /** @hide */
     public void setElapsedRealtime(long time) {
         elapsedRealtime = time;
     }
@@ -478,21 +560,25 @@ public class NetworkStats implements Parcelable {
     /**
      * Return age of this {@link NetworkStats} object with respect to
      * {@link SystemClock#elapsedRealtime()}.
+     * @hide
      */
     public long getElapsedRealtimeAge() {
         return SystemClock.elapsedRealtime() - elapsedRealtime;
     }
 
+    /** @hide */
     @UnsupportedAppUsage
     public int size() {
         return size;
     }
 
+    /** @hide */
     @VisibleForTesting
     public int internalSize() {
         return capacity;
     }
 
+    /** @hide */
     @Deprecated
     public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
             long txBytes, long txPackets, long operations) {
@@ -501,6 +587,7 @@ public class NetworkStats implements Parcelable {
                 txPackets, operations);
     }
 
+    /** @hide */
     public NetworkStats combineValues(String iface, int uid, int set, int tag,
             long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
         return combineValues(new Entry(
@@ -509,16 +596,20 @@ public class NetworkStats implements Parcelable {
 
     /**
      * Combine given values with an existing row, or create a new row if
-     * {@link #findIndex(String, int, int, int, int)} is unable to find match. Can
-     * also be used to subtract values from existing rows.
+     * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
+     * also be used to subtract values from existing rows. This method mutates the referencing
+     * {@link NetworkStats} object.
+     *
+     * @param entry the {@link Entry} to combine.
+     * @return a reference to this mutated {@link NetworkStats} object.
+     * @hide
      */
-    @UnsupportedAppUsage
-    public NetworkStats combineValues(Entry entry) {
+    public @NonNull NetworkStats combineValues(@NonNull Entry entry) {
         final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
                 entry.roaming, entry.defaultNetwork);
         if (i == -1) {
             // only create new entry when positive contribution
-            addValues(entry);
+            addEntry(entry);
         } else {
             rxBytes[i] += entry.rxBytes;
             rxPackets[i] += entry.rxPackets;
@@ -530,10 +621,33 @@ public class NetworkStats implements Parcelable {
     }
 
     /**
-     * Combine all values from another {@link NetworkStats} into this object.
+     * Add given values with an existing row, or create a new row if
+     * {@link #findIndex(String, int, int, int, int, int, int)} is unable to find match. Can
+     * also be used to subtract values from existing rows.
+     *
+     * @param entry the {@link Entry} to add.
+     * @return a new constructed {@link NetworkStats} object that contains the result.
      */
-    @UnsupportedAppUsage
-    public void combineAllValues(NetworkStats another) {
+    public @NonNull NetworkStats addValues(@NonNull Entry entry) {
+        return this.clone().combineValues(entry);
+    }
+
+    /**
+     * Add the given {@link NetworkStats} objects.
+     *
+     * @return the sum of two objects.
+     */
+    public @NonNull NetworkStats add(@NonNull NetworkStats another) {
+        final NetworkStats ret = this.clone();
+        ret.combineAllValues(another);
+        return ret;
+    }
+
+    /**
+     * Combine all values from another {@link NetworkStats} into this object.
+     * @hide
+     */
+    public void combineAllValues(@NonNull NetworkStats another) {
         NetworkStats.Entry entry = null;
         for (int i = 0; i < another.size; i++) {
             entry = another.getValues(i, entry);
@@ -543,6 +657,7 @@ public class NetworkStats implements Parcelable {
 
     /**
      * Find first stats index that matches the requested parameters.
+     * @hide
      */
     public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming,
             int defaultNetwork) {
@@ -560,6 +675,7 @@ public class NetworkStats implements Parcelable {
     /**
      * Find first stats index that matches the requested parameters, starting
      * search around the hinted index as an optimization.
+     * @hide
      */
     @VisibleForTesting
     public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming,
@@ -589,6 +705,7 @@ public class NetworkStats implements Parcelable {
      * Splice in {@link #operations} from the given {@link NetworkStats} based
      * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
      * since operation counts are at data layer.
+     * @hide
      */
     public void spliceOperationsFrom(NetworkStats stats) {
         for (int i = 0; i < size; i++) {
@@ -604,6 +721,7 @@ public class NetworkStats implements Parcelable {
 
     /**
      * Return list of unique interfaces known by this data structure.
+     * @hide
      */
     public String[] getUniqueIfaces() {
         final HashSet ifaces = new HashSet();
@@ -617,6 +735,7 @@ public class NetworkStats implements Parcelable {
 
     /**
      * Return list of unique UIDs known by this data structure.
+     * @hide
      */
     @UnsupportedAppUsage
     public int[] getUniqueUids() {
@@ -636,6 +755,7 @@ public class NetworkStats implements Parcelable {
     /**
      * Return total bytes represented by this snapshot object, usually used when
      * checking if a {@link #subtract(NetworkStats)} delta passes a threshold.
+     * @hide
      */
     @UnsupportedAppUsage
     public long getTotalBytes() {
@@ -645,6 +765,7 @@ public class NetworkStats implements Parcelable {
 
     /**
      * Return total of all fields represented by this snapshot object.
+     * @hide
      */
     @UnsupportedAppUsage
     public Entry getTotal(Entry recycle) {
@@ -654,6 +775,7 @@ public class NetworkStats implements Parcelable {
     /**
      * Return total of all fields represented by this snapshot object matching
      * the requested {@link #uid}.
+     * @hide
      */
     @UnsupportedAppUsage
     public Entry getTotal(Entry recycle, int limitUid) {
@@ -663,11 +785,13 @@ public class NetworkStats implements Parcelable {
     /**
      * Return total of all fields represented by this snapshot object matching
      * the requested {@link #iface}.
+     * @hide
      */
     public Entry getTotal(Entry recycle, HashSet limitIface) {
         return getTotal(recycle, limitIface, UID_ALL, false);
     }
 
+    /** @hide */
     @UnsupportedAppUsage
     public Entry getTotalIncludingTags(Entry recycle) {
         return getTotal(recycle, null, UID_ALL, true);
@@ -717,6 +841,7 @@ public class NetworkStats implements Parcelable {
 
     /**
      * Fast path for battery stats.
+     * @hide
      */
     public long getTotalPackets() {
         long total = 0;
@@ -729,9 +854,12 @@ public class NetworkStats implements Parcelable {
     /**
      * Subtract the given {@link NetworkStats}, effectively leaving the delta
      * between two snapshots in time. Assumes that statistics rows collect over
-     * time, and that none of them have disappeared.
+     * time, and that none of them have disappeared. This method does not mutate
+     * the referencing object.
+     *
+     * @return the delta between two objects.
      */
-    public NetworkStats subtract(NetworkStats right) {
+    public @NonNull NetworkStats subtract(@NonNull NetworkStats right) {
         return subtract(this, right, null, null);
     }
 
@@ -742,6 +870,7 @@ public class NetworkStats implements Parcelable {
      * 

* If counters have rolled backwards, they are clamped to {@code 0} and * reported to the given {@link NonMonotonicObserver}. + * @hide */ public static NetworkStats subtract(NetworkStats left, NetworkStats right, NonMonotonicObserver observer, C cookie) { @@ -759,6 +888,7 @@ public class NetworkStats implements Parcelable { * If recycle is supplied, this NetworkStats object will be * reused (and returned) as the result if it is large enough to contain * the data. + * @hide */ public static NetworkStats subtract(NetworkStats left, NetworkStats right, NonMonotonicObserver observer, C cookie, NetworkStats recycle) { @@ -817,7 +947,7 @@ public class NetworkStats implements Parcelable { entry.operations = Math.max(entry.operations, 0); } - result.addValues(entry); + result.addEntry(entry); } return result; @@ -847,6 +977,7 @@ public class NetworkStats implements Parcelable { * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. * @param useBpfStats True if eBPF is in use. + * @hide */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { @@ -899,6 +1030,7 @@ public class NetworkStats implements Parcelable { * {@link #apply464xlatAdjustments(NetworkStats, NetworkStats, Map)} with {@code this} as * base and stacked traffic. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. + * @hide */ public void apply464xlatAdjustments(Map stackedIfaces, boolean useBpfStats) { apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats); @@ -907,6 +1039,7 @@ public class NetworkStats implements Parcelable { /** * Return total statistics grouped by {@link #iface}; doesn't mutate the * original structure. + * @hide */ public NetworkStats groupedByIface() { final NetworkStats stats = new NetworkStats(elapsedRealtime, 10); @@ -938,6 +1071,7 @@ public class NetworkStats implements Parcelable { /** * Return total statistics grouped by {@link #uid}; doesn't mutate the * original structure. + * @hide */ public NetworkStats groupedByUid() { final NetworkStats stats = new NetworkStats(elapsedRealtime, 10); @@ -968,6 +1102,7 @@ public class NetworkStats implements Parcelable { /** * Remove all rows that match one of specified UIDs. + * @hide */ public void removeUids(int[] uids) { int nextOutputEntry = 0; @@ -989,6 +1124,7 @@ public class NetworkStats implements Parcelable { * @param limitUid UID to filter for, or {@link #UID_ALL}. * @param limitIfaces Interfaces to filter for, or {@link #INTERFACES_ALL}. * @param limitTag Tag to filter for, or {@link #TAG_ALL}. + * @hide */ public void filter(int limitUid, String[] limitIfaces, int limitTag) { if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) { @@ -1004,6 +1140,7 @@ public class NetworkStats implements Parcelable { * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}. * *

This mutates the original structure in place. + * @hide */ public void filterDebugEntries() { filter(e -> e.set < SET_DEBUG_START); @@ -1024,6 +1161,7 @@ public class NetworkStats implements Parcelable { size = nextOutputEntry; } + /** @hide */ public void dump(String prefix, PrintWriter pw) { pw.print(prefix); pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime); @@ -1047,6 +1185,7 @@ public class NetworkStats implements Parcelable { /** * Return text description of {@link #set} value. + * @hide */ public static String setToString(int set) { switch (set) { @@ -1067,6 +1206,7 @@ public class NetworkStats implements Parcelable { /** * Return text description of {@link #set} value. + * @hide */ public static String setToCheckinString(int set) { switch (set) { @@ -1087,6 +1227,7 @@ public class NetworkStats implements Parcelable { /** * @return true if the querySet matches the dataSet. + * @hide */ public static boolean setMatches(int querySet, int dataSet) { if (querySet == dataSet) { @@ -1098,6 +1239,7 @@ public class NetworkStats implements Parcelable { /** * Return text description of {@link #tag} value. + * @hide */ public static String tagToString(int tag) { return "0x" + Integer.toHexString(tag); @@ -1105,6 +1247,7 @@ public class NetworkStats implements Parcelable { /** * Return text description of {@link #metered} value. + * @hide */ public static String meteredToString(int metered) { switch (metered) { @@ -1121,6 +1264,7 @@ public class NetworkStats implements Parcelable { /** * Return text description of {@link #roaming} value. + * @hide */ public static String roamingToString(int roaming) { switch (roaming) { @@ -1137,6 +1281,7 @@ public class NetworkStats implements Parcelable { /** * Return text description of {@link #defaultNetwork} value. + * @hide */ public static String defaultNetworkToString(int defaultNetwork) { switch (defaultNetwork) { @@ -1151,6 +1296,7 @@ public class NetworkStats implements Parcelable { } } + /** @hide */ @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); @@ -1163,8 +1309,7 @@ public class NetworkStats implements Parcelable { return 0; } - @UnsupportedAppUsage - public static final @android.annotation.NonNull Creator CREATOR = new Creator() { + public static final @NonNull Creator CREATOR = new Creator() { @Override public NetworkStats createFromParcel(Parcel in) { return new NetworkStats(in); @@ -1176,6 +1321,7 @@ public class NetworkStats implements Parcelable { } }; + /** @hide */ public interface NonMonotonicObserver { public void foundNonMonotonic( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex, C cookie); @@ -1195,6 +1341,7 @@ public class NetworkStats implements Parcelable { * @param tunUid uid of the VPN application * @param tunIface iface of the vpn tunnel * @param underlyingIfaces underlying network ifaces used by the VPN application + * @hide */ public void migrateTun(int tunUid, @NonNull String tunIface, @NonNull String[] underlyingIfaces) { diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 162d6e27bd..8108cf08d5 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -89,7 +89,7 @@ public class TrafficStats { * * @hide */ - public static final int UID_TETHERING = -5; + public static final int UID_TETHERING = NetworkStats.UID_TETHERING; /** * Tag values in this range are reserved for the network stack. The network stack is diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 3ca1803262..22b01bee6c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -229,7 +229,7 @@ public class NetworkStatsFactory { entry.txPackets += reader.nextLong(); } - stats.addValues(entry); + stats.addEntry(entry); reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { @@ -279,7 +279,7 @@ public class NetworkStatsFactory { entry.txBytes = reader.nextLong(); entry.txPackets = reader.nextLong(); - stats.addValues(entry); + stats.addEntry(entry); reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { @@ -439,7 +439,7 @@ public class NetworkStatsFactory { if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface)) && (limitUid == UID_ALL || limitUid == entry.uid) && (limitTag == TAG_ALL || limitTag == entry.tag)) { - stats.addValues(entry); + stats.addEntry(entry); } reader.finishLine(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index a41fb7d327..a80fc05802 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,6 +27,7 @@ import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.IFACE_VT; import static android.net.NetworkStats.INTERFACES_ALL; import static android.net.NetworkStats.METERED_ALL; import static android.net.NetworkStats.ROAMING_ALL; @@ -211,7 +212,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Virtual network interface for video telephony. This is for VT data usage counting purpose. */ - public static final String VT_INTERFACE = "vt_data0"; + // TODO: Remove this after no one is using it. + public static final String VT_INTERFACE = NetworkStats.IFACE_VT; /** * Settings that can be changed externally. @@ -712,7 +714,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); final NetworkStats stats = new NetworkStats(end - start, 1); - stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, + stats.addEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, entry.operations)); return stats; @@ -1179,8 +1181,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), ident.getRoaming(), true /* metered */, true /* onDefaultNetwork */); - findOrCreateNetworkIdentitySet(mActiveIfaces, VT_INTERFACE).add(vtIdent); - findOrCreateNetworkIdentitySet(mActiveUidIfaces, VT_INTERFACE).add(vtIdent); + findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent); + findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent); } if (isMobile) { From 84b2c43b56a19b176b0d78757083aee64e2e9c18 Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 18 Nov 2019 18:10:39 +0800 Subject: [PATCH 355/881] [SP02] Add provider interfaces to system API This change contains a base class that allows external modules to implement a custom network statistics provider. And a callback interface that allows the implementation to signal the system. These interfaces will be used in the follow-up changes that implement the functionality. Test: atest FrameworksNetTests CtsUsageStatsTestCases Test: m doc-comment-check-docs Bug: 130855321 Change-Id: Ib23377c8b9cef02bc32253462b068fd10734d21a --- .../provider/INetworkStatsProvider.aidl | 28 +++++++++++++++++ .../INetworkStatsProviderCallback.aidl | 31 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 core/java/android/net/netstats/provider/INetworkStatsProvider.aidl create mode 100644 core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl new file mode 100644 index 0000000000..55b3d4edb1 --- /dev/null +++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netstats.provider; + +/** + * Interface for NetworkStatsService to query network statistics and set data limits. + * + * @hide + */ +oneway interface INetworkStatsProvider { + void requestStatsUpdate(int token); + void setLimit(String iface, long quotaBytes); + void setAlert(long quotaBytes); +} diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl new file mode 100644 index 0000000000..3ea9318f10 --- /dev/null +++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netstats.provider; + +import android.net.NetworkStats; + +/** + * Interface for implementor of {@link INetworkStatsProviderCallback} to push events + * such as network statistics update or notify limit reached. + * @hide + */ +oneway interface INetworkStatsProviderCallback { + void onStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); + void onAlertReached(); + void onLimitReached(); + void unregister(); +} From 3d5d3b32af5ccb70f010b9bb87b5d6b190c02933 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Tue, 10 Dec 2019 17:47:51 +0000 Subject: [PATCH 356/881] Use new UnsupportedAppUsage annotation. Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library. Bug: 145132366 Test: m && diff unsupportedappusage_index.csv Change-Id: I8789f8499d4dca08580672e9e45ed9a7026dd686 Merged-In: I8789f8499d4dca08580672e9e45ed9a7026dd686 --- core/java/android/app/usage/NetworkStatsManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 6bade90182..74129702b4 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -21,8 +21,8 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.Nullable; import android.annotation.SystemService; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; import android.app.usage.NetworkStats.Bucket; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.net.ConnectivityManager; import android.net.DataUsageRequest; From 892e3bf7b6b253dc3c09416abce915f3e766c9f6 Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 13 Jan 2020 14:36:55 +0800 Subject: [PATCH 357/881] [SP03.1] Replace com.android.internal.util.Preconditions.checkNotNull Extracted from ag/9990011 to make NetworkStatsManager sync with internal line, given that it is missing in aosp/1198084. Bug: 126528330 Test: Treehugger Change-Id: I77f50326869799f51d4636cb7c6d7c97daf531e6 Merged-In: I42117ebfb640e3b0b133183e5e146860bed8471a --- core/java/android/app/usage/NetworkStatsManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 74129702b4..4346d9738e 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -16,8 +16,6 @@ package android.app.usage; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.Nullable; import android.annotation.SystemService; import android.annotation.TestApi; @@ -42,6 +40,8 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import java.util.Objects; + /** * Provides access to network usage history and statistics. Usage data is collected in * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details. @@ -418,7 +418,7 @@ public class NetworkStatsManager { /** @hide */ public void registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { - checkNotNull(callback, "UsageCallback cannot be null"); + Objects.requireNonNull(callback, "UsageCallback cannot be null"); final Looper looper; if (handler == null) { From b3f085c5a86f4284dffb8831109b8a956960ea2b Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 21 Nov 2019 16:26:27 +0800 Subject: [PATCH 358/881] [SP03] support registerNetworkStatsProvider API This change provides an API that allow external modules to register a custom provider of NetworkStats to merge the network statistics that cannot be seen by the kernel to system. Test: atest FrameworksNetTests CtsUsageStatsTestCases Test: atest NetworkPolicyManagerServiceTest Test: m doc-comment-check-docs Bug: 130855321 Change-Id: I265bc637c40666cde505fde5056d2d9bfc5fb204 --- .../app/usage/NetworkStatsManager.java | 34 ++++ .../android/net/INetworkStatsService.aidl | 5 + .../server/net/NetworkStatsService.java | 192 +++++++++++++++++- 3 files changed, 225 insertions(+), 6 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 4346d9738e..9c4a8f4fbe 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -16,7 +16,10 @@ package android.app.usage; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.app.usage.NetworkStats.Bucket; @@ -27,6 +30,9 @@ import android.net.DataUsageRequest; import android.net.INetworkStatsService; import android.net.NetworkIdentity; import android.net.NetworkTemplate; +import android.net.netstats.provider.AbstractNetworkStatsProvider; +import android.net.netstats.provider.NetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProviderWrapper; import android.os.Binder; import android.os.Handler; import android.os.Looper; @@ -519,6 +525,34 @@ public class NetworkStatsManager { private DataUsageRequest request; } + /** + * Registers a custom provider of {@link android.net.NetworkStats} to combine the network + * statistics that cannot be seen by the kernel to system. To unregister, invoke + * {@link NetworkStatsProviderCallback#unregister()}. + * + * @param tag a human readable identifier of the custom network stats provider. + * @param provider a custom implementation of {@link AbstractNetworkStatsProvider} that needs to + * be registered to the system. + * @return a {@link NetworkStatsProviderCallback}, which can be used to report events to the + * system. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) + @NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider( + @NonNull String tag, + @NonNull AbstractNetworkStatsProvider provider) { + try { + final NetworkStatsProviderWrapper wrapper = new NetworkStatsProviderWrapper(provider); + return new NetworkStatsProviderCallback( + mService.registerNetworkStatsProvider(tag, wrapper)); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + // Unreachable code, but compiler doesn't know about it. + return null; + } + private static NetworkTemplate createTemplate(int networkType, String subscriberId) { final NetworkTemplate template; switch (networkType) { diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 9994f9f82b..5fa515a143 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -23,6 +23,8 @@ import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; +import android.net.netstats.provider.INetworkStatsProvider; +import android.net.netstats.provider.INetworkStatsProviderCallback; import android.os.IBinder; import android.os.Messenger; import com.android.internal.net.VpnInfo; @@ -89,4 +91,7 @@ interface INetworkStatsService { /** Get the total network stats information since boot */ long getTotalStats(int type); + /** Registers a network stats provider */ + INetworkStatsProviderCallback registerNetworkStatsProvider(String tag, + in INetworkStatsProvider provider); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index a80fc05802..29a3974df9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -18,6 +18,7 @@ package com.android.server.net; import static android.Manifest.permission.ACCESS_NETWORK_STATE; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; +import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; @@ -71,6 +72,7 @@ import static com.android.server.NetworkManagementSocketTagger.resetKernelUidSta import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.usage.NetworkStatsManager; @@ -97,6 +99,9 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.net.netstats.provider.INetworkStatsProvider; +import android.net.netstats.provider.INetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProviderCallback; import android.os.BestClock; import android.os.Binder; import android.os.DropBoxManager; @@ -109,6 +114,7 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; @@ -248,6 +254,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private final Object mStatsLock = new Object(); + private final Object mStatsProviderLock = new Object(); /** Set of currently active ifaces. */ @GuardedBy("mStatsLock") @@ -272,6 +279,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); + private final RemoteCallbackList mStatsProviderCbList = + new RemoteCallbackList<>(); + @GuardedBy("mStatsLock") private NetworkStatsRecorder mDevRecorder; @GuardedBy("mStatsLock") @@ -502,9 +512,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Register for a global alert that is delivered through - * {@link INetworkManagementEventObserver} once a threshold amount of data - * has been transferred. + * Register for a global alert that is delivered through {@link INetworkManagementEventObserver} + * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has + * been transferred. */ private void registerGlobalAlert() { try { @@ -514,6 +524,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } catch (RemoteException e) { // ignored; service lives in system_server } + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setAlert(mGlobalAlertBytes)); } @Override @@ -803,8 +814,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void incrementOperationCount(int uid, int tag, int operationCount) { if (Binder.getCallingUid() != uid) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.UPDATE_DEVICE_STATS, TAG); + mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG); } if (operationCount < 0) { @@ -1095,7 +1105,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Observer that watches for {@link INetworkManagementService} alerts. */ - private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() { + private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() { @Override public void limitReached(String limitName, String iface) { // only someone like NMS should be calling us @@ -1252,6 +1262,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { xtSnapshot.combineAllValues(tetherSnapshot); devSnapshot.combineAllValues(tetherSnapshot); + // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data + // from stats providers that isn't already counted by dev and XT stats. + Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider"); + final NetworkStats providersnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE); + Trace.traceEnd(TRACE_TAG_NETWORK); + xtSnapshot.combineAllValues(providersnapshot); + devSnapshot.combineAllValues(providersnapshot); + // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev"); @@ -1355,6 +1373,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performSampleLocked(); } + // request asynchronous stats update from all providers for next poll. + // TODO: request with a valid token. + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */)); + // finally, dispatch updated event to any listeners final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); @@ -1476,6 +1498,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void forceUpdate() { NetworkStatsService.this.forceUpdate(); } + + @Override + public void setStatsProviderLimit(@NonNull String iface, long quota) { + Slog.v(TAG, "setStatsProviderLimit(" + iface + "," + quota + ")"); + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setLimit(iface, quota)); + } } @Override @@ -1690,6 +1718,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { uidSnapshot.combineAllValues(vtStats); } + // get a stale copy of uid stats snapshot provided by providers. + final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID); + providerStats.filter(UID_ALL, ifaces, TAG_ALL); + mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats, mUseBpfTrafficStats); + uidSnapshot.combineAllValues(providerStats); + uidSnapshot.combineAllValues(mUidOperations); return uidSnapshot; @@ -1726,6 +1760,152 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + /** + * Registers a custom provider of {@link android.net.NetworkStats} to combine the network + * statistics that cannot be seen by the kernel to system. To unregister, invoke the + * {@code unregister()} of the returned callback. + * + * @param tag a human readable identifier of the custom network stats provider. + * @param provider the binder interface of + * {@link android.net.netstats.provider.AbstractNetworkStatsProvider} that + * needs to be registered to the system. + * + * @return a binder interface of + * {@link android.net.netstats.provider.NetworkStatsProviderCallback}, which can be + * used to report events to the system. + */ + public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider( + @NonNull String tag, @NonNull INetworkStatsProvider provider) { + mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG); + Objects.requireNonNull(provider, "provider is null"); + Objects.requireNonNull(tag, "tag is null"); + try { + NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl( + tag, provider, mAlertObserver, mStatsProviderCbList); + mStatsProviderCbList.register(callback); + Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid=" + + getCallingUid() + "/" + getCallingPid()); + return callback; + } catch (RemoteException e) { + Log.e(TAG, "registerNetworkStatsProvider failed", e); + } + return null; + } + + // Collect stats from local cache of providers. + private @NonNull NetworkStats getNetworkStatsFromProviders(int how) { + final NetworkStats ret = new NetworkStats(0L, 0); + invokeForAllStatsProviderCallbacks((cb) -> ret.combineAllValues(cb.getCachedStats(how))); + return ret; + } + + @FunctionalInterface + private interface ThrowingConsumer { + void accept(S s) throws T; + } + + private void invokeForAllStatsProviderCallbacks( + @NonNull ThrowingConsumer task) { + synchronized (mStatsProviderCbList) { + final int length = mStatsProviderCbList.beginBroadcast(); + try { + for (int i = 0; i < length; i++) { + final NetworkStatsProviderCallbackImpl cb = + mStatsProviderCbList.getBroadcastItem(i); + try { + task.accept(cb); + } catch (RemoteException e) { + Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); + } + } + } finally { + mStatsProviderCbList.finishBroadcast(); + } + } + } + + private static class NetworkStatsProviderCallbackImpl extends INetworkStatsProviderCallback.Stub + implements IBinder.DeathRecipient { + @NonNull final String mTag; + @NonNull private final Object mProviderStatsLock = new Object(); + @NonNull final INetworkStatsProvider mProvider; + @NonNull final INetworkManagementEventObserver mAlertObserver; + @NonNull final RemoteCallbackList mStatsProviderCbList; + + @GuardedBy("mProviderStatsLock") + // STATS_PER_IFACE and STATS_PER_UID + private final NetworkStats mIfaceStats = new NetworkStats(0L, 0); + @GuardedBy("mProviderStatsLock") + private final NetworkStats mUidStats = new NetworkStats(0L, 0); + + NetworkStatsProviderCallbackImpl( + @NonNull String tag, @NonNull INetworkStatsProvider provider, + @NonNull INetworkManagementEventObserver alertObserver, + @NonNull RemoteCallbackList cbList) + throws RemoteException { + mTag = tag; + mProvider = provider; + mProvider.asBinder().linkToDeath(this, 0); + mAlertObserver = alertObserver; + mStatsProviderCbList = cbList; + } + + @NonNull + public NetworkStats getCachedStats(int how) { + synchronized (mProviderStatsLock) { + NetworkStats stats; + switch (how) { + case STATS_PER_IFACE: + stats = mIfaceStats; + break; + case STATS_PER_UID: + stats = mUidStats; + break; + default: + throw new IllegalArgumentException("Invalid type: " + how); + } + // Return a defensive copy instead of local reference. + return stats.clone(); + } + } + + @Override + public void onStatsUpdated(int token, @Nullable NetworkStats ifaceStats, + @Nullable NetworkStats uidStats) { + // TODO: 1. Use token to map ifaces to correct NetworkIdentity. + // 2. Store the difference and store it directly to the recorder. + synchronized (mProviderStatsLock) { + if (ifaceStats != null) mIfaceStats.combineAllValues(ifaceStats); + if (uidStats != null) mUidStats.combineAllValues(uidStats); + } + } + + @Override + public void onAlertReached() throws RemoteException { + mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */); + } + + @Override + public void onLimitReached() { + Log.d(TAG, mTag + ": onLimitReached"); + LocalServices.getService(NetworkPolicyManagerInternal.class) + .onStatsProviderLimitReached(mTag); + } + + @Override + public void binderDied() { + Log.d(TAG, mTag + ": binderDied"); + mStatsProviderCbList.unregister(this); + } + + @Override + public void unregister() { + Log.d(TAG, mTag + ": unregister"); + mStatsProviderCbList.unregister(this); + } + + } + @VisibleForTesting static class HandlerCallback implements Handler.Callback { private final NetworkStatsService mService; From c215221f567e5a0d6aebe12c8a6d223f614507e5 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 22 Nov 2019 22:27:21 +0800 Subject: [PATCH 359/881] [SP04] add unit test for NetworkStatsProvider Test: atest NetworkStatsServiceTest Bug: 130855321 Change-Id: I0c19d8bedcb9398da3f464efe01e775fde9f8a78 --- .../java/com/android/server/net/NetworkStatsService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 29a3974df9..fc39a253bc 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -182,7 +182,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * This avoids firing the global alert too often on devices with high transfer speeds and * high quota. */ - private static final int PERFORM_POLL_DELAY_MS = 1000; + private static final int DEFAULT_PERFORM_POLL_DELAY_MS = 1000; private static final String TAG_NETSTATS_ERROR = "netstats_error"; @@ -226,6 +226,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ public interface NetworkStatsSettings { public long getPollInterval(); + public long getPollDelay(); public boolean getSampleEnabled(); public boolean getAugmentEnabled(); @@ -1116,7 +1117,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // such a call pending; UID stats are handled during normal polling interval. if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) { mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT, - PERFORM_POLL_DELAY_MS); + mSettings.getPollDelay()); } } } @@ -1995,6 +1996,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); } @Override + public long getPollDelay() { + return DEFAULT_PERFORM_POLL_DELAY_MS; + } + @Override public long getGlobalAlertBytes(long def) { return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def); } From ea0a0c347f5eb629d4d9195dadda029dabc8364c Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Tue, 10 Dec 2019 17:47:53 +0000 Subject: [PATCH 360/881] Use new UnsupportedAppUsage annotation. Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library. Bug: 145132366 Test: m && diff unsupportedappusage_index.csv Change-Id: I534e3fd1305e2f4af076986770033478448a665c Merged-In: I534e3fd1305e2f4af076986770033478448a665c --- core/java/android/net/nsd/NsdServiceInfo.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java index 459b140980..0946499f16 100644 --- a/core/java/android/net/nsd/NsdServiceInfo.java +++ b/core/java/android/net/nsd/NsdServiceInfo.java @@ -17,13 +17,13 @@ package android.net.nsd; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; -import android.os.Parcelable; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; +import android.os.Parcelable; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Base64; import android.util.Log; -import android.util.ArrayMap; import java.io.UnsupportedEncodingException; import java.net.InetAddress; From b8c3a054d5043d5c6c5512409d70105acf5a4a45 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 6 Jan 2020 20:22:17 +0800 Subject: [PATCH 361/881] Move DnsSdTxtRecord to net common static library DnsSdTxtRecord is moved to frameworks/libs/net for mainline support. Also change the import path using this class. Bug: 139268426 Bug: 135998869 Test: atest FrameworksNetTests ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: I6118b313ce668707d598aa2eab9baee2f7622dbc --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index b9b7bf73c1..4a1820a8e5 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -22,10 +22,10 @@ import android.content.Intent; import android.database.ContentObserver; import android.net.NetworkStack; import android.net.Uri; -import android.net.nsd.DnsSdTxtRecord; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; +import android.net.util.nsd.DnsSdTxtRecord; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; From 1b031a2900896e4ab172b1b6bfccc762d562a515 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Mon, 13 Jan 2020 14:16:01 -0800 Subject: [PATCH 362/881] NetworkStatsFactory.cpp: IWYU Bug: 140330870 Test: N/A Change-Id: Id6107c8a83b22ac56f4da61a5d5757d29ecb07ac --- services/core/jni/com_android_server_net_NetworkStatsFactory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp index 9cd743b346..8b6526ff49 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include From 004a9039c29c473aa5a4ac4dfdbb5058380dc2a4 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 10 Jan 2020 13:57:07 +0800 Subject: [PATCH 363/881] [SP11] add dumpsys support to dump stats inside providers Sample output is like below: Stats Providers: OffloadController Xt: NetworkStats: ... OffloadController Uid: NetworkStats: ... ImsPhoneCallTracker Xt: NetworkStats: ... Test: adb shell dumpsys netstats (--uid) Bug: 130855321 Change-Id: I968006de83e13e66bb3359135f0237daf7252bd2 --- .../android/server/net/NetworkStatsService.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index fc39a253bc..415ccb8fe8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1610,6 +1610,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { pw.decreaseIndent(); pw.println(); + pw.println("Stats Providers:"); + pw.increaseIndent(); + invokeForAllStatsProviderCallbacks((cb) -> { + pw.println(cb.mTag + " Xt:"); + pw.increaseIndent(); + pw.print(cb.getCachedStats(STATS_PER_IFACE).toString()); + pw.decreaseIndent(); + if (includeUid) { + pw.println(cb.mTag + " Uid:"); + pw.increaseIndent(); + pw.print(cb.getCachedStats(STATS_PER_UID).toString()); + pw.decreaseIndent(); + } + }); + pw.decreaseIndent(); + pw.println("Dev stats:"); pw.increaseIndent(); mDevRecorder.dumpLocked(pw, fullHistory); From 556e59ad64f7f652965651b6ee1d704b83f5fa0f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 24 Jan 2020 17:57:27 +0900 Subject: [PATCH 364/881] Support one Ethernet interface in server mode. Currently, Ethernet only supports interfaces in client mode (e.g., to connect to the Internet). Add minimal support to Ethernet to support interfaces in server mode. This simple implementation only works on the default interface, which is the first interface that is detected on boot (even if the interface is later removed). This also provides (but does not yet unhide) a simple API for Tethering to request that the next-plugged-in interface to be placed into server mode. Test: Enabling tethering with change on top Bug: 130840861 Change-Id: I78f85bc36aaceb62ce274003a75ea99d0b6bc8b7 --- .../server/ethernet/EthernetServiceImpl.java | 14 ++ .../server/ethernet/EthernetTracker.java | 131 ++++++++++++++++-- 2 files changed, 137 insertions(+), 8 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index fda3c3c2f9..1cf38b45f4 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -20,12 +20,14 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; import android.net.IpConfiguration; import android.net.NetworkStack; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; import android.util.PrintWriterPrinter; @@ -161,6 +163,18 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker.removeListener(listener); } + @Override + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { + NetworkStack.checkNetworkStackPermission(mContext); + mTracker.requestTetheredInterface(callback); + } + + @Override + public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { + NetworkStack.checkNetworkStackPermission(mContext); + mTracker.releaseTetheredInterface(callback); + } + @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 4ab1dff881..24616b78dc 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -19,6 +19,7 @@ package com.android.server.ethernet; import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfiguration; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -61,6 +62,9 @@ import java.util.concurrent.ConcurrentHashMap; *

All public or package private methods must be thread-safe unless stated otherwise. */ final class EthernetTracker { + private static final int INTERFACE_MODE_CLIENT = 1; + private static final int INTERFACE_MODE_SERVER = 2; + private final static String TAG = EthernetTracker.class.getSimpleName(); private final static boolean DBG = EthernetNetworkFactory.DBG; @@ -73,6 +77,7 @@ final class EthernetTracker { private final ConcurrentHashMap mIpConfigurations = new ConcurrentHashMap<>(); + private final Context mContext; private final INetworkManagementService mNMService; private final Handler mHandler; private final EthernetNetworkFactory mFactory; @@ -80,10 +85,25 @@ final class EthernetTracker { private final RemoteCallbackList mListeners = new RemoteCallbackList<>(); + private final TetheredInterfaceRequestList mTetheredInterfaceRequests = + new TetheredInterfaceRequestList(); + // Used only on the handler thread + private String mDefaultInterface; + private int mDefaultInterfaceMode; + // Tracks whether clients were notified that the tethered interface is available + private boolean mTetheredInterfaceWasAvailable = false; private volatile IpConfiguration mIpConfigForDefaultInterface; + private class TetheredInterfaceRequestList extends RemoteCallbackList { + @Override + public void onCallbackDied(ITetheredInterfaceCallback cb, Object cookie) { + mHandler.post(EthernetTracker.this::maybeUntetherDefaultInterface); + } + } + EthernetTracker(Context context, Handler handler) { + mContext = context; mHandler = handler; // The services we use. @@ -167,6 +187,68 @@ final class EthernetTracker { mListeners.unregister(listener); } + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { + mHandler.post(() -> { + if (!mTetheredInterfaceRequests.register(callback)) { + // Remote process has already died + return; + } + if (mDefaultInterfaceMode == INTERFACE_MODE_SERVER) { + if (mTetheredInterfaceWasAvailable) { + notifyTetheredInterfaceAvailable(callback, mDefaultInterface); + } + return; + } + + setDefaultInterfaceMode(INTERFACE_MODE_SERVER); + }); + } + + public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { + mHandler.post(() -> { + mTetheredInterfaceRequests.unregister(callback); + maybeUntetherDefaultInterface(); + }); + } + + private void notifyTetheredInterfaceAvailable(ITetheredInterfaceCallback cb, String iface) { + try { + cb.onAvailable(iface); + } catch (RemoteException e) { + Log.e(TAG, "Error sending tethered interface available callback", e); + } + } + + private void notifyTetheredInterfaceUnavailable(ITetheredInterfaceCallback cb) { + try { + cb.onUnavailable(); + } catch (RemoteException e) { + Log.e(TAG, "Error sending tethered interface available callback", e); + } + } + + private void maybeUntetherDefaultInterface() { + if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return; + // mDefaultInterface null means that there never was a default interface (it is never set + // to null). + if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT || mDefaultInterface == null) return; + + setDefaultInterfaceMode(INTERFACE_MODE_CLIENT); + } + + private void setDefaultInterfaceMode(int mode) { + mDefaultInterfaceMode = mode; + removeInterface(mDefaultInterface); + addInterface(mDefaultInterface); + } + + private int getInterfaceMode(final String iface) { + if (iface.equals(mDefaultInterface)) { + return mDefaultInterfaceMode; + } + return INTERFACE_MODE_CLIENT; + } + private void removeInterface(String iface) { mFactory.removeInterface(iface); } @@ -198,13 +280,17 @@ final class EthernetTracker { nc = createDefaultNetworkCapabilities(); } } - IpConfiguration ipConfiguration = mIpConfigurations.get(iface); - if (ipConfiguration == null) { - ipConfiguration = createDefaultIpConfiguration(); - } - Log.d(TAG, "Started tracking interface " + iface); - mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + final int mode = getInterfaceMode(iface); + if (mode == INTERFACE_MODE_CLIENT) { + IpConfiguration ipConfiguration = mIpConfigurations.get(iface); + if (ipConfiguration == null) { + ipConfiguration = createDefaultIpConfiguration(); + } + + Log.d(TAG, "Started tracking interface " + iface); + mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + } // Note: if the interface already has link (e.g., if we crashed and got // restarted while it was running), we need to fake a link up notification so we @@ -215,8 +301,11 @@ final class EthernetTracker { } private void updateInterfaceState(String iface, boolean up) { - boolean modified = mFactory.updateInterfaceLinkState(iface, up); - if (modified) { + final int mode = getInterfaceMode(iface); + final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) + && mFactory.updateInterfaceLinkState(iface, up); + + if (factoryLinkStateUpdated) { boolean restricted = isRestrictedInterface(iface); int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { @@ -234,6 +323,25 @@ final class EthernetTracker { } mListeners.finishBroadcast(); } + + updateServerModeInterfaceState(iface, up, mode); + } + + private void updateServerModeInterfaceState(String iface, boolean up, int mode) { + final boolean available = up && (mode == INTERFACE_MODE_SERVER); + if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; + + final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); + for (int i = 0; i < pendingCbs; i++) { + ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i); + if (available) { + notifyTetheredInterfaceAvailable(item, iface); + } else { + notifyTetheredInterfaceUnavailable(item); + } + } + mTetheredInterfaceRequests.finishBroadcast(); + mTetheredInterfaceWasAvailable = available; } private void maybeTrackInterface(String iface) { @@ -244,6 +352,11 @@ final class EthernetTracker { return; } + // TODO: avoid making an interface default if it has configured NetworkCapabilities. + if (mDefaultInterface == null) { + mDefaultInterface = iface; + } + if (mIpConfigForDefaultInterface != null) { updateIpConfiguration(iface, mIpConfigForDefaultInterface); mIpConfigForDefaultInterface = null; @@ -467,6 +580,8 @@ final class EthernetTracker { postAndWaitForRunnable(() -> { pw.println(getClass().getSimpleName()); pw.println("Ethernet interface name filter: " + mIfaceMatch); + pw.println("Default interface: " + mDefaultInterface); + pw.println("Default interface mode: " + mDefaultInterfaceMode); pw.println("Listeners: " + mListeners.getRegisteredCallbackCount()); pw.println("IP Configurations:"); pw.increaseIndent(); From 815e0fde8704ccb85c85c92f72756ac1e4dab563 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 24 Jan 2020 19:29:17 +0900 Subject: [PATCH 365/881] Support putting one Ethernet interface in server mode. requestTetheredInterface can be used to put an interface in server mode, which will persist until release() is called on the returned request, or until the requesting process dies. Test: Enabled ethernet tethering with change on top Bug: 130840861 Change-Id: Id96d581acb3fa4e52ca62dd94ec257f56bd3a1ce --- core/java/android/net/EthernetManager.java | 78 ++++++++++++++++++- core/java/android/net/IEthernetManager.aidl | 3 + .../net/ITetheredInterfaceCallback.aidl | 23 ++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 core/java/android/net/ITetheredInterfaceCallback.aidl diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index fd015b4fe5..95000f5744 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.SystemService; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -24,6 +25,7 @@ import android.os.Message; import android.os.RemoteException; import java.util.ArrayList; +import java.util.Objects; /** * A class representing the IP configuration of the Ethernet network. @@ -37,7 +39,7 @@ public class EthernetManager { private final Context mContext; private final IEthernetManager mService; - private final Handler mHandler = new Handler() { + private final Handler mHandler = new Handler(ConnectivityThread.getInstanceLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == MSG_AVAILABILITY_CHANGED) { @@ -180,4 +182,78 @@ public class EthernetManager { } } } + + /** + * A request for a tethered interface. + */ + public static class TetheredInterfaceRequest { + private final IEthernetManager mService; + private final ITetheredInterfaceCallback mCb; + + private TetheredInterfaceRequest(@NonNull IEthernetManager service, + @NonNull ITetheredInterfaceCallback cb) { + this.mService = service; + this.mCb = cb; + } + + /** + * Release the request, causing the interface to revert back from tethering mode if there + * is no other requestor. + */ + public void release() { + try { + mService.releaseTetheredInterface(mCb); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + } + + /** + * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}. + */ + public interface TetheredInterfaceCallback { + /** + * Called when the tethered interface is available. + * @param iface The name of the interface. + */ + void onAvailable(@NonNull String iface); + + /** + * Called when the tethered interface is now unavailable. + */ + void onUnavailable(); + } + + /** + * Request a tethered interface in tethering mode. + * + *

When this method is called and there is at least one ethernet interface available, the + * system will designate one to act as a tethered interface. If there is already a tethered + * interface, the existing interface will be used. + * @param callback A callback to be called once the request has been fulfilled. + */ + @NonNull + public TetheredInterfaceRequest requestTetheredInterface( + @NonNull TetheredInterfaceCallback callback) { + Objects.requireNonNull(callback, "Callback must be non-null"); + final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() { + @Override + public void onAvailable(String iface) { + callback.onAvailable(iface); + } + + @Override + public void onUnavailable() { + callback.onUnavailable(); + } + }; + + try { + mService.requestTetheredInterface(cbInternal); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return new TetheredInterfaceRequest(mService, cbInternal); + } } diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl index 94960b51d3..ccc6e35209 100644 --- a/core/java/android/net/IEthernetManager.aidl +++ b/core/java/android/net/IEthernetManager.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; /** * Interface that answers queries about, and allows changing @@ -32,4 +33,6 @@ interface IEthernetManager boolean isAvailable(String iface); void addListener(in IEthernetServiceListener listener); void removeListener(in IEthernetServiceListener listener); + void requestTetheredInterface(in ITetheredInterfaceCallback callback); + void releaseTetheredInterface(in ITetheredInterfaceCallback callback); } diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/core/java/android/net/ITetheredInterfaceCallback.aidl new file mode 100644 index 0000000000..e3d075988c --- /dev/null +++ b/core/java/android/net/ITetheredInterfaceCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +interface ITetheredInterfaceCallback { + void onAvailable(in String iface); + void onUnavailable(); +} \ No newline at end of file From 355e6f0692902bb439f605b28a8f4d58df8b5544 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 24 Jan 2020 22:57:09 +0900 Subject: [PATCH 366/881] Add support for Ethernet tethering Ethernet tethering can be started via startTethering(TETHERING_ETHERNET). Test: flashed, enabled ethernet tethering, verified internet access on downstream. Bug: 130840861 Change-Id: I34842acd94b972e440c3622f7617df10c18acf65 --- core/java/android/net/EthernetManager.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 95000f5744..a3899b705c 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -17,7 +17,9 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.annotation.SystemService; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Handler; @@ -32,6 +34,8 @@ import java.util.Objects; * * @hide */ +@SystemApi +@TestApi @SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; @@ -62,12 +66,14 @@ public class EthernetManager { /** * A listener interface to receive notification on changes in Ethernet. + * @hide */ public interface Listener { /** * Called when Ethernet port's availability is changed. * @param iface Ethernet interface name * @param isAvailable {@code true} if Ethernet port exists. + * @hide */ @UnsupportedAppUsage void onAvailabilityChanged(String iface, boolean isAvailable); @@ -78,6 +84,7 @@ public class EthernetManager { * Applications will almost always want to use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}. + * @hide */ public EthernetManager(Context context, IEthernetManager service) { mContext = context; @@ -87,6 +94,7 @@ public class EthernetManager { /** * Get Ethernet configuration. * @return the Ethernet Configuration, contained in {@link IpConfiguration}. + * @hide */ @UnsupportedAppUsage public IpConfiguration getConfiguration(String iface) { @@ -99,6 +107,7 @@ public class EthernetManager { /** * Set Ethernet configuration. + * @hide */ @UnsupportedAppUsage public void setConfiguration(String iface, IpConfiguration config) { @@ -111,6 +120,7 @@ public class EthernetManager { /** * Indicates whether the system currently has one or more Ethernet interfaces. + * @hide */ @UnsupportedAppUsage public boolean isAvailable() { @@ -121,6 +131,7 @@ public class EthernetManager { * Indicates whether the system has given interface. * * @param iface Ethernet interface name + * @hide */ @UnsupportedAppUsage public boolean isAvailable(String iface) { @@ -135,6 +146,7 @@ public class EthernetManager { * Adds a listener. * @param listener A {@link Listener} to add. * @throws IllegalArgumentException If the listener is null. + * @hide */ @UnsupportedAppUsage public void addListener(Listener listener) { @@ -153,6 +165,7 @@ public class EthernetManager { /** * Returns an array of available Ethernet interface names. + * @hide */ @UnsupportedAppUsage public String[] getAvailableInterfaces() { @@ -167,6 +180,7 @@ public class EthernetManager { * Removes a listener. * @param listener A {@link Listener} to remove. * @throws IllegalArgumentException If the listener is null. + * @hide */ @UnsupportedAppUsage public void removeListener(Listener listener) { From b13338a8e389e3a5551c55fc1bc857d32d344eee Mon Sep 17 00:00:00 2001 From: David Su Date: Mon, 27 Jan 2020 13:27:50 -0800 Subject: [PATCH 367/881] Networking: Rename removeDoubleQuotes to sanitizeSsid Bug: 145745815 Test: compiles Change-Id: Iaa6f0d65cab556c24b0a9010427de8e6a02836c1 Merged-In: Iaa6f0d65cab556c24b0a9010427de8e6a02836c1 (clean cherry-pick from internal branch) --- core/java/android/net/NetworkTemplate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 5e6c47a47a..5498f74ba2 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -32,7 +32,7 @@ import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; -import static android.net.wifi.WifiInfo.removeDoubleQuotes; +import static android.net.wifi.WifiInfo.sanitizeSsid; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -401,7 +401,7 @@ public class NetworkTemplate implements Parcelable { switch (ident.mType) { case TYPE_WIFI: return Objects.equals( - removeDoubleQuotes(mNetworkId), removeDoubleQuotes(ident.mNetworkId)); + sanitizeSsid(mNetworkId), sanitizeSsid(ident.mNetworkId)); default: return false; } From 8b5779ee384824a036f55ef453ed4e6bc09a804e Mon Sep 17 00:00:00 2001 From: David Su Date: Mon, 27 Jan 2020 13:27:50 -0800 Subject: [PATCH 368/881] Networking: Rename removeDoubleQuotes to sanitizeSsid Bug: 145745815 Test: compiles Change-Id: Iaa6f0d65cab556c24b0a9010427de8e6a02836c1 --- core/java/android/net/NetworkTemplate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 5e6c47a47a..5498f74ba2 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -32,7 +32,7 @@ import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; -import static android.net.wifi.WifiInfo.removeDoubleQuotes; +import static android.net.wifi.WifiInfo.sanitizeSsid; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -401,7 +401,7 @@ public class NetworkTemplate implements Parcelable { switch (ident.mType) { case TYPE_WIFI: return Objects.equals( - removeDoubleQuotes(mNetworkId), removeDoubleQuotes(ident.mNetworkId)); + sanitizeSsid(mNetworkId), sanitizeSsid(ident.mNetworkId)); default: return false; } From c359926d90cada661ca5c1cc4f0e99aebfbe67bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Mon, 27 Jan 2020 17:36:56 -0800 Subject: [PATCH 369/881] Fix incorrect interpolation of active bucket for partial requests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just because the bucket is active (ie. overlaps with 'now') doesn't mean the request necessarily covers the entire bucket. For example a bucketDuration=5 with a bucket from curStart=1 to curEnd=6 with now=4 and requests: - from start=0 to end=3 --> overlap=[1,3] --> bucketSpan=2 - from start=2 to end=3 --> overlap=[2,3] --> bucketSpan=1 - from start=2 to end=5 --> overlap=[2,4] --> bucketSpan=2 - from start=2 to end=7 --> overlap=[2,4] --> bucketSpan=2 and the previously correctly handled cases: - from start=0 to end=5 --> overlap=[1,4] --> bucketSpan=3 - from start=0 to end=7 --> overlap=[1,4] --> bucketSpan=3 We fix this by bounding the end of buckets to now, this means that bucketDuration is no longer a constant, but it simplifies all the rest of the logic. Test: builds, atest Bug: 143338233 Signed-off-by: Maciej Żenczykowski Change-Id: I642b57f7b8486071ad7808fd9b901859923b6d25 --- .../java/android/net/NetworkStatsHistory.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 7b799e2624..c82c288222 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -548,32 +548,32 @@ public class NetworkStatsHistory implements Parcelable { final int startIndex = getIndexAfter(end); for (int i = startIndex; i >= 0; i--) { final long curStart = bucketStart[i]; - final long curEnd = curStart + bucketDuration; + long curEnd = curStart + bucketDuration; // bucket is older than request; we're finished if (curEnd <= start) break; // bucket is newer than request; keep looking if (curStart >= end) continue; - // include full value for active buckets, otherwise only fractional - final boolean activeBucket = curStart < now && curEnd > now; - final long overlap; - if (activeBucket) { - overlap = bucketDuration; - } else { - final long overlapEnd = curEnd < end ? curEnd : end; - final long overlapStart = curStart > start ? curStart : start; - overlap = overlapEnd - overlapStart; - } + // the active bucket is shorter then a normal completed bucket + if (curEnd > now) curEnd = now; + // usually this is simply bucketDuration + final long bucketSpan = curEnd - curStart; + // prevent division by zero + if (bucketSpan <= 0) continue; + + final long overlapEnd = curEnd < end ? curEnd : end; + final long overlapStart = curStart > start ? curStart : start; + final long overlap = overlapEnd - overlapStart; if (overlap <= 0) continue; // integer math each time is faster than floating point - if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration; - if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration; - if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration; - if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration; - if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketDuration; - if (operations != null) entry.operations += operations[i] * overlap / bucketDuration; + if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketSpan; + if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketSpan; + if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketSpan; + if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketSpan; + if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketSpan; + if (operations != null) entry.operations += operations[i] * overlap / bucketSpan; } return entry; } From 0486f517ad3e7e974c363c91c1da0718945b5b99 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 24 Jan 2020 17:57:27 +0900 Subject: [PATCH 370/881] Support one Ethernet interface in server mode. Currently, Ethernet only supports interfaces in client mode (e.g., to connect to the Internet). Add minimal support to Ethernet to support interfaces in server mode. This simple implementation only works on the default interface, which is the first interface that is detected on boot (even if the interface is later removed). This also provides (but does not yet unhide) a simple API for Tethering to request that the next-plugged-in interface to be placed into server mode. Test: Enabling tethering with change on top Bug: 130840861 Merged-In: I78f85bc36aaceb62ce274003a75ea99d0b6bc8b7 Change-Id: I78f85bc36aaceb62ce274003a75ea99d0b6bc8b7 (clean cherry-pick from internal branch) --- .../server/ethernet/EthernetServiceImpl.java | 14 ++ .../server/ethernet/EthernetTracker.java | 131 ++++++++++++++++-- 2 files changed, 137 insertions(+), 8 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index fda3c3c2f9..1cf38b45f4 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -20,12 +20,14 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; import android.net.IpConfiguration; import android.net.NetworkStack; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; import android.util.PrintWriterPrinter; @@ -161,6 +163,18 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker.removeListener(listener); } + @Override + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { + NetworkStack.checkNetworkStackPermission(mContext); + mTracker.requestTetheredInterface(callback); + } + + @Override + public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { + NetworkStack.checkNetworkStackPermission(mContext); + mTracker.releaseTetheredInterface(callback); + } + @Override protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 4ab1dff881..24616b78dc 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -19,6 +19,7 @@ package com.android.server.ethernet; import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfiguration; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -61,6 +62,9 @@ import java.util.concurrent.ConcurrentHashMap; *

All public or package private methods must be thread-safe unless stated otherwise. */ final class EthernetTracker { + private static final int INTERFACE_MODE_CLIENT = 1; + private static final int INTERFACE_MODE_SERVER = 2; + private final static String TAG = EthernetTracker.class.getSimpleName(); private final static boolean DBG = EthernetNetworkFactory.DBG; @@ -73,6 +77,7 @@ final class EthernetTracker { private final ConcurrentHashMap mIpConfigurations = new ConcurrentHashMap<>(); + private final Context mContext; private final INetworkManagementService mNMService; private final Handler mHandler; private final EthernetNetworkFactory mFactory; @@ -80,10 +85,25 @@ final class EthernetTracker { private final RemoteCallbackList mListeners = new RemoteCallbackList<>(); + private final TetheredInterfaceRequestList mTetheredInterfaceRequests = + new TetheredInterfaceRequestList(); + // Used only on the handler thread + private String mDefaultInterface; + private int mDefaultInterfaceMode; + // Tracks whether clients were notified that the tethered interface is available + private boolean mTetheredInterfaceWasAvailable = false; private volatile IpConfiguration mIpConfigForDefaultInterface; + private class TetheredInterfaceRequestList extends RemoteCallbackList { + @Override + public void onCallbackDied(ITetheredInterfaceCallback cb, Object cookie) { + mHandler.post(EthernetTracker.this::maybeUntetherDefaultInterface); + } + } + EthernetTracker(Context context, Handler handler) { + mContext = context; mHandler = handler; // The services we use. @@ -167,6 +187,68 @@ final class EthernetTracker { mListeners.unregister(listener); } + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { + mHandler.post(() -> { + if (!mTetheredInterfaceRequests.register(callback)) { + // Remote process has already died + return; + } + if (mDefaultInterfaceMode == INTERFACE_MODE_SERVER) { + if (mTetheredInterfaceWasAvailable) { + notifyTetheredInterfaceAvailable(callback, mDefaultInterface); + } + return; + } + + setDefaultInterfaceMode(INTERFACE_MODE_SERVER); + }); + } + + public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { + mHandler.post(() -> { + mTetheredInterfaceRequests.unregister(callback); + maybeUntetherDefaultInterface(); + }); + } + + private void notifyTetheredInterfaceAvailable(ITetheredInterfaceCallback cb, String iface) { + try { + cb.onAvailable(iface); + } catch (RemoteException e) { + Log.e(TAG, "Error sending tethered interface available callback", e); + } + } + + private void notifyTetheredInterfaceUnavailable(ITetheredInterfaceCallback cb) { + try { + cb.onUnavailable(); + } catch (RemoteException e) { + Log.e(TAG, "Error sending tethered interface available callback", e); + } + } + + private void maybeUntetherDefaultInterface() { + if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return; + // mDefaultInterface null means that there never was a default interface (it is never set + // to null). + if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT || mDefaultInterface == null) return; + + setDefaultInterfaceMode(INTERFACE_MODE_CLIENT); + } + + private void setDefaultInterfaceMode(int mode) { + mDefaultInterfaceMode = mode; + removeInterface(mDefaultInterface); + addInterface(mDefaultInterface); + } + + private int getInterfaceMode(final String iface) { + if (iface.equals(mDefaultInterface)) { + return mDefaultInterfaceMode; + } + return INTERFACE_MODE_CLIENT; + } + private void removeInterface(String iface) { mFactory.removeInterface(iface); } @@ -198,13 +280,17 @@ final class EthernetTracker { nc = createDefaultNetworkCapabilities(); } } - IpConfiguration ipConfiguration = mIpConfigurations.get(iface); - if (ipConfiguration == null) { - ipConfiguration = createDefaultIpConfiguration(); - } - Log.d(TAG, "Started tracking interface " + iface); - mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + final int mode = getInterfaceMode(iface); + if (mode == INTERFACE_MODE_CLIENT) { + IpConfiguration ipConfiguration = mIpConfigurations.get(iface); + if (ipConfiguration == null) { + ipConfiguration = createDefaultIpConfiguration(); + } + + Log.d(TAG, "Started tracking interface " + iface); + mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + } // Note: if the interface already has link (e.g., if we crashed and got // restarted while it was running), we need to fake a link up notification so we @@ -215,8 +301,11 @@ final class EthernetTracker { } private void updateInterfaceState(String iface, boolean up) { - boolean modified = mFactory.updateInterfaceLinkState(iface, up); - if (modified) { + final int mode = getInterfaceMode(iface); + final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) + && mFactory.updateInterfaceLinkState(iface, up); + + if (factoryLinkStateUpdated) { boolean restricted = isRestrictedInterface(iface); int n = mListeners.beginBroadcast(); for (int i = 0; i < n; i++) { @@ -234,6 +323,25 @@ final class EthernetTracker { } mListeners.finishBroadcast(); } + + updateServerModeInterfaceState(iface, up, mode); + } + + private void updateServerModeInterfaceState(String iface, boolean up, int mode) { + final boolean available = up && (mode == INTERFACE_MODE_SERVER); + if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; + + final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); + for (int i = 0; i < pendingCbs; i++) { + ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i); + if (available) { + notifyTetheredInterfaceAvailable(item, iface); + } else { + notifyTetheredInterfaceUnavailable(item); + } + } + mTetheredInterfaceRequests.finishBroadcast(); + mTetheredInterfaceWasAvailable = available; } private void maybeTrackInterface(String iface) { @@ -244,6 +352,11 @@ final class EthernetTracker { return; } + // TODO: avoid making an interface default if it has configured NetworkCapabilities. + if (mDefaultInterface == null) { + mDefaultInterface = iface; + } + if (mIpConfigForDefaultInterface != null) { updateIpConfiguration(iface, mIpConfigForDefaultInterface); mIpConfigForDefaultInterface = null; @@ -467,6 +580,8 @@ final class EthernetTracker { postAndWaitForRunnable(() -> { pw.println(getClass().getSimpleName()); pw.println("Ethernet interface name filter: " + mIfaceMatch); + pw.println("Default interface: " + mDefaultInterface); + pw.println("Default interface mode: " + mDefaultInterfaceMode); pw.println("Listeners: " + mListeners.getRegisteredCallbackCount()); pw.println("IP Configurations:"); pw.increaseIndent(); From 22a02a74220142b4da35b0b47ad75709e3f8f75b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 24 Jan 2020 19:29:17 +0900 Subject: [PATCH 371/881] Support putting one Ethernet interface in server mode. requestTetheredInterface can be used to put an interface in server mode, which will persist until release() is called on the returned request, or until the requesting process dies. Test: Enabled ethernet tethering with change on top Bug: 130840861 Merged-In: Id96d581acb3fa4e52ca62dd94ec257f56bd3a1ce Change-Id: Id96d581acb3fa4e52ca62dd94ec257f56bd3a1ce (clean cherry-pick from internal branch) --- core/java/android/net/EthernetManager.java | 78 ++++++++++++++++++- core/java/android/net/IEthernetManager.aidl | 3 + .../net/ITetheredInterfaceCallback.aidl | 23 ++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 core/java/android/net/ITetheredInterfaceCallback.aidl diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index fd015b4fe5..95000f5744 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.NonNull; import android.annotation.SystemService; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -24,6 +25,7 @@ import android.os.Message; import android.os.RemoteException; import java.util.ArrayList; +import java.util.Objects; /** * A class representing the IP configuration of the Ethernet network. @@ -37,7 +39,7 @@ public class EthernetManager { private final Context mContext; private final IEthernetManager mService; - private final Handler mHandler = new Handler() { + private final Handler mHandler = new Handler(ConnectivityThread.getInstanceLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == MSG_AVAILABILITY_CHANGED) { @@ -180,4 +182,78 @@ public class EthernetManager { } } } + + /** + * A request for a tethered interface. + */ + public static class TetheredInterfaceRequest { + private final IEthernetManager mService; + private final ITetheredInterfaceCallback mCb; + + private TetheredInterfaceRequest(@NonNull IEthernetManager service, + @NonNull ITetheredInterfaceCallback cb) { + this.mService = service; + this.mCb = cb; + } + + /** + * Release the request, causing the interface to revert back from tethering mode if there + * is no other requestor. + */ + public void release() { + try { + mService.releaseTetheredInterface(mCb); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + } + + /** + * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}. + */ + public interface TetheredInterfaceCallback { + /** + * Called when the tethered interface is available. + * @param iface The name of the interface. + */ + void onAvailable(@NonNull String iface); + + /** + * Called when the tethered interface is now unavailable. + */ + void onUnavailable(); + } + + /** + * Request a tethered interface in tethering mode. + * + *

When this method is called and there is at least one ethernet interface available, the + * system will designate one to act as a tethered interface. If there is already a tethered + * interface, the existing interface will be used. + * @param callback A callback to be called once the request has been fulfilled. + */ + @NonNull + public TetheredInterfaceRequest requestTetheredInterface( + @NonNull TetheredInterfaceCallback callback) { + Objects.requireNonNull(callback, "Callback must be non-null"); + final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() { + @Override + public void onAvailable(String iface) { + callback.onAvailable(iface); + } + + @Override + public void onUnavailable() { + callback.onUnavailable(); + } + }; + + try { + mService.requestTetheredInterface(cbInternal); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return new TetheredInterfaceRequest(mService, cbInternal); + } } diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl index 94960b51d3..ccc6e35209 100644 --- a/core/java/android/net/IEthernetManager.aidl +++ b/core/java/android/net/IEthernetManager.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; +import android.net.ITetheredInterfaceCallback; /** * Interface that answers queries about, and allows changing @@ -32,4 +33,6 @@ interface IEthernetManager boolean isAvailable(String iface); void addListener(in IEthernetServiceListener listener); void removeListener(in IEthernetServiceListener listener); + void requestTetheredInterface(in ITetheredInterfaceCallback callback); + void releaseTetheredInterface(in ITetheredInterfaceCallback callback); } diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/core/java/android/net/ITetheredInterfaceCallback.aidl new file mode 100644 index 0000000000..e3d075988c --- /dev/null +++ b/core/java/android/net/ITetheredInterfaceCallback.aidl @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** @hide */ +interface ITetheredInterfaceCallback { + void onAvailable(in String iface); + void onUnavailable(); +} \ No newline at end of file From 07b469658f11c2412c027779526f10d7b67988a4 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 24 Jan 2020 22:57:09 +0900 Subject: [PATCH 372/881] Add support for Ethernet tethering Ethernet tethering can be started via startTethering(TETHERING_ETHERNET). Test: flashed, enabled ethernet tethering, verified internet access on downstream. Bug: 130840861 Merged-In: I34842acd94b972e440c3622f7617df10c18acf65 Change-Id: I34842acd94b972e440c3622f7617df10c18acf65 (cherry-pick with conflicts in test-current.txt) --- core/java/android/net/EthernetManager.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 95000f5744..a3899b705c 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -17,7 +17,9 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.annotation.SystemService; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Handler; @@ -32,6 +34,8 @@ import java.util.Objects; * * @hide */ +@SystemApi +@TestApi @SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; @@ -62,12 +66,14 @@ public class EthernetManager { /** * A listener interface to receive notification on changes in Ethernet. + * @hide */ public interface Listener { /** * Called when Ethernet port's availability is changed. * @param iface Ethernet interface name * @param isAvailable {@code true} if Ethernet port exists. + * @hide */ @UnsupportedAppUsage void onAvailabilityChanged(String iface, boolean isAvailable); @@ -78,6 +84,7 @@ public class EthernetManager { * Applications will almost always want to use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}. + * @hide */ public EthernetManager(Context context, IEthernetManager service) { mContext = context; @@ -87,6 +94,7 @@ public class EthernetManager { /** * Get Ethernet configuration. * @return the Ethernet Configuration, contained in {@link IpConfiguration}. + * @hide */ @UnsupportedAppUsage public IpConfiguration getConfiguration(String iface) { @@ -99,6 +107,7 @@ public class EthernetManager { /** * Set Ethernet configuration. + * @hide */ @UnsupportedAppUsage public void setConfiguration(String iface, IpConfiguration config) { @@ -111,6 +120,7 @@ public class EthernetManager { /** * Indicates whether the system currently has one or more Ethernet interfaces. + * @hide */ @UnsupportedAppUsage public boolean isAvailable() { @@ -121,6 +131,7 @@ public class EthernetManager { * Indicates whether the system has given interface. * * @param iface Ethernet interface name + * @hide */ @UnsupportedAppUsage public boolean isAvailable(String iface) { @@ -135,6 +146,7 @@ public class EthernetManager { * Adds a listener. * @param listener A {@link Listener} to add. * @throws IllegalArgumentException If the listener is null. + * @hide */ @UnsupportedAppUsage public void addListener(Listener listener) { @@ -153,6 +165,7 @@ public class EthernetManager { /** * Returns an array of available Ethernet interface names. + * @hide */ @UnsupportedAppUsage public String[] getAvailableInterfaces() { @@ -167,6 +180,7 @@ public class EthernetManager { * Removes a listener. * @param listener A {@link Listener} to remove. * @throws IllegalArgumentException If the listener is null. + * @hide */ @UnsupportedAppUsage public void removeListener(Listener listener) { From 05742521b959b665246f8865d7f8d3cb9488e67d Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 22 Jan 2020 16:47:43 +0900 Subject: [PATCH 373/881] Make NetworkScore system API Bug: 146583853 Test: FrameworksNetTests Change-Id: Ie7b70750ef0e17141080f4266dea6155c3601569 --- .../ethernet/EthernetNetworkFactory.java | 71 ++++++++----------- 1 file changed, 30 insertions(+), 41 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 28f46061af..7f12a136bc 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,7 +16,6 @@ package com.android.server.ethernet; -import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; import static com.android.internal.util.Preconditions.checkNotNull; @@ -29,11 +28,11 @@ import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkProperties; import android.net.NetworkAgent; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.StringNetworkSpecifier; import android.net.ip.IIpClient; @@ -52,7 +51,6 @@ import android.util.SparseArray; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; -import java.lang.Math; import java.util.concurrent.ConcurrentHashMap; import java.util.Objects; @@ -68,6 +66,9 @@ public class EthernetNetworkFactory extends NetworkFactory { private final static int NETWORK_SCORE = 70; private static final String NETWORK_TYPE = "Ethernet"; + private final static NetworkScore NULL_SCORE = new NetworkScore.Builder() + .setRange(NetworkScore.RANGE_CLOSE) + .build(); private final ConcurrentHashMap mTrackingInterfaces = new ConcurrentHashMap<>(); @@ -221,12 +222,12 @@ public class EthernetNetworkFactory extends NetworkFactory { NetworkInterfaceState network = null; if (!TextUtils.isEmpty(requestedIface)) { NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface); - if (n != null && n.statisified(request.networkCapabilities)) { + if (n != null && n.satisfied(request.networkCapabilities)) { network = n; } } else { for (NetworkInterfaceState n : mTrackingInterfaces.values()) { - if (n.statisified(request.networkCapabilities) && n.mLinkUp) { + if (n.satisfied(request.networkCapabilities) && n.mLinkUp) { network = n; break; } @@ -247,8 +248,8 @@ public class EthernetNetworkFactory extends NetworkFactory { private final NetworkCapabilities mCapabilities; private final Handler mHandler; private final Context mContext; - private final NetworkInfo mNetworkInfo; private final NetworkFactory mNetworkFactory; + private final int mLegacyType; private static String sTcpBufferSizes = null; // Lazy initialized. @@ -375,9 +376,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } mHwAddress = hwAddress; - mNetworkInfo = new NetworkInfo(legacyType, 0, NETWORK_TYPE, ""); - mNetworkInfo.setExtraInfo(mHwAddress); - mNetworkInfo.setIsAvailable(true); + mLegacyType = legacyType; } void setIpConfig(IpConfiguration ipConfig) { @@ -386,12 +385,12 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } this.mIpConfig = ipConfig; - if (mNetworkInfo.getDetailedState() != DetailedState.DISCONNECTED) { + if (mNetworkAgent != null) { restart(); } } - boolean statisified(NetworkCapabilities requestedCapabilities) { + boolean satisfied(NetworkCapabilities requestedCapabilities) { return requestedCapabilities.satisfiedByNetworkCapabilities(mCapabilities); } @@ -421,23 +420,23 @@ public class EthernetNetworkFactory extends NetworkFactory { * This function is called with the purpose of assigning and updating the network score of * the member NetworkAgent. */ - private int getNetworkScore() { + private NetworkScore getNetworkScore() { // never set the network score below 0. if (!mLinkUp) { - return 0; + return NULL_SCORE; } int[] transportTypes = mCapabilities.getTransportTypes(); if (transportTypes.length < 1) { Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no " + "transport type associated with it. Score set to zero"); - return 0; + return NULL_SCORE; } TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null); if (transportInfo != null) { - return transportInfo.mScore; + return new NetworkScore.Builder().setLegacyScore(transportInfo.mScore).build(); } - return 0; + return NULL_SCORE; } private void start() { @@ -446,11 +445,9 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } if (DBG) { - Log.d(TAG, String.format("starting IpClient(%s): mNetworkInfo=%s", name, - mNetworkInfo)); + Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name)); } - mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress); mIpClientCallback = new IpClientCallbacksImpl(); IpClientUtil.makeIpClient(mContext, name, mIpClientCallback); mIpClientCallback.awaitIpClientStart(); @@ -468,13 +465,16 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } mLinkProperties = linkProperties; - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddress); - mNetworkInfo.setIsAvailable(true); // Create our NetworkAgent. - mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, - NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties, - getNetworkScore(), mNetworkFactory.getSerialNumber()) { + // STOPSHIP : use the new constructor for NetworkAgent that takes a NetworkScore + final NetworkAgentConfig config = new NetworkAgentConfig.Builder() + .setLegacyType(mLegacyType) + .setLegacyTypeName(NETWORK_TYPE) + .build(); + mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(), + NETWORK_TYPE, mCapabilities, mLinkProperties, + getNetworkScore(), config, mNetworkFactory.getProvider()) { public void unwanted() { if (this == mNetworkAgent) { stop(); @@ -484,6 +484,9 @@ public class EthernetNetworkFactory extends NetworkFactory { } // Otherwise, we've already called stop. } }; + mNetworkAgent.register(); + mNetworkAgent.setLegacyExtraInfo(mHwAddress); + mNetworkAgent.setConnected(); } void onIpLayerStopped(LinkProperties linkProperties) { @@ -526,16 +529,11 @@ public class EthernetNetworkFactory extends NetworkFactory { } mIpClientCallback = null; - // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object - // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: - // that sets the state to IDLE, and ConnectivityService will still think we're connected. - // - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddress); if (mNetworkAgent != null) { - updateAgent(); + mNetworkAgent.unregister(); mNetworkAgent = null; } - clear(); + mLinkProperties.clear(); } private void updateAgent() { @@ -543,11 +541,9 @@ public class EthernetNetworkFactory extends NetworkFactory { if (DBG) { Log.i(TAG, "Updating mNetworkAgent with: " + mCapabilities + ", " + - mNetworkInfo + ", " + mLinkProperties); } mNetworkAgent.sendNetworkCapabilities(mCapabilities); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); mNetworkAgent.sendLinkProperties(mLinkProperties); // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now @@ -556,12 +552,6 @@ public class EthernetNetworkFactory extends NetworkFactory { mNetworkAgent.sendNetworkScore(getNetworkScore()); } - private void clear() { - mLinkProperties.clear(); - mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null); - mNetworkInfo.setIsAvailable(false); - } - private static void provisionIpClient(IIpClient ipClient, IpConfiguration config, String tcpBufferSizes) { if (config.getProxySettings() == ProxySettings.STATIC || @@ -612,7 +602,6 @@ public class EthernetNetworkFactory extends NetworkFactory { + "iface: " + name + ", " + "up: " + mLinkUp + ", " + "hwAddress: " + mHwAddress + ", " - + "networkInfo: " + mNetworkInfo + ", " + "networkCapabilities: " + mCapabilities + ", " + "networkAgent: " + mNetworkAgent + ", " + "score: " + getNetworkScore() + ", " From eb7777b7e00dc3538b164254b218ea69c65d36d9 Mon Sep 17 00:00:00 2001 From: Milim Lee Date: Fri, 31 Jan 2020 11:33:32 +0900 Subject: [PATCH 374/881] Set Ethernet default mode as CLIENT Bug: 130840861 Test: build, boot atest EthernetTrackerTest manual test (using Ethernet) Change-Id: I935ea2e5f214aced67fb60f4aec2744077177545 --- service-t/src/com/android/server/ethernet/EthernetTracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 24616b78dc..58803d14fe 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -90,7 +90,7 @@ final class EthernetTracker { // Used only on the handler thread private String mDefaultInterface; - private int mDefaultInterfaceMode; + private int mDefaultInterfaceMode = INTERFACE_MODE_CLIENT; // Tracks whether clients were notified that the tethered interface is available private boolean mTetheredInterfaceWasAvailable = false; private volatile IpConfiguration mIpConfigForDefaultInterface; From 950d79e145c190b33271f58e418b94186bc1d2ef Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 8 Jan 2020 20:34:36 +0800 Subject: [PATCH 375/881] [SP10] Add IntDef annotations for system api of NetworkStats Test: m -j Bug: 130855321 Change-Id: I8855ec95d5d086fc14e2eb71558bc2dcd9a830e5 --- core/java/android/net/NetworkStats.java | 62 +++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 96d7a80886..2f536ffd8c 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -18,6 +18,7 @@ package android.net; import static android.os.Process.CLAT_UID; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -35,6 +36,8 @@ import libcore.util.EmptyArray; import java.io.CharArrayWriter; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.HashSet; import java.util.Map; @@ -100,6 +103,19 @@ public final class NetworkStats implements Parcelable { */ public static final int SET_DBG_VPN_OUT = 1002; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "SET_" }, value = { + SET_ALL, + SET_DEFAULT, + SET_FOREGROUND, + SET_DEBUG_START, + SET_DBG_VPN_IN, + SET_DBG_VPN_OUT + }) + public @interface State { + } + /** * Include all interfaces when filtering * @hide @@ -120,6 +136,17 @@ public final class NetworkStats implements Parcelable { /** {@link #metered} value where metered data is accounted. */ public static final int METERED_YES = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "METERED_" }, value = { + METERED_ALL, + METERED_NO, + METERED_YES + }) + public @interface Meteredness { + } + + /** * {@link #roaming} value to account for all roaming states. * @hide @@ -130,6 +157,16 @@ public final class NetworkStats implements Parcelable { /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "ROAMING_" }, value = { + ROAMING_ALL, + ROAMING_NO, + ROAMING_YES + }) + public @interface Roaming { + } + /** * {@link #onDefaultNetwork} value to account for all default network states. * @hide @@ -140,6 +177,16 @@ public final class NetworkStats implements Parcelable { /** {@link #onDefaultNetwork} value to account for usage while the default network. */ public static final int DEFAULT_NETWORK_YES = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "DEFAULT_NETWORK_" }, value = { + DEFAULT_NETWORK_ALL, + DEFAULT_NETWORK_NO, + DEFAULT_NETWORK_YES + }) + public @interface DefaultNetwork { + } + /** * Denotes a request for stats at the interface level. * @hide @@ -151,6 +198,15 @@ public final class NetworkStats implements Parcelable { */ public static final int STATS_PER_UID = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "STATS_PER_" }, value = { + STATS_PER_IFACE, + STATS_PER_UID + }) + public @interface StatsType { + } + private static final String CLATD_INTERFACE_PREFIX = "v4-"; // Delta between IPv4 header (20b) and IPv6 header (40b). // Used for correct stats accounting on clatd interfaces. @@ -263,9 +319,9 @@ public final class NetworkStats implements Parcelable { rxBytes, rxPackets, txBytes, txPackets, operations); } - public Entry(@Nullable String iface, int uid, int set, int tag, int metered, int roaming, - int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, - long operations) { + public Entry(@Nullable String iface, int uid, @State int set, int tag, + @Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork, + long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { this.iface = iface; this.uid = uid; this.set = set; From d7fc38a1cb358daf9228c2992d30ac5019c1aff3 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 12 Nov 2019 22:31:51 -0800 Subject: [PATCH 376/881] Implement Ikev2VpnRunner This change adds the implementation for IKEv2/IPsec VPNs. Bug: 144246767 Test: Manually tested Change-Id: I5ccec756cec49ccf57ccc4d5ad800eeb5d595a76 --- core/java/android/net/IpSecManager.java | 2 +- .../java/com/android/server/IpSecService.java | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 09ec6c35fc..d83715c692 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -51,7 +51,7 @@ import java.net.Socket; * *

Note that not all aspects of IPsec are permitted by this API. Applications may create * transport mode security associations and apply them to individual sockets. Applications looking - * to create a VPN should use {@link VpnService}. + * to create an IPsec VPN should use {@link VpnManager} and {@link Ikev2VpnProfile}. * * @see RFC 4301, Security Architecture for the * Internet Protocol diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index c98762074b..9540f43364 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1556,16 +1556,16 @@ public class IpSecService extends IIpSecService.Stub { } Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels"); - switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) { - case AppOpsManager.MODE_DEFAULT: - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); - break; - case AppOpsManager.MODE_ALLOWED: - return; - default: - throw new SecurityException("Request to ignore AppOps for non-legacy API"); + + // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system + // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS + // permission or is the System Server. + if (AppOpsManager.MODE_ALLOWED == getAppOpsManager().noteOpNoThrow( + TUNNEL_OP, Binder.getCallingUid(), callingPackage)) { + return; } + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); } private void createOrUpdateTransform( From 514983cc3efb1fb4d51d79c043a66fb01d556343 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 12 Nov 2019 22:31:51 -0800 Subject: [PATCH 377/881] Implement Ikev2VpnRunner This change adds the implementation for IKEv2/IPsec VPNs. Bug: 144246767 Test: Manually tested Change-Id: I5ccec756cec49ccf57ccc4d5ad800eeb5d595a76 Merged-In: I5ccec756cec49ccf57ccc4d5ad800eeb5d595a76 --- core/java/android/net/IpSecManager.java | 2 +- .../java/com/android/server/IpSecService.java | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 09ec6c35fc..d83715c692 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -51,7 +51,7 @@ import java.net.Socket; * *

Note that not all aspects of IPsec are permitted by this API. Applications may create * transport mode security associations and apply them to individual sockets. Applications looking - * to create a VPN should use {@link VpnService}. + * to create an IPsec VPN should use {@link VpnManager} and {@link Ikev2VpnProfile}. * * @see RFC 4301, Security Architecture for the * Internet Protocol diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index a629b3fbb8..98ac4cb712 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1557,16 +1557,16 @@ public class IpSecService extends IIpSecService.Stub { } checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); - switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) { - case AppOpsManager.MODE_DEFAULT: - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); - break; - case AppOpsManager.MODE_ALLOWED: - return; - default: - throw new SecurityException("Request to ignore AppOps for non-legacy API"); + + // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system + // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS + // permission or is the System Server. + if (AppOpsManager.MODE_ALLOWED == getAppOpsManager().noteOpNoThrow( + TUNNEL_OP, Binder.getCallingUid(), callingPackage)) { + return; } + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService"); } private void createOrUpdateTransform( From b375131b031e6ea56b190e7dcf58c5b75aabe4f8 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 14 Jan 2020 18:41:08 +0800 Subject: [PATCH 378/881] [SP12] Remove the usage of getVtDataUsage Currently NetworkStatsService holding a lock when invoking getVtDataUsage, which causes a lot of deadlock problems since Phone will also have binder calls to system_server. Thus, this change uses a new set of API to break such situation, that allows VT to report stats asynchronously. Test: atest FrameworksNetTests FrameworksTelephonyTests Bug: 130855321 Fix: 143923500 Change-Id: Ifdb8599c3bade09208b4730710fc99da1afad71d --- .../server/net/NetworkStatsService.java | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index fc39a253bc..60af1d6bc2 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1249,7 +1249,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt"); - final NetworkStats xtSnapshot = getNetworkStatsXt(); + final NetworkStats xtSnapshot = readNetworkStatsSummaryXt(); Trace.traceEnd(TRACE_TAG_NETWORK); Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev"); final NetworkStats devSnapshot = readNetworkStatsSummaryDev(); @@ -1707,18 +1707,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mUseBpfTrafficStats); uidSnapshot.combineAllValues(tetherSnapshot); - final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( - Context.TELEPHONY_SERVICE); - - // fold video calling data usage stats into uid snapshot - final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); - if (vtStats != null) { - vtStats.filter(UID_ALL, ifaces, TAG_ALL); - mStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats, - mUseBpfTrafficStats); - uidSnapshot.combineAllValues(vtStats); - } - // get a stale copy of uid stats snapshot provided by providers. final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID); providerStats.filter(UID_ALL, ifaces, TAG_ALL); @@ -1730,24 +1718,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return uidSnapshot; } - /** - * Return snapshot of current XT statistics with video calling data usage statistics. - */ - private NetworkStats getNetworkStatsXt() throws RemoteException { - final NetworkStats xtSnapshot = readNetworkStatsSummaryXt(); - - final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( - Context.TELEPHONY_SERVICE); - - // Merge video calling data usage into XT - final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE); - if (vtSnapshot != null) { - xtSnapshot.combineAllValues(vtSnapshot); - } - - return xtSnapshot; - } - /** * Return snapshot of current tethering statistics. Will return empty * {@link NetworkStats} if any problems are encountered. From 0d16cdde0f7604f4129eee95fe46a01a0a9ebc81 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 21 Jan 2020 13:52:04 +0800 Subject: [PATCH 379/881] [SP16] Address comments on aosp/1172143 Test: atest FrameworksNetTests Test: atest NetworkPolicyManagerServiceTest Test: m doc-comment-check-docs Bug: 130855321 Change-Id: Iccaab09f5b9668ec4a7249737c64a69cecb08d15 --- .../app/usage/NetworkStatsManager.java | 16 ++++++++------ .../server/net/NetworkStatsService.java | 22 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 9c4a8f4fbe..5b98188300 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -526,15 +526,17 @@ public class NetworkStatsManager { } /** - * Registers a custom provider of {@link android.net.NetworkStats} to combine the network - * statistics that cannot be seen by the kernel to system. To unregister, invoke - * {@link NetworkStatsProviderCallback#unregister()}. + * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics + * to the system. To unregister, invoke {@link NetworkStatsProviderCallback#unregister()}. + * Note that no de-duplication of statistics between providers is performed, so each provider + * must only report network traffic that is not being reported by any other provider. * - * @param tag a human readable identifier of the custom network stats provider. - * @param provider a custom implementation of {@link AbstractNetworkStatsProvider} that needs to - * be registered to the system. + * @param tag a human readable identifier of the custom network stats provider. This is only + * used for debugging. + * @param provider the subclass of {@link AbstractNetworkStatsProvider} that needs to be + * registered to the system. * @return a {@link NetworkStatsProviderCallback}, which can be used to report events to the - * system. + * system or unregister the provider. * @hide */ @SystemApi diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 415ccb8fe8..2af6e349ff 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -255,7 +255,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private final Object mStatsLock = new Object(); - private final Object mStatsProviderLock = new Object(); /** Set of currently active ifaces. */ @GuardedBy("mStatsLock") @@ -1501,8 +1500,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void setStatsProviderLimit(@NonNull String iface, long quota) { - Slog.v(TAG, "setStatsProviderLimit(" + iface + "," + quota + ")"); + public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { + Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setLimit(iface, quota)); } } @@ -1783,9 +1782,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * {@code unregister()} of the returned callback. * * @param tag a human readable identifier of the custom network stats provider. - * @param provider the binder interface of - * {@link android.net.netstats.provider.AbstractNetworkStatsProvider} that - * needs to be registered to the system. + * @param provider the {@link INetworkStatsProvider} binder corresponding to the + * {@link android.net.netstats.provider.AbstractNetworkStatsProvider} to be + * registered. * * @return a binder interface of * {@link android.net.netstats.provider.NetworkStatsProviderCallback}, which can be @@ -1823,7 +1822,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void invokeForAllStatsProviderCallbacks( @NonNull ThrowingConsumer task) { - synchronized (mStatsProviderCbList) { + synchronized (mStatsLock) { final int length = mStatsProviderCbList.beginBroadcast(); try { for (int i = 0; i < length; i++) { @@ -1844,13 +1843,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static class NetworkStatsProviderCallbackImpl extends INetworkStatsProviderCallback.Stub implements IBinder.DeathRecipient { @NonNull final String mTag; - @NonNull private final Object mProviderStatsLock = new Object(); + @NonNull final INetworkStatsProvider mProvider; @NonNull final INetworkManagementEventObserver mAlertObserver; @NonNull final RemoteCallbackList mStatsProviderCbList; + @NonNull private final Object mProviderStatsLock = new Object(); + @GuardedBy("mProviderStatsLock") - // STATS_PER_IFACE and STATS_PER_UID + // Track STATS_PER_IFACE and STATS_PER_UID separately. private final NetworkStats mIfaceStats = new NetworkStats(0L, 0); @GuardedBy("mProviderStatsLock") private final NetworkStats mUidStats = new NetworkStats(0L, 0); @@ -1881,7 +1882,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { default: throw new IllegalArgumentException("Invalid type: " + how); } - // Return a defensive copy instead of local reference. + // Callers might be able to mutate the returned object. Return a defensive copy + // instead of local reference. return stats.clone(); } } From 137e140e1035c9cd0fd82d29325edf256e80eb38 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 12 Feb 2020 14:55:54 +0800 Subject: [PATCH 380/881] [SP17] Wait for stats providers to report stats update From current design, the traffic accounted by stats providers will be updated asynchronously when force polling. When upper layer make two subsequently queries. They will get stale stats upon the first query, and may get newest/stale stats base on the result of race. Thus, wait for a bit of time to allow asynchronous stats update complete to reduce the chance of race. In pratice, it would be finished in ~2ms when testing. Test: systrace.py network Test: atest FrameworksNetTests Bug: 147460444 Change-Id: I22a00fc4049cddf77fd578e25769ae1979f2cc6d --- .../server/net/NetworkStatsService.java | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 415ccb8fe8..1c52110449 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -155,6 +155,8 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; /** * Collect and persist detailed network statistics, and provide this data to @@ -280,8 +282,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); + private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100; private final RemoteCallbackList mStatsProviderCbList = new RemoteCallbackList<>(); + /** Semaphore used to wait for stats provider to respond to request stats update. */ + private final Semaphore mStatsProviderSem = new Semaphore(0, true); @GuardedBy("mStatsLock") private NetworkStatsRecorder mDevRecorder; @@ -1337,6 +1342,25 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0; final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; + // Request asynchronous stats update from all providers for next poll. And wait a bit of + // time to allow providers report-in given that normally binder call should be fast. + // TODO: request with a valid token. + Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); + final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount(); + mStatsProviderSem.drainPermits(); + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */)); + try { + mStatsProviderSem.tryAcquire(registeredCallbackCount, + MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + // Strictly speaking it's possible a provider happened to deliver between the timeout + // and the log, and that doesn't matter too much as this is just a debug log. + Log.d(TAG, "requestStatsUpdate - providers responded " + + mStatsProviderSem.availablePermits() + + "/" + registeredCallbackCount + " : " + e); + } + Trace.traceEnd(TRACE_TAG_NETWORK); + // TODO: consider marking "untrusted" times in historical stats final long currentTime = mClock.millis(); @@ -1374,10 +1398,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performSampleLocked(); } - // request asynchronous stats update from all providers for next poll. - // TODO: request with a valid token. - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */)); - // finally, dispatch updated event to any listeners final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); @@ -1798,7 +1818,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Objects.requireNonNull(tag, "tag is null"); try { NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl( - tag, provider, mAlertObserver, mStatsProviderCbList); + tag, provider, mStatsProviderSem, mAlertObserver, + mStatsProviderCbList); mStatsProviderCbList.register(callback); Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid=" + getCallingUid() + "/" + getCallingPid()); @@ -1846,6 +1867,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull final String mTag; @NonNull private final Object mProviderStatsLock = new Object(); @NonNull final INetworkStatsProvider mProvider; + @NonNull private final Semaphore mSemaphore; @NonNull final INetworkManagementEventObserver mAlertObserver; @NonNull final RemoteCallbackList mStatsProviderCbList; @@ -1857,12 +1879,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsProviderCallbackImpl( @NonNull String tag, @NonNull INetworkStatsProvider provider, + @NonNull Semaphore semaphore, @NonNull INetworkManagementEventObserver alertObserver, @NonNull RemoteCallbackList cbList) throws RemoteException { mTag = tag; mProvider = provider; mProvider.asBinder().linkToDeath(this, 0); + mSemaphore = semaphore; mAlertObserver = alertObserver; mStatsProviderCbList = cbList; } @@ -1895,6 +1919,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (ifaceStats != null) mIfaceStats.combineAllValues(ifaceStats); if (uidStats != null) mUidStats.combineAllValues(uidStats); } + mSemaphore.release(); } @Override From 466e2e953b3bd2afda835cab6b81838b41b54a1b Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 24 Feb 2020 19:17:42 +0800 Subject: [PATCH 381/881] Add permission check functions to NetworkStatsService This is shameless copied from ConnectivityService and plan to be used in follow-up change. For long term perspective we should have a permission util that contains those util in one place. Test: m -j Change-Id: I837545b54f36c8f21c878cbb1fd028ff23be6cb8 --- .../server/net/NetworkStatsService.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 896bf676d4..211d496a5b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -23,6 +23,7 @@ import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkStack.checkNetworkStackPermission; @@ -1766,6 +1767,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + // TODO: It is copied from ConnectivitySerivce, consider refactor these check permission + // functions to a proper util. + private boolean checkAnyPermissionOf(String... permissions) { + for (String permission : permissions) { + if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { + return true; + } + } + return false; + } + + private void enforceAnyPermissionOf(String... permissions) { + if (!checkAnyPermissionOf(permissions)) { + throw new SecurityException("Requires one of the following permissions: " + + String.join(", ", permissions) + "."); + } + } + /** * Registers a custom provider of {@link android.net.NetworkStats} to combine the network * statistics that cannot be seen by the kernel to system. To unregister, invoke the From 1c20161672fa78addaf15116a209b1c207a37751 Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 24 Feb 2020 18:16:54 +0800 Subject: [PATCH 382/881] [SP20] Check signature permission when accessing network stats provider Currently, registerNetworkStatsProvider requires the UPDATE_DEVICE_STATS permission. This is a privileged permission so it can be granted to preinstalled apps. Thus, apps like GmsCore, or preinstalled apps will be able to update network stats. This change checks for a new permission that would only allow signature apps to declare that. Also check MAINLINE_NETWORK_STACK permission to allow NetworkStack process to use it. Test: adb shell dumpsys netstats Test: atest FrameworksNetTests Bug: 149652079 Change-Id: Idfebd0a1988c3dcfd812d87e30f6a2034d6fbf6b --- core/java/android/app/usage/NetworkStatsManager.java | 5 ++++- .../java/com/android/server/net/NetworkStatsService.java | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 5b98188300..7d13f050a7 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -29,6 +29,7 @@ import android.net.ConnectivityManager; import android.net.DataUsageRequest; import android.net.INetworkStatsService; import android.net.NetworkIdentity; +import android.net.NetworkStack; import android.net.NetworkTemplate; import android.net.netstats.provider.AbstractNetworkStatsProvider; import android.net.netstats.provider.NetworkStatsProviderCallback; @@ -540,7 +541,9 @@ public class NetworkStatsManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STATS_PROVIDER, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) @NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider( @NonNull String tag, @NonNull AbstractNetworkStatsProvider provider) { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 211d496a5b..9e5f704e83 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.NETWORK_STATS_PROVIDER; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.content.Intent.ACTION_SHUTDOWN; @@ -1801,7 +1802,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider( @NonNull String tag, @NonNull INetworkStatsProvider provider) { - mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG); + enforceAnyPermissionOf(NETWORK_STATS_PROVIDER, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); Objects.requireNonNull(provider, "provider is null"); Objects.requireNonNull(tag, "tag is null"); try { From e3576345d62d85d2d93fb3ee334747cf3a0af851 Mon Sep 17 00:00:00 2001 From: markchien Date: Wed, 26 Feb 2020 20:54:55 +0800 Subject: [PATCH 383/881] Fix crash and duplicated ethernet tethering request This change fix two things: 1. Handle ethernet callback in internal thread to avoid crash. IpServer should be created from tethering thread, otherwise mIpNeighborMonitor of IpServer would throw IllegalStateException("start() called from off-thread") 2. Ethernet tethering request may be duplicated if multiple startTethering is called but no stopTethering Bug: 130840861 Bug: 148824036 Test: ON/OFF ethernet tehtering manually atest TetheringTests Change-Id: I7c5127e96d80d077735010d2e62c7227805ccb10 --- core/java/android/net/EthernetManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index a3899b705c..139f5bebcd 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -28,6 +28,7 @@ import android.os.RemoteException; import java.util.ArrayList; import java.util.Objects; +import java.util.concurrent.Executor; /** * A class representing the IP configuration of the Ethernet network. @@ -248,18 +249,19 @@ public class EthernetManager { * @param callback A callback to be called once the request has been fulfilled. */ @NonNull - public TetheredInterfaceRequest requestTetheredInterface( - @NonNull TetheredInterfaceCallback callback) { + public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor, + @NonNull final TetheredInterfaceCallback callback) { Objects.requireNonNull(callback, "Callback must be non-null"); + Objects.requireNonNull(executor, "Executor must be non-null"); final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() { @Override public void onAvailable(String iface) { - callback.onAvailable(iface); + executor.execute(() -> callback.onAvailable(iface)); } @Override public void onUnavailable() { - callback.onUnavailable(); + executor.execute(() -> callback.onUnavailable()); } }; From 534f6e7891cdb88251fb7821b4aa0d8122fa75be Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 21 Feb 2020 19:52:43 +0900 Subject: [PATCH 384/881] Revert part of 05742521b959b665246f8865d7f8d3cb9488e67d This reverts the parts of the above commit that have to do with NetworkScore. The parts that convert the factory to the new NetworkAgent API are conserved. Bug: 113554781 Test: FrameworksNetTests Change-Id: If2c368e084e29f9f358f43dcd547d42e8c7c4846 --- .../server/ethernet/EthernetNetworkFactory.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 7f12a136bc..1c835062ba 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -32,7 +32,6 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkRequest; -import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.StringNetworkSpecifier; import android.net.ip.IIpClient; @@ -66,9 +65,6 @@ public class EthernetNetworkFactory extends NetworkFactory { private final static int NETWORK_SCORE = 70; private static final String NETWORK_TYPE = "Ethernet"; - private final static NetworkScore NULL_SCORE = new NetworkScore.Builder() - .setRange(NetworkScore.RANGE_CLOSE) - .build(); private final ConcurrentHashMap mTrackingInterfaces = new ConcurrentHashMap<>(); @@ -420,23 +416,23 @@ public class EthernetNetworkFactory extends NetworkFactory { * This function is called with the purpose of assigning and updating the network score of * the member NetworkAgent. */ - private NetworkScore getNetworkScore() { + private int getNetworkScore() { // never set the network score below 0. if (!mLinkUp) { - return NULL_SCORE; + return 0; } int[] transportTypes = mCapabilities.getTransportTypes(); if (transportTypes.length < 1) { Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no " + "transport type associated with it. Score set to zero"); - return NULL_SCORE; + return 0; } TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null); if (transportInfo != null) { - return new NetworkScore.Builder().setLegacyScore(transportInfo.mScore).build(); + return transportInfo.mScore; } - return NULL_SCORE; + return 0; } private void start() { @@ -467,7 +463,6 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkProperties = linkProperties; // Create our NetworkAgent. - // STOPSHIP : use the new constructor for NetworkAgent that takes a NetworkScore final NetworkAgentConfig config = new NetworkAgentConfig.Builder() .setLegacyType(mLegacyType) .setLegacyTypeName(NETWORK_TYPE) From 8005a2285fa071b7b59e6d23801240a1e6a59c8d Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 6 Jan 2020 20:22:17 +0800 Subject: [PATCH 385/881] Move DnsSdTxtRecord to net common static library DnsSdTxtRecord is moved to frameworks/libs/net for mainline support. Also change the import path using this class. Bug: 139268426 Bug: 135998869 Test: atest FrameworksNetTests ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: I6118b313ce668707d598aa2eab9baee2f7622dbc Merged-In: I6118b313ce668707d598aa2eab9baee2f7622dbc --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index b9b7bf73c1..4a1820a8e5 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -22,10 +22,10 @@ import android.content.Intent; import android.database.ContentObserver; import android.net.NetworkStack; import android.net.Uri; -import android.net.nsd.DnsSdTxtRecord; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; +import android.net.util.nsd.DnsSdTxtRecord; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; From 28561caf5858ba9f6691a4e4c6c3d707b74ebdd9 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 3 Mar 2020 15:53:56 +0800 Subject: [PATCH 386/881] Remove setHandler in NetworkStatsService Currently, internal handler is set by setHandler after constructing NSS object. This was introduced in ag/866187 to access the handler in the unit test. However, the design put NSS in a bad situation where all classes that need handler or executor could not be final and need to be dynamically allocated in order to get a valid handler. Thus, since the usage of handler is removed in previous patch, this change eliminate setHandler by initializing the handler in the constructor. Test: atest FrameworksNetTests Bug: 150664039 Change-Id: I794a24d00b0ca9fdc78091e7b9ab7307e0f034b7 --- .../server/net/NetworkStatsService.java | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 896bf676d4..66e691a79f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -306,9 +306,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); - /** Must be set in factory by calling #setHandler. */ - private Handler mHandler; - private Handler.Callback mHandlerCallback; + @NonNull + private final Handler mHandler; private volatile boolean mSystemReady; private long mPersistThreshold = 2 * MB_IN_BYTES; @@ -324,6 +323,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final static int DUMP_STATS_SESSION_COUNT = 20; + @NonNull + private final Dependencies mDeps; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -339,9 +341,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Clock.systemUTC()); } - private static final class NetworkStatsHandler extends Handler { - NetworkStatsHandler(Looper looper, Handler.Callback callback) { - super(looper, callback); + private final class NetworkStatsHandler extends Handler { + NetworkStatsHandler(@NonNull Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_PERFORM_POLL: { + performPoll(FLAG_PERSIST_ALL); + break; + } + case MSG_PERFORM_POLL_REGISTER_ALERT: { + performPoll(FLAG_PERSIST_NETWORK); + registerGlobalAlert(); + break; + } + } } } @@ -355,14 +372,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), - new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); + new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), + new Dependencies()); service.registerLocalService(); - HandlerThread handlerThread = new HandlerThread(TAG); - Handler.Callback callback = new HandlerCallback(service); - handlerThread.start(); - Handler handler = new NetworkStatsHandler(handlerThread.getLooper(), callback); - service.setHandler(handler, callback); return service; } @@ -373,7 +386,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, TelephonyManager teleManager, NetworkStatsSettings settings, NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, - File baseDir) { + File baseDir, @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); mNetworkManager = Objects.requireNonNull(networkManager, "missing INetworkManagementService"); @@ -387,6 +400,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir"); mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir"); mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists(); + mDeps = Objects.requireNonNull(deps, "missing Dependencies"); + + final HandlerThread handlerThread = mDeps.makeHandlerThread(); + handlerThread.start(); + mHandler = new NetworkStatsHandler(handlerThread.getLooper()); + } + + /** + * Dependencies of NetworkStatsService, for injection in tests. + */ + // TODO: Move more stuff into dependencies object. + @VisibleForTesting + public static class Dependencies { + /** + * Create a HandlerThread to use in NetworkStatsService. + */ + @NonNull + public HandlerThread makeHandlerThread() { + return new HandlerThread(TAG); + } } private void registerLocalService() { @@ -394,12 +427,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { new NetworkStatsManagerInternalImpl()); } - @VisibleForTesting - void setHandler(Handler handler, Handler.Callback callback) { - mHandler = handler; - mHandlerCallback = callback; - } - public void systemReady() { synchronized (mStatsLock) { mSystemReady = true; @@ -1920,33 +1947,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } - @VisibleForTesting - static class HandlerCallback implements Handler.Callback { - private final NetworkStatsService mService; - - HandlerCallback(NetworkStatsService service) { - this.mService = service; - } - - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_PERFORM_POLL: { - mService.performPoll(FLAG_PERSIST_ALL); - return true; - } - case MSG_PERFORM_POLL_REGISTER_ALERT: { - mService.performPoll(FLAG_PERSIST_NETWORK); - mService.registerGlobalAlert(); - return true; - } - default: { - return false; - } - } - } - } - private void assertSystemReady() { if (!mSystemReady) { throw new IllegalStateException("System not ready"); From f90ad41c071632c1cb57f99c7773b0654e2679a4 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Fri, 28 Feb 2020 03:42:44 +0000 Subject: [PATCH 387/881] Fix crash and duplicated ethernet tethering request This change fix two things: 1. Handle ethernet callback in internal thread to avoid crash. IpServer should be created from tethering thread, otherwise mIpNeighborMonitor of IpServer would throw IllegalStateException("start() called from off-thread") 2. Ethernet tethering request may be duplicated if multiple startTethering is called but no stopTethering Bug: 130840861 Bug: 148824036 Test: ON/OFF ethernet tehtering manually atest TetheringTests Change-Id: Ibd3ea6bc6751bd65647ff381f9b0124bc3395c09 Merged-In: I7c5127e96d80d077735010d2e62c7227805ccb10 Merged-In: Ibd3ea6bc6751bd65647ff381f9b0124bc3395c09 (cherry picked from commit 72702b979654234c18045f04270040056a74cf90) --- core/java/android/net/EthernetManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index a3899b705c..139f5bebcd 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -28,6 +28,7 @@ import android.os.RemoteException; import java.util.ArrayList; import java.util.Objects; +import java.util.concurrent.Executor; /** * A class representing the IP configuration of the Ethernet network. @@ -248,18 +249,19 @@ public class EthernetManager { * @param callback A callback to be called once the request has been fulfilled. */ @NonNull - public TetheredInterfaceRequest requestTetheredInterface( - @NonNull TetheredInterfaceCallback callback) { + public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor, + @NonNull final TetheredInterfaceCallback callback) { Objects.requireNonNull(callback, "Callback must be non-null"); + Objects.requireNonNull(executor, "Executor must be non-null"); final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() { @Override public void onAvailable(String iface) { - callback.onAvailable(iface); + executor.execute(() -> callback.onAvailable(iface)); } @Override public void onUnavailable() { - callback.onUnavailable(); + executor.execute(() -> callback.onUnavailable()); } }; From f94a6010c07f35ef0b2700ee6c377f00ca76b9ba Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 9 Mar 2020 13:56:18 +0900 Subject: [PATCH 388/881] Add missing RequiresPermission to EthernetManager The method requires NETWORK_STACK or MAINLINE_NETWORK_STACK permissions, but the annotation was missing. Test: m Fixes: 150877670 Change-Id: I2af74cbcfa642f05f5e7bf85b2a8e8c38595f6ca --- core/java/android/net/EthernetManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 139f5bebcd..83b5f63576 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; @@ -248,6 +249,10 @@ public class EthernetManager { * interface, the existing interface will be used. * @param callback A callback to be called once the request has been fulfilled. */ + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STACK, + android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) @NonNull public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor, @NonNull final TetheredInterfaceCallback callback) { From f5706306fbfc78962ce7dbe104ff45e00c95a1c0 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Wed, 4 Mar 2020 13:36:11 +0000 Subject: [PATCH 389/881] Merge NetworkStatsService handler changes. ===== Remove the need of accessing handler in NSS unit test Currently, to wait for handler becomes idle, specific message is used and the test would wait for condition variable to be open when the message is processed. However, this is already done in the HandlerUtils. Thus, there is no need to post such message manually in the handler. Test: atest FrameworksNetTests Bug: 150664039 Change-Id: Iab32b2dbab01634ca159dcb90fc9f929d1fed1a2 ===== Remove setHandler in NetworkStatsService Currently, internal handler is set by setHandler after constructing NSS object. This was introduced in ag/866187 to access the handler in the unit test. However, the design put NSS in a bad situation where all classes that need handler or executor could not be final and need to be dynamically allocated in order to get a valid handler. Thus, since the usage of handler is removed in previous patch, this change eliminate setHandler by initializing the handler in the constructor. Test: atest FrameworksNetTests Bug: 150664039 Change-Id: I794a24d00b0ca9fdc78091e7b9ab7307e0f034b7 ===== Bug: 150664039 Change-Id: If256ed4437ddcbcc72a6f766cff2f4cc512ee3f7 Merged-In: If256ed4437ddcbcc72a6f766cff2f4cc512ee3f7 (cherry picked from commit 2a6439d7e2a3926e10a0b9a4dc730b1a022d8138) --- .../server/net/NetworkStatsService.java | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index ee5a4fe248..4af31b0369 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -306,9 +306,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); - /** Must be set in factory by calling #setHandler. */ - private Handler mHandler; - private Handler.Callback mHandlerCallback; + @NonNull + private final Handler mHandler; private volatile boolean mSystemReady; private long mPersistThreshold = 2 * MB_IN_BYTES; @@ -324,6 +323,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final static int DUMP_STATS_SESSION_COUNT = 20; + @NonNull + private final Dependencies mDeps; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -339,9 +341,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Clock.systemUTC()); } - private static final class NetworkStatsHandler extends Handler { - NetworkStatsHandler(Looper looper, Handler.Callback callback) { - super(looper, callback); + private final class NetworkStatsHandler extends Handler { + NetworkStatsHandler(@NonNull Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_PERFORM_POLL: { + performPoll(FLAG_PERSIST_ALL); + break; + } + case MSG_PERFORM_POLL_REGISTER_ALERT: { + performPoll(FLAG_PERSIST_NETWORK); + registerGlobalAlert(); + break; + } + } } } @@ -355,14 +372,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), - new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir()); + new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), + new Dependencies()); service.registerLocalService(); - HandlerThread handlerThread = new HandlerThread(TAG); - Handler.Callback callback = new HandlerCallback(service); - handlerThread.start(); - Handler handler = new NetworkStatsHandler(handlerThread.getLooper(), callback); - service.setHandler(handler, callback); return service; } @@ -373,7 +386,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, TelephonyManager teleManager, NetworkStatsSettings settings, NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, - File baseDir) { + File baseDir, @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); mNetworkManager = Objects.requireNonNull(networkManager, "missing INetworkManagementService"); @@ -387,6 +400,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir"); mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir"); mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists(); + mDeps = Objects.requireNonNull(deps, "missing Dependencies"); + + final HandlerThread handlerThread = mDeps.makeHandlerThread(); + handlerThread.start(); + mHandler = new NetworkStatsHandler(handlerThread.getLooper()); + } + + /** + * Dependencies of NetworkStatsService, for injection in tests. + */ + // TODO: Move more stuff into dependencies object. + @VisibleForTesting + public static class Dependencies { + /** + * Create a HandlerThread to use in NetworkStatsService. + */ + @NonNull + public HandlerThread makeHandlerThread() { + return new HandlerThread(TAG); + } } private void registerLocalService() { @@ -394,12 +427,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { new NetworkStatsManagerInternalImpl()); } - @VisibleForTesting - void setHandler(Handler handler, Handler.Callback callback) { - mHandler = handler; - mHandlerCallback = callback; - } - public void systemReady() { synchronized (mStatsLock) { mSystemReady = true; @@ -1920,33 +1947,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } - @VisibleForTesting - static class HandlerCallback implements Handler.Callback { - private final NetworkStatsService mService; - - HandlerCallback(NetworkStatsService service) { - this.mService = service; - } - - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_PERFORM_POLL: { - mService.performPoll(FLAG_PERSIST_ALL); - return true; - } - case MSG_PERFORM_POLL_REGISTER_ALERT: { - mService.performPoll(FLAG_PERSIST_NETWORK); - mService.registerGlobalAlert(); - return true; - } - default: { - return false; - } - } - } - } - private void assertSystemReady() { if (!mSystemReady) { throw new IllegalStateException("System not ready"); From e91080987ff49a750303cc2ea303e7d1ebe9a872 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Mon, 9 Mar 2020 08:40:23 +0000 Subject: [PATCH 390/881] Add missing RequiresPermission to EthernetManager The method requires NETWORK_STACK or MAINLINE_NETWORK_STACK permissions, but the annotation was missing. Test: m Fixes: 150877670 Merged-In: I2af74cbcfa642f05f5e7bf85b2a8e8c38595f6ca (cherry picked from commit e45d3ff849695977cb063cc59550c505b220bd6c) Change-Id: Ia215b74df99ae60be2e380917be68a272d658ef4 --- core/java/android/net/EthernetManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 139f5bebcd..83b5f63576 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; @@ -248,6 +249,10 @@ public class EthernetManager { * interface, the existing interface will be used. * @param callback A callback to be called once the request has been fulfilled. */ + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STACK, + android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK + }) @NonNull public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor, @NonNull final TetheredInterfaceCallback callback) { From 261a430893e131a145ade912503fdc0cb57a9a19 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 11 Feb 2020 23:36:42 -0800 Subject: [PATCH 391/881] Relax IPsec resource count restrictions. IPsec resource counts were selected to be conservative, due to unknowns about device capabilities. Since then, it appears that we no longer need such stringent quotas, and this can be relaxed. Test: FrameworksNetTest passing Change-Id: Id53d14e5698e5fcc410868424176b00350c7ae79 --- .../core/java/com/android/server/IpSecService.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 98ac4cb712..15cbfb5c65 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -360,10 +360,14 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting static final class UserRecord { /* Maximum number of each type of resource that a single UID may possess */ - public static final int MAX_NUM_TUNNEL_INTERFACES = 2; - public static final int MAX_NUM_ENCAP_SOCKETS = 2; - public static final int MAX_NUM_TRANSFORMS = 4; - public static final int MAX_NUM_SPIS = 8; + + // Up to 4 active VPNs/IWLAN with potential soft handover. + public static final int MAX_NUM_TUNNEL_INTERFACES = 8; + public static final int MAX_NUM_ENCAP_SOCKETS = 16; + + // SPIs and Transforms are both cheap, and are 1:1 correlated. + public static final int MAX_NUM_TRANSFORMS = 64; + public static final int MAX_NUM_SPIS = 64; /** * Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing From 13f2ab82914200c3a2dd62e1618b1adc175293d7 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 11 Feb 2020 23:49:36 -0800 Subject: [PATCH 392/881] Automatically set IPsec tunnel interface as up This change makes IPsec tunnel interfaces automatically get brought up once they are created. Originally this was considered to be an additional safety check, as they would not be start routing traffic until explicitly brought up. However, in the intervening time, the NetworkManagementController now requires the NETWORK_STACK permission to set an interface as up. Additionally, that call is a hidden API, and thus not usable for use cases such as IWLAN. Bug: 149348618 Test: FrameworksNetTests, CtsNetTestCases passing. Change-Id: I55b63a748463a388e1e2991d2d5d6b3023545e60 --- .../java/com/android/server/IpSecService.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 15cbfb5c65..424407a957 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -48,6 +48,7 @@ import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; +import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -76,6 +77,7 @@ import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * A service to manage multiple clients that want to access the IpSec API. The service is @@ -115,6 +117,9 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; + /* NetworkManager instance */ + private final INetworkManagementService mNetworkManager; + /** * The next non-repeating global ID for tracking resources between users, this service, and * kernel data structures. Accessing this variable is not thread safe, so it is only read or @@ -993,12 +998,13 @@ public class IpSecService extends IIpSecService.Stub { * * @param context Binder context for this service */ - private IpSecService(Context context) { - this(context, IpSecServiceConfiguration.GETSRVINSTANCE); + private IpSecService(Context context, INetworkManagementService networkManager) { + this(context, networkManager, IpSecServiceConfiguration.GETSRVINSTANCE); } - static IpSecService create(Context context) throws InterruptedException { - final IpSecService service = new IpSecService(context); + static IpSecService create(Context context, INetworkManagementService networkManager) + throws InterruptedException { + final IpSecService service = new IpSecService(context, networkManager); service.connectNativeNetdService(); return service; } @@ -1012,9 +1018,11 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, IpSecServiceConfiguration config) { + public IpSecService(Context context, INetworkManagementService networkManager, + IpSecServiceConfiguration config) { this( context, + networkManager, config, (fd, uid) -> { try { @@ -1028,9 +1036,10 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService( - Context context, IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { + public IpSecService(Context context, INetworkManagementService networkManager, + IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { mContext = context; + mNetworkManager = Objects.requireNonNull(networkManager); mSrvConfig = config; mUidFdTagger = uidFdTagger; } @@ -1309,6 +1318,10 @@ public class IpSecService extends IIpSecService.Stub { final INetd netd = mSrvConfig.getNetdInstance(); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); + Binder.withCleanCallingIdentity(() -> { + mNetworkManager.setInterfaceUp(intfName); + }); + for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. netd.ipSecAddSecurityPolicy( From 6b65a8484b48c53728e71e07a1652b8db306ebc9 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 6 Mar 2020 14:50:48 +0800 Subject: [PATCH 393/881] [SP21] Address comments for API council review about aosp/1172143 Test: atest FrameworksNetTests ImsPhoneCallTrackerTest Test: atest TetheringTests NetworkStackTests Test: m doc-comment-check-docs Fix: 148552904 Change-Id: I141393f229e772d2eb9f7c156849e379bd71b845 --- .../app/usage/NetworkStatsManager.java | 48 +++-- .../provider/INetworkStatsProvider.aidl | 6 +- .../INetworkStatsProviderCallback.aidl | 6 +- .../provider/NetworkStatsProvider.java | 195 ++++++++++++++++++ .../server/net/NetworkStatsService.java | 23 +-- 5 files changed, 245 insertions(+), 33 deletions(-) create mode 100644 core/java/android/net/netstats/provider/NetworkStatsProvider.java diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 7d13f050a7..d6e77624a9 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -31,9 +31,8 @@ import android.net.INetworkStatsService; import android.net.NetworkIdentity; import android.net.NetworkStack; import android.net.NetworkTemplate; -import android.net.netstats.provider.AbstractNetworkStatsProvider; -import android.net.netstats.provider.NetworkStatsProviderCallback; -import android.net.netstats.provider.NetworkStatsProviderWrapper; +import android.net.netstats.provider.INetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; import android.os.Handler; import android.os.Looper; @@ -528,34 +527,53 @@ public class NetworkStatsManager { /** * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics - * to the system. To unregister, invoke {@link NetworkStatsProviderCallback#unregister()}. + * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}. * Note that no de-duplication of statistics between providers is performed, so each provider - * must only report network traffic that is not being reported by any other provider. + * must only report network traffic that is not being reported by any other provider. Also note + * that the provider cannot be re-registered after unregistering. * * @param tag a human readable identifier of the custom network stats provider. This is only * used for debugging. - * @param provider the subclass of {@link AbstractNetworkStatsProvider} that needs to be + * @param provider the subclass of {@link NetworkStatsProvider} that needs to be * registered to the system. - * @return a {@link NetworkStatsProviderCallback}, which can be used to report events to the - * system or unregister the provider. * @hide */ @SystemApi @RequiresPermission(anyOf = { android.Manifest.permission.NETWORK_STATS_PROVIDER, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) - @NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider( + @NonNull public void registerNetworkStatsProvider( @NonNull String tag, - @NonNull AbstractNetworkStatsProvider provider) { + @NonNull NetworkStatsProvider provider) { try { - final NetworkStatsProviderWrapper wrapper = new NetworkStatsProviderWrapper(provider); - return new NetworkStatsProviderCallback( - mService.registerNetworkStatsProvider(tag, wrapper)); + if (provider.getProviderCallbackBinder() != null) { + throw new IllegalArgumentException("provider is already registered"); + } + final INetworkStatsProviderCallback cbBinder = + mService.registerNetworkStatsProvider(tag, provider.getProviderBinder()); + provider.setProviderCallbackBinder(cbBinder); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Unregisters an instance of {@link NetworkStatsProvider}. + * + * @param provider the subclass of {@link NetworkStatsProvider} that needs to be + * unregistered to the system. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STATS_PROVIDER, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) { + try { + provider.getProviderCallbackBinderOrThrow().unregister(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } - // Unreachable code, but compiler doesn't know about it. - return null; } private static NetworkTemplate createTemplate(int networkType, String subscriberId) { diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl index 55b3d4edb1..4078b24921 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl @@ -22,7 +22,7 @@ package android.net.netstats.provider; * @hide */ oneway interface INetworkStatsProvider { - void requestStatsUpdate(int token); - void setLimit(String iface, long quotaBytes); - void setAlert(long quotaBytes); + void onRequestStatsUpdate(int token); + void onSetLimit(String iface, long quotaBytes); + void onSetAlert(long quotaBytes); } diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index 3ea9318f10..bd336dd348 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -24,8 +24,8 @@ import android.net.NetworkStats; * @hide */ oneway interface INetworkStatsProviderCallback { - void onStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); - void onAlertReached(); - void onLimitReached(); + void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); + void notifyAlertReached(); + void notifyLimitReached(); void unregister(); } diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java new file mode 100644 index 0000000000..7639d2244c --- /dev/null +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netstats.provider; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.NetworkStats; +import android.os.RemoteException; + +/** + * A base class that allows external modules to implement a custom network statistics provider. + * @hide + */ +@SystemApi +public abstract class NetworkStatsProvider { + /** + * A value used by {@link #onSetLimit} and {@link #onSetAlert} indicates there is no limit. + */ + public static final int QUOTA_UNLIMITED = -1; + + @NonNull private final INetworkStatsProvider mProviderBinder = + new INetworkStatsProvider.Stub() { + + @Override + public void onRequestStatsUpdate(int token) { + NetworkStatsProvider.this.onRequestStatsUpdate(token); + } + + @Override + public void onSetLimit(String iface, long quotaBytes) { + NetworkStatsProvider.this.onSetLimit(iface, quotaBytes); + } + + @Override + public void onSetAlert(long quotaBytes) { + NetworkStatsProvider.this.onSetAlert(quotaBytes); + } + }; + + // The binder given by the service when successfully registering. Only null before registering, + // never null once non-null. + @Nullable + private INetworkStatsProviderCallback mProviderCbBinder; + + /** + * Return the binder invoked by the service and redirect function calls to the overridden + * methods. + * @hide + */ + @NonNull + public INetworkStatsProvider getProviderBinder() { + return mProviderBinder; + } + + /** + * Store the binder that was returned by the service when successfully registering. Note that + * the provider cannot be re-registered. Hence this method can only be called once per provider. + * + * @hide + */ + public void setProviderCallbackBinder(@NonNull INetworkStatsProviderCallback binder) { + if (mProviderCbBinder != null) { + throw new IllegalArgumentException("provider is already registered"); + } + mProviderCbBinder = binder; + } + + /** + * Get the binder that was returned by the service when successfully registering. Or null if the + * provider was never registered. + * + * @hide + */ + @Nullable + public INetworkStatsProviderCallback getProviderCallbackBinder() { + return mProviderCbBinder; + } + + /** + * Get the binder that was returned by the service when successfully registering. Throw an + * {@link IllegalStateException} if the provider is not registered. + * + * @hide + */ + @NonNull + public INetworkStatsProviderCallback getProviderCallbackBinderOrThrow() { + if (mProviderCbBinder == null) { + throw new IllegalStateException("the provider is not registered"); + } + return mProviderCbBinder; + } + + /** + * Notify the system of new network statistics. + * + * Send the network statistics recorded since the last call to {@link #notifyStatsUpdated}. Must + * be called as soon as possible after {@link NetworkStatsProvider#onRequestStatsUpdate(int)} + * being called. Responding later increases the probability stats will be dropped. The + * provider can also call this whenever it wants to reports new stats for any reason. + * Note that the system will not necessarily immediately propagate the statistics to + * reflect the update. + * + * @param token the token under which these stats were gathered. Providers can call this method + * with the current token as often as they want, until the token changes. + * {@see NetworkStatsProvider#onRequestStatsUpdate()} + * @param ifaceStats the {@link NetworkStats} per interface to be reported. + * The provider should not include any traffic that is already counted by + * kernel interface counters. + * @param uidStats the same stats as above, but counts {@link NetworkStats} + * per uid. + */ + public void notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats, + @NonNull NetworkStats uidStats) { + try { + getProviderCallbackBinderOrThrow().notifyStatsUpdated(token, ifaceStats, uidStats); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Notify system that the quota set by {@code onSetAlert} has been reached. + */ + public void notifyAlertReached() { + try { + getProviderCallbackBinderOrThrow().notifyAlertReached(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Notify system that the quota set by {@code onSetLimit} has been reached. + */ + public void notifyLimitReached() { + try { + getProviderCallbackBinderOrThrow().notifyLimitReached(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Called by {@code NetworkStatsService} when it requires to know updated stats. + * The provider MUST respond by calling {@link #notifyStatsUpdated} as soon as possible. + * Responding later increases the probability stats will be dropped. Memory allowing, the + * system will try to take stats into account up to one minute after calling + * {@link #onRequestStatsUpdate}. + * + * @param token a positive number identifying the new state of the system under which + * {@link NetworkStats} have to be gathered from now on. When this is called, + * custom implementations of providers MUST tally and report the latest stats with + * the previous token, under which stats were being gathered so far. + */ + public abstract void onRequestStatsUpdate(int token); + + /** + * Called by {@code NetworkStatsService} when setting the interface quota for the specified + * upstream interface. When this is called, the custom implementation should block all egress + * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have + * been reached, and MUST respond to it by calling + * {@link NetworkStatsProvider#notifyLimitReached()}. + * + * @param iface the interface requiring the operation. + * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting + * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. + */ + public abstract void onSetLimit(@NonNull String iface, long quotaBytes); + + /** + * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations + * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes + * have been reached. Unlike {@link #onSetLimit(String, long)}, the custom implementation should + * not block all egress packets. + * + * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting + * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert. + */ + public abstract void onSetAlert(long quotaBytes); +} diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index c5a48106fb..0ceaa69308 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -103,7 +103,7 @@ import android.net.NetworkTemplate; import android.net.TrafficStats; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; -import android.net.netstats.provider.NetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProvider; import android.os.BestClock; import android.os.Binder; import android.os.DropBoxManager; @@ -558,7 +558,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } catch (RemoteException e) { // ignored; service lives in system_server } - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setAlert(mGlobalAlertBytes)); + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes)); } @Override @@ -1376,7 +1376,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount(); mStatsProviderSem.drainPermits(); - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */)); + invokeForAllStatsProviderCallbacks( + (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); try { mStatsProviderSem.tryAcquire(registeredCallbackCount, MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS); @@ -1551,7 +1552,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setLimit(iface, quota)); + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); } } @@ -1820,12 +1821,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * * @param tag a human readable identifier of the custom network stats provider. * @param provider the {@link INetworkStatsProvider} binder corresponding to the - * {@link android.net.netstats.provider.AbstractNetworkStatsProvider} to be - * registered. + * {@link NetworkStatsProvider} to be registered. * - * @return a binder interface of - * {@link android.net.netstats.provider.NetworkStatsProviderCallback}, which can be - * used to report events to the system. + * @return a {@link INetworkStatsProviderCallback} binder + * interface, which can be used to report events to the system. */ public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider( @NonNull String tag, @NonNull INetworkStatsProvider provider) { @@ -1931,7 +1930,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void onStatsUpdated(int token, @Nullable NetworkStats ifaceStats, + public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats, @Nullable NetworkStats uidStats) { // TODO: 1. Use token to map ifaces to correct NetworkIdentity. // 2. Store the difference and store it directly to the recorder. @@ -1943,12 +1942,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void onAlertReached() throws RemoteException { + public void notifyAlertReached() throws RemoteException { mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */); } @Override - public void onLimitReached() { + public void notifyLimitReached() { Log.d(TAG, mTag + ": onLimitReached"); LocalServices.getService(NetworkPolicyManagerInternal.class) .onStatsProviderLimitReached(mTag); From 05b2fc228369c54d3daf7fcc50c29a46d8107487 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 13 Mar 2020 16:12:35 +0800 Subject: [PATCH 394/881] [SP23] Address misc API review comment about NetworkStats This change add several javadoc for NetworkStats and its Entry class. Also remove IFACE_ALL constant accordlingly. Test: atest FrameworkNetTests Test: m doc-comment-check-docs Bug: 148895143 Change-Id: Id1b8f41be79f847ad73197ff0e18258b6ee8a730 --- core/java/android/net/NetworkStats.java | 45 ++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 2f536ffd8c..10f7dbfc57 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,7 +21,6 @@ import static android.os.Process.CLAT_UID; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -58,9 +57,12 @@ import java.util.function.Predicate; public final class NetworkStats implements Parcelable { private static final String TAG = "NetworkStats"; - /** {@link #iface} value when interface details unavailable. */ - @SuppressLint("CompileTimeConstant") + /** + * {@link #iface} value when interface details unavailable. + * @hide + */ @Nullable public static final String IFACE_ALL = null; + /** * Virtual network interface for video telephony. This is for VT data usage counting * purpose. @@ -248,7 +250,13 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage private long[] operations; - /** @hide */ + /** + * Basic element of network statistics. Contains the number of packets and number of bytes + * transferred on both directions in a given set of conditions. See + * {@link Entry#Entry(String, int, int, int, int, int, int, long, long, long, long, long)}. + * + * @hide + */ @SystemApi public static class Entry { /** @hide */ @@ -319,6 +327,35 @@ public final class NetworkStats implements Parcelable { rxBytes, rxPackets, txBytes, txPackets, operations); } + /** + * Construct a {@link Entry} object by giving statistics of packet and byte transferred on + * both direction, and associated with a set of given conditions. + * + * @param iface interface name of this {@link Entry}. Or null if not specified. + * @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is + * for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only + * counting iface stats. + * @param set usage state of this {@link Entry}. Should be one of the following + * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}. + * @param tag tag of this {@link Entry}. + * @param metered metered state of this {@link Entry}. Should be one of the following + * values: {link #METERED_YES}, {link #METERED_NO}. + * @param roaming roaming state of this {@link Entry}. Should be one of the following + * values: {link #ROAMING_YES}, {link #ROAMING_NO}. + * @param defaultNetwork default network status of this {@link Entry}. Should be one + * of the following values: {link #DEFAULT_NETWORK_YES}, + * {link #DEFAULT_NETWORK_NO}. + * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param rxPackets Number of packets received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param operations count of network operations performed for this {@link Entry}. This can + * be used to derive bytes-per-operation. + */ public Entry(@Nullable String iface, int uid, @State int set, int tag, @Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { From f27a3cd08f02250b8ae2d4c51b60b12b78337b96 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 13 Mar 2020 19:04:17 +0800 Subject: [PATCH 395/881] [SP24] Rename functions that add Entry unconditionally Currently, in NetworkStats, there are many methods to manipulate the records. However, some methods are similar and ambiguous, such as addEntry, addValues, setValues, addIfaceValues, combineValues and combineAllValues. Thus, properly grouping and renaming methods are necessary. In this change, for methods that add one record unconditionally, name them insertEntry. setIfaceValues -> insertEntry addEntry -> insertEntry Test: atest FrameworksNetTests ImsPhoneCallTrackerTest TetheringTests Test: m doc-comment-check-docs Bug: 148895143 Change-Id: I801ddc49e283a254b9586700c9b597c0adb0d459 --- core/java/android/net/NetworkStats.java | 24 +++++++++---------- .../server/net/NetworkStatsFactory.java | 6 ++--- .../server/net/NetworkStatsService.java | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 10f7dbfc57..0fc74b0894 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -503,7 +503,7 @@ public final class NetworkStats implements Parcelable { NetworkStats.Entry entry = null; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - clone.addEntry(entry); + clone.insertEntry(entry); } return clone; } @@ -530,26 +530,26 @@ public final class NetworkStats implements Parcelable { /** @hide */ @VisibleForTesting - public NetworkStats addIfaceValues( + public NetworkStats insertEntry( String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) { - return addEntry( + return insertEntry( iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L); } /** @hide */ @VisibleForTesting - public NetworkStats addEntry(String iface, int uid, int set, int tag, long rxBytes, + public NetworkStats insertEntry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - return addEntry(new Entry( + return insertEntry(new Entry( iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } /** @hide */ @VisibleForTesting - public NetworkStats addEntry(String iface, int uid, int set, int tag, int metered, int roaming, - int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, - long operations) { - return addEntry(new Entry( + public NetworkStats insertEntry(String iface, int uid, int set, int tag, int metered, + int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes, + long txPackets, long operations) { + return insertEntry(new Entry( iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets, txBytes, txPackets, operations)); } @@ -559,7 +559,7 @@ public final class NetworkStats implements Parcelable { * object can be recycled across multiple calls. * @hide */ - public NetworkStats addEntry(Entry entry) { + public NetworkStats insertEntry(Entry entry) { if (size >= capacity) { final int newLength = Math.max(size, 10) * 3 / 2; iface = Arrays.copyOf(iface, newLength); @@ -702,7 +702,7 @@ public final class NetworkStats implements Parcelable { entry.roaming, entry.defaultNetwork); if (i == -1) { // only create new entry when positive contribution - addEntry(entry); + insertEntry(entry); } else { rxBytes[i] += entry.rxBytes; rxPackets[i] += entry.rxPackets; @@ -1040,7 +1040,7 @@ public final class NetworkStats implements Parcelable { entry.operations = Math.max(entry.operations, 0); } - result.addEntry(entry); + result.insertEntry(entry); } return result; diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 22b01bee6c..75ffe35674 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -229,7 +229,7 @@ public class NetworkStatsFactory { entry.txPackets += reader.nextLong(); } - stats.addEntry(entry); + stats.insertEntry(entry); reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { @@ -279,7 +279,7 @@ public class NetworkStatsFactory { entry.txBytes = reader.nextLong(); entry.txPackets = reader.nextLong(); - stats.addEntry(entry); + stats.insertEntry(entry); reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { @@ -439,7 +439,7 @@ public class NetworkStatsFactory { if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface)) && (limitUid == UID_ALL || limitUid == entry.uid) && (limitTag == TAG_ALL || limitTag == entry.tag)) { - stats.addEntry(entry); + stats.insertEntry(entry); } reader.finishLine(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 0ceaa69308..619cdc6612 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -759,7 +759,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); final NetworkStats stats = new NetworkStats(end - start, 1); - stats.addEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, + stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, entry.operations)); return stats; From 7eaf6a2d48f62458c375c713f851f5dfe911ef07 Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 16 Mar 2020 15:00:24 +0800 Subject: [PATCH 396/881] Fix typo in aosp/1242602 Test: m -j Bug: 149652079 Change-Id: Ie023c8371785fc239c54eacbf056141c2e9e3444 --- .../core/java/com/android/server/net/NetworkStatsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 0ceaa69308..aa869afa21 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1796,7 +1796,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - // TODO: It is copied from ConnectivitySerivce, consider refactor these check permission + // TODO: It is copied from ConnectivityService, consider refactor these check permission // functions to a proper util. private boolean checkAnyPermissionOf(String... permissions) { for (String permission : permissions) { From d53914cadcdd363eadf7c899062b9d82d7de6d36 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Thu, 12 Mar 2020 09:46:43 +0000 Subject: [PATCH 397/881] Add permission check functions to NetworkStatsService This is shameless copied from ConnectivityService and plan to be used in follow-up change. For long term perspective we should have a permission util that contains those util in one place. Test: m -j Change-Id: If70e6e831c0386b604d0151cc0650f68457b6e5f Merged-In: If70e6e831c0386b604d0151cc0650f68457b6e5f Merged-In: I837545b54f36c8f21c878cbb1fd028ff23be6cb8 Bug: 149652079 (cherry picked from commit 4da7af7e7e4a0d3360cd41e98e4d6fa731d21515) --- .../server/net/NetworkStatsService.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4af31b0369..cb3da918f4 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -23,6 +23,7 @@ import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkStack.checkNetworkStackPermission; @@ -1793,6 +1794,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + // TODO: It is copied from ConnectivitySerivce, consider refactor these check permission + // functions to a proper util. + private boolean checkAnyPermissionOf(String... permissions) { + for (String permission : permissions) { + if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { + return true; + } + } + return false; + } + + private void enforceAnyPermissionOf(String... permissions) { + if (!checkAnyPermissionOf(permissions)) { + throw new SecurityException("Requires one of the following permissions: " + + String.join(", ", permissions) + "."); + } + } + /** * Registers a custom provider of {@link android.net.NetworkStats} to combine the network * statistics that cannot be seen by the kernel to system. To unregister, invoke the From f9dc64e61215ca8a3ddbf2453b903ce27acc009d Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 16 Mar 2020 15:00:24 +0800 Subject: [PATCH 398/881] Fix typo in aosp/1242602 Test: m -j Bug: 149652079 Change-Id: Ie023c8371785fc239c54eacbf056141c2e9e3444 Merged-In: Ie023c8371785fc239c54eacbf056141c2e9e3444 (cherry picked from aosp/1259461) --- .../core/java/com/android/server/net/NetworkStatsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index cb3da918f4..45047048cc 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1794,7 +1794,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - // TODO: It is copied from ConnectivitySerivce, consider refactor these check permission + // TODO: It is copied from ConnectivityService, consider refactor these check permission // functions to a proper util. private boolean checkAnyPermissionOf(String... permissions) { for (String permission : permissions) { From b76186859bddc76aeb2a26988733170537003787 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Thu, 12 Mar 2020 09:46:48 +0000 Subject: [PATCH 399/881] [SP20] Check signature permission when accessing network stats provider Currently, registerNetworkStatsProvider requires the UPDATE_DEVICE_STATS permission. This is a privileged permission so it can be granted to preinstalled apps. Thus, apps like GmsCore, or preinstalled apps will be able to update network stats. This change checks for a new permission that would only allow signature apps to declare that. Also check MAINLINE_NETWORK_STACK permission to allow NetworkStack process to use it. Test: adb shell dumpsys netstats Test: atest FrameworksNetTests Bug: 149652079 Change-Id: Iaecbf10a7610461bd52e315659006c7332c416e6 Merged-In: Iaecbf10a7610461bd52e315659006c7332c416e6 Merged-In: Idfebd0a1988c3dcfd812d87e30f6a2034d6fbf6b (cherry picked from commit e9e8d8f9ff096c1723eba1d74b17bb7cade7f23b) --- core/java/android/app/usage/NetworkStatsManager.java | 5 ++++- .../java/com/android/server/net/NetworkStatsService.java | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 5b98188300..7d13f050a7 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -29,6 +29,7 @@ import android.net.ConnectivityManager; import android.net.DataUsageRequest; import android.net.INetworkStatsService; import android.net.NetworkIdentity; +import android.net.NetworkStack; import android.net.NetworkTemplate; import android.net.netstats.provider.AbstractNetworkStatsProvider; import android.net.netstats.provider.NetworkStatsProviderCallback; @@ -540,7 +541,9 @@ public class NetworkStatsManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STATS_PROVIDER, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) @NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider( @NonNull String tag, @NonNull AbstractNetworkStatsProvider provider) { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 45047048cc..a6c2c827fa 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.Manifest.permission.ACCESS_NETWORK_STATE; +import static android.Manifest.permission.NETWORK_STATS_PROVIDER; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.content.Intent.ACTION_SHUTDOWN; @@ -1828,7 +1829,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider( @NonNull String tag, @NonNull INetworkStatsProvider provider) { - mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG); + enforceAnyPermissionOf(NETWORK_STATS_PROVIDER, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); Objects.requireNonNull(provider, "provider is null"); Objects.requireNonNull(tag, "tag is null"); try { From a42fd8ab38b40fbea0a06972a82e293a7514ef48 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 6 Mar 2020 14:50:48 +0800 Subject: [PATCH 400/881] [SP21] Address comments for API council review about aosp/1172143 Test: atest FrameworksNetTests ImsPhoneCallTrackerTest Test: atest TetheringTests NetworkStackTests Test: m doc-comment-check-docs Fix: 148552904 Change-Id: I141393f229e772d2eb9f7c156849e379bd71b845 Merged-In: I141393f229e772d2eb9f7c156849e379bd71b845 (cherry picked from aosp/1253717) --- .../app/usage/NetworkStatsManager.java | 48 +++-- .../provider/INetworkStatsProvider.aidl | 6 +- .../INetworkStatsProviderCallback.aidl | 6 +- .../provider/NetworkStatsProvider.java | 195 ++++++++++++++++++ .../server/net/NetworkStatsService.java | 23 +-- 5 files changed, 245 insertions(+), 33 deletions(-) create mode 100644 core/java/android/net/netstats/provider/NetworkStatsProvider.java diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 7d13f050a7..d6e77624a9 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -31,9 +31,8 @@ import android.net.INetworkStatsService; import android.net.NetworkIdentity; import android.net.NetworkStack; import android.net.NetworkTemplate; -import android.net.netstats.provider.AbstractNetworkStatsProvider; -import android.net.netstats.provider.NetworkStatsProviderCallback; -import android.net.netstats.provider.NetworkStatsProviderWrapper; +import android.net.netstats.provider.INetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; import android.os.Handler; import android.os.Looper; @@ -528,34 +527,53 @@ public class NetworkStatsManager { /** * Registers a custom provider of {@link android.net.NetworkStats} to provide network statistics - * to the system. To unregister, invoke {@link NetworkStatsProviderCallback#unregister()}. + * to the system. To unregister, invoke {@link #unregisterNetworkStatsProvider}. * Note that no de-duplication of statistics between providers is performed, so each provider - * must only report network traffic that is not being reported by any other provider. + * must only report network traffic that is not being reported by any other provider. Also note + * that the provider cannot be re-registered after unregistering. * * @param tag a human readable identifier of the custom network stats provider. This is only * used for debugging. - * @param provider the subclass of {@link AbstractNetworkStatsProvider} that needs to be + * @param provider the subclass of {@link NetworkStatsProvider} that needs to be * registered to the system. - * @return a {@link NetworkStatsProviderCallback}, which can be used to report events to the - * system or unregister the provider. * @hide */ @SystemApi @RequiresPermission(anyOf = { android.Manifest.permission.NETWORK_STATS_PROVIDER, NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) - @NonNull public NetworkStatsProviderCallback registerNetworkStatsProvider( + @NonNull public void registerNetworkStatsProvider( @NonNull String tag, - @NonNull AbstractNetworkStatsProvider provider) { + @NonNull NetworkStatsProvider provider) { try { - final NetworkStatsProviderWrapper wrapper = new NetworkStatsProviderWrapper(provider); - return new NetworkStatsProviderCallback( - mService.registerNetworkStatsProvider(tag, wrapper)); + if (provider.getProviderCallbackBinder() != null) { + throw new IllegalArgumentException("provider is already registered"); + } + final INetworkStatsProviderCallback cbBinder = + mService.registerNetworkStatsProvider(tag, provider.getProviderBinder()); + provider.setProviderCallbackBinder(cbBinder); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Unregisters an instance of {@link NetworkStatsProvider}. + * + * @param provider the subclass of {@link NetworkStatsProvider} that needs to be + * unregistered to the system. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_STATS_PROVIDER, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) + @NonNull public void unregisterNetworkStatsProvider(@NonNull NetworkStatsProvider provider) { + try { + provider.getProviderCallbackBinderOrThrow().unregister(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } - // Unreachable code, but compiler doesn't know about it. - return null; } private static NetworkTemplate createTemplate(int networkType, String subscriberId) { diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl index 55b3d4edb1..4078b24921 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl @@ -22,7 +22,7 @@ package android.net.netstats.provider; * @hide */ oneway interface INetworkStatsProvider { - void requestStatsUpdate(int token); - void setLimit(String iface, long quotaBytes); - void setAlert(long quotaBytes); + void onRequestStatsUpdate(int token); + void onSetLimit(String iface, long quotaBytes); + void onSetAlert(long quotaBytes); } diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index 3ea9318f10..bd336dd348 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -24,8 +24,8 @@ import android.net.NetworkStats; * @hide */ oneway interface INetworkStatsProviderCallback { - void onStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); - void onAlertReached(); - void onLimitReached(); + void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); + void notifyAlertReached(); + void notifyLimitReached(); void unregister(); } diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java new file mode 100644 index 0000000000..7639d2244c --- /dev/null +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netstats.provider; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.NetworkStats; +import android.os.RemoteException; + +/** + * A base class that allows external modules to implement a custom network statistics provider. + * @hide + */ +@SystemApi +public abstract class NetworkStatsProvider { + /** + * A value used by {@link #onSetLimit} and {@link #onSetAlert} indicates there is no limit. + */ + public static final int QUOTA_UNLIMITED = -1; + + @NonNull private final INetworkStatsProvider mProviderBinder = + new INetworkStatsProvider.Stub() { + + @Override + public void onRequestStatsUpdate(int token) { + NetworkStatsProvider.this.onRequestStatsUpdate(token); + } + + @Override + public void onSetLimit(String iface, long quotaBytes) { + NetworkStatsProvider.this.onSetLimit(iface, quotaBytes); + } + + @Override + public void onSetAlert(long quotaBytes) { + NetworkStatsProvider.this.onSetAlert(quotaBytes); + } + }; + + // The binder given by the service when successfully registering. Only null before registering, + // never null once non-null. + @Nullable + private INetworkStatsProviderCallback mProviderCbBinder; + + /** + * Return the binder invoked by the service and redirect function calls to the overridden + * methods. + * @hide + */ + @NonNull + public INetworkStatsProvider getProviderBinder() { + return mProviderBinder; + } + + /** + * Store the binder that was returned by the service when successfully registering. Note that + * the provider cannot be re-registered. Hence this method can only be called once per provider. + * + * @hide + */ + public void setProviderCallbackBinder(@NonNull INetworkStatsProviderCallback binder) { + if (mProviderCbBinder != null) { + throw new IllegalArgumentException("provider is already registered"); + } + mProviderCbBinder = binder; + } + + /** + * Get the binder that was returned by the service when successfully registering. Or null if the + * provider was never registered. + * + * @hide + */ + @Nullable + public INetworkStatsProviderCallback getProviderCallbackBinder() { + return mProviderCbBinder; + } + + /** + * Get the binder that was returned by the service when successfully registering. Throw an + * {@link IllegalStateException} if the provider is not registered. + * + * @hide + */ + @NonNull + public INetworkStatsProviderCallback getProviderCallbackBinderOrThrow() { + if (mProviderCbBinder == null) { + throw new IllegalStateException("the provider is not registered"); + } + return mProviderCbBinder; + } + + /** + * Notify the system of new network statistics. + * + * Send the network statistics recorded since the last call to {@link #notifyStatsUpdated}. Must + * be called as soon as possible after {@link NetworkStatsProvider#onRequestStatsUpdate(int)} + * being called. Responding later increases the probability stats will be dropped. The + * provider can also call this whenever it wants to reports new stats for any reason. + * Note that the system will not necessarily immediately propagate the statistics to + * reflect the update. + * + * @param token the token under which these stats were gathered. Providers can call this method + * with the current token as often as they want, until the token changes. + * {@see NetworkStatsProvider#onRequestStatsUpdate()} + * @param ifaceStats the {@link NetworkStats} per interface to be reported. + * The provider should not include any traffic that is already counted by + * kernel interface counters. + * @param uidStats the same stats as above, but counts {@link NetworkStats} + * per uid. + */ + public void notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats, + @NonNull NetworkStats uidStats) { + try { + getProviderCallbackBinderOrThrow().notifyStatsUpdated(token, ifaceStats, uidStats); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Notify system that the quota set by {@code onSetAlert} has been reached. + */ + public void notifyAlertReached() { + try { + getProviderCallbackBinderOrThrow().notifyAlertReached(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Notify system that the quota set by {@code onSetLimit} has been reached. + */ + public void notifyLimitReached() { + try { + getProviderCallbackBinderOrThrow().notifyLimitReached(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Called by {@code NetworkStatsService} when it requires to know updated stats. + * The provider MUST respond by calling {@link #notifyStatsUpdated} as soon as possible. + * Responding later increases the probability stats will be dropped. Memory allowing, the + * system will try to take stats into account up to one minute after calling + * {@link #onRequestStatsUpdate}. + * + * @param token a positive number identifying the new state of the system under which + * {@link NetworkStats} have to be gathered from now on. When this is called, + * custom implementations of providers MUST tally and report the latest stats with + * the previous token, under which stats were being gathered so far. + */ + public abstract void onRequestStatsUpdate(int token); + + /** + * Called by {@code NetworkStatsService} when setting the interface quota for the specified + * upstream interface. When this is called, the custom implementation should block all egress + * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have + * been reached, and MUST respond to it by calling + * {@link NetworkStatsProvider#notifyLimitReached()}. + * + * @param iface the interface requiring the operation. + * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting + * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. + */ + public abstract void onSetLimit(@NonNull String iface, long quotaBytes); + + /** + * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations + * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes + * have been reached. Unlike {@link #onSetLimit(String, long)}, the custom implementation should + * not block all egress packets. + * + * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting + * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert. + */ + public abstract void onSetAlert(long quotaBytes); +} diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index a6c2c827fa..46e865c7e8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -103,7 +103,7 @@ import android.net.NetworkTemplate; import android.net.TrafficStats; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; -import android.net.netstats.provider.NetworkStatsProviderCallback; +import android.net.netstats.provider.NetworkStatsProvider; import android.os.BestClock; import android.os.Binder; import android.os.DropBoxManager; @@ -558,7 +558,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } catch (RemoteException e) { // ignored; service lives in system_server } - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setAlert(mGlobalAlertBytes)); + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes)); } @Override @@ -1376,7 +1376,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount(); mStatsProviderSem.drainPermits(); - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.requestStatsUpdate(0 /* unused */)); + invokeForAllStatsProviderCallbacks( + (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); try { mStatsProviderSem.tryAcquire(registeredCallbackCount, MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS); @@ -1551,7 +1552,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.setLimit(iface, quota)); + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); } } @@ -1820,12 +1821,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * * @param tag a human readable identifier of the custom network stats provider. * @param provider the {@link INetworkStatsProvider} binder corresponding to the - * {@link android.net.netstats.provider.AbstractNetworkStatsProvider} to be - * registered. + * {@link NetworkStatsProvider} to be registered. * - * @return a binder interface of - * {@link android.net.netstats.provider.NetworkStatsProviderCallback}, which can be - * used to report events to the system. + * @return a {@link INetworkStatsProviderCallback} binder + * interface, which can be used to report events to the system. */ public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider( @NonNull String tag, @NonNull INetworkStatsProvider provider) { @@ -1931,7 +1930,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void onStatsUpdated(int token, @Nullable NetworkStats ifaceStats, + public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats, @Nullable NetworkStats uidStats) { // TODO: 1. Use token to map ifaces to correct NetworkIdentity. // 2. Store the difference and store it directly to the recorder. @@ -1943,12 +1942,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void onAlertReached() throws RemoteException { + public void notifyAlertReached() throws RemoteException { mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */); } @Override - public void onLimitReached() { + public void notifyLimitReached() { Log.d(TAG, mTag + ": onLimitReached"); LocalServices.getService(NetworkPolicyManagerInternal.class) .onStatsProviderLimitReached(mTag); From 89c23a62eb69f420b57160d1f6622f6f7b27d1b8 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 13 Mar 2020 16:12:35 +0800 Subject: [PATCH 401/881] [SP23] Address misc API review comment about NetworkStats This change add several javadoc for NetworkStats and its Entry class. Also remove IFACE_ALL constant accordlingly. Test: atest FrameworkNetTests Test: m doc-comment-check-docs Bug: 148895143 Change-Id: Id1b8f41be79f847ad73197ff0e18258b6ee8a730 Merged-In: Id1b8f41be79f847ad73197ff0e18258b6ee8a730 (cherry picked from aosp/1256351) --- core/java/android/net/NetworkStats.java | 45 ++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 2f536ffd8c..10f7dbfc57 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,7 +21,6 @@ import static android.os.Process.CLAT_UID; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -58,9 +57,12 @@ import java.util.function.Predicate; public final class NetworkStats implements Parcelable { private static final String TAG = "NetworkStats"; - /** {@link #iface} value when interface details unavailable. */ - @SuppressLint("CompileTimeConstant") + /** + * {@link #iface} value when interface details unavailable. + * @hide + */ @Nullable public static final String IFACE_ALL = null; + /** * Virtual network interface for video telephony. This is for VT data usage counting * purpose. @@ -248,7 +250,13 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage private long[] operations; - /** @hide */ + /** + * Basic element of network statistics. Contains the number of packets and number of bytes + * transferred on both directions in a given set of conditions. See + * {@link Entry#Entry(String, int, int, int, int, int, int, long, long, long, long, long)}. + * + * @hide + */ @SystemApi public static class Entry { /** @hide */ @@ -319,6 +327,35 @@ public final class NetworkStats implements Parcelable { rxBytes, rxPackets, txBytes, txPackets, operations); } + /** + * Construct a {@link Entry} object by giving statistics of packet and byte transferred on + * both direction, and associated with a set of given conditions. + * + * @param iface interface name of this {@link Entry}. Or null if not specified. + * @param uid uid of this {@link Entry}. {@link #UID_TETHERING} if this {@link Entry} is + * for tethering. Or {@link #UID_ALL} if this {@link NetworkStats} is only + * counting iface stats. + * @param set usage state of this {@link Entry}. Should be one of the following + * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}. + * @param tag tag of this {@link Entry}. + * @param metered metered state of this {@link Entry}. Should be one of the following + * values: {link #METERED_YES}, {link #METERED_NO}. + * @param roaming roaming state of this {@link Entry}. Should be one of the following + * values: {link #ROAMING_YES}, {link #ROAMING_NO}. + * @param defaultNetwork default network status of this {@link Entry}. Should be one + * of the following values: {link #DEFAULT_NETWORK_YES}, + * {link #DEFAULT_NETWORK_NO}. + * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param rxPackets Number of packets received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param operations count of network operations performed for this {@link Entry}. This can + * be used to derive bytes-per-operation. + */ public Entry(@Nullable String iface, int uid, @State int set, int tag, @Meteredness int metered, @Roaming int roaming, @DefaultNetwork int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { From 21b5e7f1b205ca43ad6537f5e3b6efbfc2dde1f7 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 13 Mar 2020 19:04:17 +0800 Subject: [PATCH 402/881] [SP24] Rename functions that add Entry unconditionally Currently, in NetworkStats, there are many methods to manipulate the records. However, some methods are similar and ambiguous, such as addEntry, addValues, setValues, addIfaceValues, combineValues and combineAllValues. Thus, properly grouping and renaming methods are necessary. In this change, for methods that add one record unconditionally, name them insertEntry. setIfaceValues -> insertEntry addEntry -> insertEntry Test: atest FrameworksNetTests ImsPhoneCallTrackerTest TetheringTests Test: m doc-comment-check-docs Bug: 148895143 Change-Id: I801ddc49e283a254b9586700c9b597c0adb0d459 Merged-In: I801ddc49e283a254b9586700c9b597c0adb0d459 (cherry picked from aosp/1256352) --- core/java/android/net/NetworkStats.java | 24 +++++++++---------- .../server/net/NetworkStatsFactory.java | 6 ++--- .../server/net/NetworkStatsService.java | 2 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 10f7dbfc57..0fc74b0894 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -503,7 +503,7 @@ public final class NetworkStats implements Parcelable { NetworkStats.Entry entry = null; for (int i = 0; i < size; i++) { entry = getValues(i, entry); - clone.addEntry(entry); + clone.insertEntry(entry); } return clone; } @@ -530,26 +530,26 @@ public final class NetworkStats implements Parcelable { /** @hide */ @VisibleForTesting - public NetworkStats addIfaceValues( + public NetworkStats insertEntry( String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) { - return addEntry( + return insertEntry( iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L); } /** @hide */ @VisibleForTesting - public NetworkStats addEntry(String iface, int uid, int set, int tag, long rxBytes, + public NetworkStats insertEntry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - return addEntry(new Entry( + return insertEntry(new Entry( iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } /** @hide */ @VisibleForTesting - public NetworkStats addEntry(String iface, int uid, int set, int tag, int metered, int roaming, - int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, - long operations) { - return addEntry(new Entry( + public NetworkStats insertEntry(String iface, int uid, int set, int tag, int metered, + int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes, + long txPackets, long operations) { + return insertEntry(new Entry( iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets, txBytes, txPackets, operations)); } @@ -559,7 +559,7 @@ public final class NetworkStats implements Parcelable { * object can be recycled across multiple calls. * @hide */ - public NetworkStats addEntry(Entry entry) { + public NetworkStats insertEntry(Entry entry) { if (size >= capacity) { final int newLength = Math.max(size, 10) * 3 / 2; iface = Arrays.copyOf(iface, newLength); @@ -702,7 +702,7 @@ public final class NetworkStats implements Parcelable { entry.roaming, entry.defaultNetwork); if (i == -1) { // only create new entry when positive contribution - addEntry(entry); + insertEntry(entry); } else { rxBytes[i] += entry.rxBytes; rxPackets[i] += entry.rxPackets; @@ -1040,7 +1040,7 @@ public final class NetworkStats implements Parcelable { entry.operations = Math.max(entry.operations, 0); } - result.addEntry(entry); + result.insertEntry(entry); } return result; diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 22b01bee6c..75ffe35674 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -229,7 +229,7 @@ public class NetworkStatsFactory { entry.txPackets += reader.nextLong(); } - stats.addEntry(entry); + stats.insertEntry(entry); reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { @@ -279,7 +279,7 @@ public class NetworkStatsFactory { entry.txBytes = reader.nextLong(); entry.txPackets = reader.nextLong(); - stats.addEntry(entry); + stats.insertEntry(entry); reader.finishLine(); } } catch (NullPointerException|NumberFormatException e) { @@ -439,7 +439,7 @@ public class NetworkStatsFactory { if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface)) && (limitUid == UID_ALL || limitUid == entry.uid) && (limitTag == TAG_ALL || limitTag == entry.tag)) { - stats.addEntry(entry); + stats.insertEntry(entry); } reader.finishLine(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 46e865c7e8..10136b3b8b 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -759,7 +759,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); final NetworkStats stats = new NetworkStats(end - start, 1); - stats.addEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, + stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, entry.operations)); return stats; From 6300ca0896c409bc7f9acf0005eacc46500ab5cb Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 16 Mar 2020 13:27:28 +0800 Subject: [PATCH 403/881] [SP25] Rename functions that add Entry conditionally Currently, in NetworkStats, there are many methods to manipulate the records. However, some methods are similar and ambiguous, such as addEntry, addValues, setValues, addIfaceValues, combineValues and combineAllValues. Thus, properly grouping and renaming methods are necessary. In this change, for methods that add one record conditionally, name them addEntry. addValues -> addEntry Test: atest FrameworksNetTests ImsPhoneCallTrackerTest TetheringTests Fix: 148895143 Change-Id: I9495a198cf247e6c79100f7ac1edcea370b071de --- core/java/android/net/NetworkStats.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 0fc74b0894..9c1fb41ecc 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -721,7 +721,7 @@ public final class NetworkStats implements Parcelable { * @param entry the {@link Entry} to add. * @return a new constructed {@link NetworkStats} object that contains the result. */ - public @NonNull NetworkStats addValues(@NonNull Entry entry) { + public @NonNull NetworkStats addEntry(@NonNull Entry entry) { return this.clone().combineValues(entry); } From 4ceb6470bd810e92dad8903aa44054492f309aac Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 16 Mar 2020 13:27:28 +0800 Subject: [PATCH 404/881] [SP25] Rename functions that add Entry conditionally Currently, in NetworkStats, there are many methods to manipulate the records. However, some methods are similar and ambiguous, such as addEntry, addValues, setValues, addIfaceValues, combineValues and combineAllValues. Thus, properly grouping and renaming methods are necessary. In this change, for methods that add one record conditionally, name them addEntry. addValues -> addEntry Test: atest FrameworksNetTests ImsPhoneCallTrackerTest TetheringTests Fix: 148895143 Change-Id: I9495a198cf247e6c79100f7ac1edcea370b071de Merged-In: I9495a198cf247e6c79100f7ac1edcea370b071de (cherry picked from ag/10700816) --- core/java/android/net/NetworkStats.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 0fc74b0894..9c1fb41ecc 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -721,7 +721,7 @@ public final class NetworkStats implements Parcelable { * @param entry the {@link Entry} to add. * @return a new constructed {@link NetworkStats} object that contains the result. */ - public @NonNull NetworkStats addValues(@NonNull Entry entry) { + public @NonNull NetworkStats addEntry(@NonNull Entry entry) { return this.clone().combineValues(entry); } From 96105f0d217a9cc168b0dda72f0125c1624ff692 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 12 Dec 2019 19:42:59 +0800 Subject: [PATCH 405/881] [SM02] Support record mobile network stats by collapsed rat type Previously network stats could be recorded by different rat type. However, the feature was disabled by ag/173504 since rat type frequently flapping between HSPA+ and UMTS. Given that this feature might be useful for collecting metrics, re-implement it based on current architecture and reduce the overhead introduced by frequently flapping by: 1. only react when rat type changes between 2G/3G/4G/5G. 2. reduce the number of records by only recording a subset of rat type that represented for a given network class. 3. enforce 1 second rate limit if flapping too much. Note that the feature is still disabled but will be enabled in follow-up patches. Test: manual test Bug: 129082217 Change-Id: Ic6b2f10f2c8b082820e0662eb9cee70d70d28cd6 --- core/java/android/net/NetworkIdentity.java | 15 ++-- core/java/android/net/NetworkTemplate.java | 40 +++++++++ .../server/net/NetworkStatsService.java | 89 ++++++++++++++++++- 3 files changed, 134 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index c1198aac27..b67ad519b4 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.service.NetworkIdentityProto; +import android.telephony.Annotation.NetworkType; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -42,11 +43,8 @@ public class NetworkIdentity implements Comparable { /** * When enabled, combine all {@link #mSubType} together under * {@link #SUBTYPE_COMBINED}. - * - * @deprecated we no longer offer to collect statistics on a per-subtype - * basis; this is always disabled. */ - @Deprecated + // TODO: make this flag configurable through settings. See http://b/146415925 public static final boolean COMBINE_SUBTYPE_ENABLED = true; public static final int SUBTYPE_COMBINED = -1; @@ -187,13 +185,14 @@ public class NetworkIdentity implements Comparable { } /** - * Build a {@link NetworkIdentity} from the given {@link NetworkState}, - * assuming that any mobile networks are using the current IMSI. + * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType}, + * assuming that any mobile networks are using the current IMSI. The subType if applicable, + * should be set as one of the TelephonyManager.NETWORK_TYPE_* constants, or + * {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. */ public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, - boolean defaultNetwork) { + boolean defaultNetwork, @NetworkType int subType) { final int type = state.networkInfo.getType(); - final int subType = state.networkInfo.getSubtype(); String subscriberId = null; String networkId = null; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 5498f74ba2..6080d16b9d 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.TelephonyManager; import android.util.BackupUtils; import android.util.Log; @@ -394,6 +395,45 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types. + * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}. + * + * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. + */ + // TODO: 1. Consider move this to TelephonyManager if used by other modules. + // 2. Consider make this configurable. + // 3. Use TelephonyManager APIs when available. + public static int getCollapsedRatType(int ratType) { + switch (ratType) { + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_GSM: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_IDEN: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_1xRTT: + return TelephonyManager.NETWORK_TYPE_GSM; + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + case TelephonyManager.NETWORK_TYPE_TD_SCDMA: + return TelephonyManager.NETWORK_TYPE_UMTS; + case TelephonyManager.NETWORK_TYPE_LTE: + case TelephonyManager.NETWORK_TYPE_IWLAN: + return TelephonyManager.NETWORK_TYPE_LTE; + case TelephonyManager.NETWORK_TYPE_NR: + return TelephonyManager.NETWORK_TYPE_NR; + default: + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } + /** * Check if matches Wi-Fi network template. */ diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 10136b3b8b..7c4624d25c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,6 +27,8 @@ import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; +import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; @@ -45,6 +47,7 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; +import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -64,6 +67,9 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; +import static android.telephony.PhoneStateListener.LISTEN_NONE; +import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; +import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -109,6 +115,7 @@ import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkManagementService; @@ -125,6 +132,8 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.text.format.DateUtils; @@ -157,6 +166,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -173,6 +183,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int MSG_PERFORM_POLL = 1; // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; + private static final int MSG_UPDATE_IFACES = 3; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -280,6 +291,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; + /** Last states of all networks sent from ConnectivityService. */ + @GuardedBy("mStatsLock") + @Nullable + private NetworkState[] mLastNetworkStates = null; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -355,6 +371,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performPoll(FLAG_PERSIST_ALL); break; } + case MSG_UPDATE_IFACES: { + // If no cached states, ignore. + if (mLastNetworkStates == null) break; + updateIfaces(mDefaultNetworks, mLastNetworkStates, mActiveIface); + break; + } case MSG_PERFORM_POLL_REGISTER_ALERT: { performPoll(FLAG_PERSIST_NETWORK); registerGlobalAlert(); @@ -407,6 +429,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); + mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); } /** @@ -486,6 +509,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); + // TODO: listen to changes from all subscriptions. + // watch for networkType changes + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + } + registerGlobalAlert(); } @@ -506,6 +535,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_NONE); + } + final long currentTime = mClock.millis(); // persist any pending stats @@ -1156,6 +1189,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; + /** + * Receiver that watches for {@link TelephonyManager} changes, such as + * transitioning between Radio Access Technology(RAT) types. + */ + @NonNull + private final NetworkTypeListener mPhoneListener; + + class NetworkTypeListener extends PhoneStateListener { + private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; + + NetworkTypeListener(@NonNull Executor executor) { + super(executor); + } + + @Override + public void onServiceStateChanged(@NonNull ServiceState ss) { + final int networkType = ss.getDataNetworkType(); + final int collapsedRatType = getCollapsedRatType(networkType); + if (collapsedRatType == mLastCollapsedRatType) return; + + if (LOGV) { + Log.d(TAG, "subtype changed for mobile: " + + mLastCollapsedRatType + " -> " + collapsedRatType); + } + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mLastCollapsedRatType = collapsedRatType; + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); + } + } + private void updateIfaces( Network[] defaultNetworks, NetworkState[] networkStates, @@ -1177,7 +1242,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { + private void updateIfacesLocked(@Nullable Network[] defaultNetworks, + @NonNull NetworkState[] states) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1197,13 +1263,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mDefaultNetworks = defaultNetworks; } + mLastNetworkStates = states; + final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); + final int subType = getSubTypeForState(state); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, - isDefault); + isDefault, subType); // Traffic occurring on the base interface is always counted for // both total usage and UID details. @@ -1264,6 +1333,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]); } + /** + * If combine subtype is not enabled. For networks with {@code TRANSPORT_CELLULAR}, get + * subType that obtained through {@link PhoneStateListener}. Otherwise, return 0 given that + * other networks with different transport types do not actually fill this value. + */ + private int getSubTypeForState(@NonNull NetworkState state) { + if (COMBINE_SUBTYPE_ENABLED) return SUBTYPE_COMBINED; + + if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return 0; + } + + // TODO: return different subType for different subscriptions. + return mPhoneListener.mLastCollapsedRatType; + } + private static NetworkIdentitySet findOrCreateNetworkIdentitySet( ArrayMap map, K key) { NetworkIdentitySet ident = map.get(key); From 82d9f7cbb0e684d2de2911be3a0473c3edbc50df Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 20 Dec 2019 16:35:34 +0800 Subject: [PATCH 406/881] [SM04] Support fetching data with NetworkTemplate with subType Add a NetworkTemplate build function that allows user to specify subType. NetworkStats corresponding to the same group would be retrieved. Test: atest FrameworksNetTests Bug: 129082217 Change-Id: Ie2d229be0b6bd239f799989c070475c73a096d71 --- core/java/android/net/NetworkTemplate.java | 60 +++++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 6080d16b9d..cb9463a59d 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,10 +34,13 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.sanitizeSsid; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.NetworkType; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.BackupUtils; import android.util.Log; @@ -74,6 +77,14 @@ public class NetworkTemplate implements Parcelable { public static final int MATCH_BLUETOOTH = 8; public static final int MATCH_PROXY = 9; + /** + * Include all network types when filtering. This is meant to merge in with the + * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. + * + * @hide + */ + public static final int NETWORK_TYPE_ALL = -1; + private static boolean isKnownMatchRule(final int rule) { switch (rule) { case MATCH_MOBILE: @@ -118,7 +129,22 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks, + * Template to match cellular networks with the given IMSI and {@code ratType}. + * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering. + * See {@code TelephonyManager.NETWORK_TYPE_*}. + */ + public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, + @NetworkType int ratType) { + if (TextUtils.isEmpty(subscriberId)) { + return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + } + return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + } + + /** + * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ @UnsupportedAppUsage @@ -127,7 +153,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks, + * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks, * regardless of SSID. */ @UnsupportedAppUsage @@ -193,6 +219,7 @@ public class NetworkTemplate implements Parcelable { private final int mMetered; private final int mRoaming; private final int mDefaultNetwork; + private final int mSubType; @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { @@ -202,11 +229,11 @@ public class NetworkTemplate implements Parcelable { public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL); + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL); } public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String networkId, int metered, int roaming, int defaultNetwork) { + String networkId, int metered, int roaming, int defaultNetwork, int subType) { mMatchRule = matchRule; mSubscriberId = subscriberId; mMatchSubscriberIds = matchSubscriberIds; @@ -214,6 +241,7 @@ public class NetworkTemplate implements Parcelable { mMetered = metered; mRoaming = roaming; mDefaultNetwork = defaultNetwork; + mSubType = subType; if (!isKnownMatchRule(matchRule)) { Log.e(TAG, "Unknown network template rule " + matchRule @@ -229,6 +257,7 @@ public class NetworkTemplate implements Parcelable { mMetered = in.readInt(); mRoaming = in.readInt(); mDefaultNetwork = in.readInt(); + mSubType = in.readInt(); } @Override @@ -240,6 +269,7 @@ public class NetworkTemplate implements Parcelable { dest.writeInt(mMetered); dest.writeInt(mRoaming); dest.writeInt(mDefaultNetwork); + dest.writeInt(mSubType); } @Override @@ -272,13 +302,16 @@ public class NetworkTemplate implements Parcelable { builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( mDefaultNetwork)); } + if (mSubType != NETWORK_TYPE_ALL) { + builder.append(", subType=").append(mSubType); + } return builder.toString(); } @Override public int hashCode() { return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, - mDefaultNetwork); + mDefaultNetwork, mSubType); } @Override @@ -290,7 +323,8 @@ public class NetworkTemplate implements Parcelable { && Objects.equals(mNetworkId, other.mNetworkId) && mMetered == other.mMetered && mRoaming == other.mRoaming - && mDefaultNetwork == other.mDefaultNetwork; + && mDefaultNetwork == other.mDefaultNetwork + && mSubType == other.mSubType; } return false; } @@ -377,6 +411,11 @@ public class NetworkTemplate implements Parcelable { || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); } + private boolean matchesCollapsedRatType(NetworkIdentity ident) { + return mSubType == NETWORK_TYPE_ALL + || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType); + } + public boolean matchesSubscriberId(String subscriberId) { return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); } @@ -389,9 +428,13 @@ public class NetworkTemplate implements Parcelable { // TODO: consider matching against WiMAX subscriber identity return true; } else { + // Only metered mobile network would be matched regardless of metered filter. + // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. + // TODO: Respect metered filter and remove mMetered condition. return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) && !ArrayUtils.isEmpty(mMatchSubscriberIds) - && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); + && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) + && matchesCollapsedRatType(ident); } } @@ -461,7 +504,8 @@ public class NetworkTemplate implements Parcelable { if (ident.mType == TYPE_WIMAX) { return true; } else { - return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered); + return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) + && matchesCollapsedRatType(ident); } } From 8413d3c1af0f6bdf5a9dbf0ef28c48e99f599a93 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 31 Dec 2019 13:40:15 +0800 Subject: [PATCH 407/881] [SM05] Enable record mobile network stats by collapsed rat type Switch on the recording in device side. Metrics will be collected in follow-up patches which can be independently enabled/disabled. This change also fix the fail in NetworkStatsCollectionTest which caused by enabling this feature, where the rounding problem happened when records are distributed into smaller buckets and categorized into more NetworkIdentity. Test: atest FrameworksNetTests Bug: 129082217 Change-Id: If330e85330a4ff713dd420c98d42fa741eabd90a --- core/java/android/net/NetworkIdentity.java | 2 +- .../core/java/com/android/server/net/NetworkStatsService.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index b67ad519b4..2cf3531d2f 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -45,7 +45,7 @@ public class NetworkIdentity implements Comparable { * {@link #SUBTYPE_COMBINED}. */ // TODO: make this flag configurable through settings. See http://b/146415925 - public static final boolean COMBINE_SUBTYPE_ENABLED = true; + public static final boolean COMBINE_SUBTYPE_ENABLED = false; public static final int SUBTYPE_COMBINED = -1; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 7c4624d25c..ff4407aa12 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1209,7 +1209,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; - if (LOGV) { + if (LOGD) { Log.d(TAG, "subtype changed for mobile: " + mLastCollapsedRatType + " -> " + collapsedRatType); } @@ -1217,7 +1217,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mHandler.removeMessages(MSG_UPDATE_IFACES); mLastCollapsedRatType = collapsedRatType; mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } } From 2c31ca121194fdc3867b02d5d46786ae50d5d617 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 12 Dec 2019 19:42:59 +0800 Subject: [PATCH 408/881] [SM02] Support record mobile network stats by collapsed rat type Previously network stats could be recorded by different rat type. However, the feature was disabled by ag/173504 since rat type frequently flapping between HSPA+ and UMTS. Given that this feature might be useful for collecting metrics, re-implement it based on current architecture and reduce the overhead introduced by frequently flapping by: 1. only react when rat type changes between 2G/3G/4G/5G. 2. reduce the number of records by only recording a subset of rat type that represented for a given network class. 3. enforce 1 second rate limit if flapping too much. Note that the feature is still disabled but will be enabled in follow-up patches. Test: manual test Bug: 129082217 Change-Id: Ic6b2f10f2c8b082820e0662eb9cee70d70d28cd6 Merged-In: Ic6b2f10f2c8b082820e0662eb9cee70d70d28cd6 (cherry picked from commit 15ab452e7e3f00289fbedbdb86c512ad560dda7e) --- core/java/android/net/NetworkIdentity.java | 15 ++-- core/java/android/net/NetworkTemplate.java | 40 +++++++++ .../server/net/NetworkStatsService.java | 89 ++++++++++++++++++- 3 files changed, 134 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index c1198aac27..b67ad519b4 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.service.NetworkIdentityProto; +import android.telephony.Annotation.NetworkType; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -42,11 +43,8 @@ public class NetworkIdentity implements Comparable { /** * When enabled, combine all {@link #mSubType} together under * {@link #SUBTYPE_COMBINED}. - * - * @deprecated we no longer offer to collect statistics on a per-subtype - * basis; this is always disabled. */ - @Deprecated + // TODO: make this flag configurable through settings. See http://b/146415925 public static final boolean COMBINE_SUBTYPE_ENABLED = true; public static final int SUBTYPE_COMBINED = -1; @@ -187,13 +185,14 @@ public class NetworkIdentity implements Comparable { } /** - * Build a {@link NetworkIdentity} from the given {@link NetworkState}, - * assuming that any mobile networks are using the current IMSI. + * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType}, + * assuming that any mobile networks are using the current IMSI. The subType if applicable, + * should be set as one of the TelephonyManager.NETWORK_TYPE_* constants, or + * {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. */ public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, - boolean defaultNetwork) { + boolean defaultNetwork, @NetworkType int subType) { final int type = state.networkInfo.getType(); - final int subType = state.networkInfo.getSubtype(); String subscriberId = null; String networkId = null; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 5498f74ba2..6080d16b9d 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.TelephonyManager; import android.util.BackupUtils; import android.util.Log; @@ -394,6 +395,45 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types. + * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}. + * + * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. + */ + // TODO: 1. Consider move this to TelephonyManager if used by other modules. + // 2. Consider make this configurable. + // 3. Use TelephonyManager APIs when available. + public static int getCollapsedRatType(int ratType) { + switch (ratType) { + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_GSM: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_IDEN: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_1xRTT: + return TelephonyManager.NETWORK_TYPE_GSM; + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + case TelephonyManager.NETWORK_TYPE_TD_SCDMA: + return TelephonyManager.NETWORK_TYPE_UMTS; + case TelephonyManager.NETWORK_TYPE_LTE: + case TelephonyManager.NETWORK_TYPE_IWLAN: + return TelephonyManager.NETWORK_TYPE_LTE; + case TelephonyManager.NETWORK_TYPE_NR: + return TelephonyManager.NETWORK_TYPE_NR; + default: + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } + /** * Check if matches Wi-Fi network template. */ diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 10136b3b8b..7c4624d25c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,6 +27,8 @@ import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; +import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; @@ -45,6 +47,7 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; +import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -64,6 +67,9 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; +import static android.telephony.PhoneStateListener.LISTEN_NONE; +import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; +import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -109,6 +115,7 @@ import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkManagementService; @@ -125,6 +132,8 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.text.format.DateUtils; @@ -157,6 +166,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -173,6 +183,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int MSG_PERFORM_POLL = 1; // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; + private static final int MSG_UPDATE_IFACES = 3; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -280,6 +291,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; + /** Last states of all networks sent from ConnectivityService. */ + @GuardedBy("mStatsLock") + @Nullable + private NetworkState[] mLastNetworkStates = null; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -355,6 +371,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performPoll(FLAG_PERSIST_ALL); break; } + case MSG_UPDATE_IFACES: { + // If no cached states, ignore. + if (mLastNetworkStates == null) break; + updateIfaces(mDefaultNetworks, mLastNetworkStates, mActiveIface); + break; + } case MSG_PERFORM_POLL_REGISTER_ALERT: { performPoll(FLAG_PERSIST_NETWORK); registerGlobalAlert(); @@ -407,6 +429,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); + mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); } /** @@ -486,6 +509,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); + // TODO: listen to changes from all subscriptions. + // watch for networkType changes + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + } + registerGlobalAlert(); } @@ -506,6 +535,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_NONE); + } + final long currentTime = mClock.millis(); // persist any pending stats @@ -1156,6 +1189,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; + /** + * Receiver that watches for {@link TelephonyManager} changes, such as + * transitioning between Radio Access Technology(RAT) types. + */ + @NonNull + private final NetworkTypeListener mPhoneListener; + + class NetworkTypeListener extends PhoneStateListener { + private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; + + NetworkTypeListener(@NonNull Executor executor) { + super(executor); + } + + @Override + public void onServiceStateChanged(@NonNull ServiceState ss) { + final int networkType = ss.getDataNetworkType(); + final int collapsedRatType = getCollapsedRatType(networkType); + if (collapsedRatType == mLastCollapsedRatType) return; + + if (LOGV) { + Log.d(TAG, "subtype changed for mobile: " + + mLastCollapsedRatType + " -> " + collapsedRatType); + } + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mLastCollapsedRatType = collapsedRatType; + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); + } + } + private void updateIfaces( Network[] defaultNetworks, NetworkState[] networkStates, @@ -1177,7 +1242,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { + private void updateIfacesLocked(@Nullable Network[] defaultNetworks, + @NonNull NetworkState[] states) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1197,13 +1263,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mDefaultNetworks = defaultNetworks; } + mLastNetworkStates = states; + final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); + final int subType = getSubTypeForState(state); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, - isDefault); + isDefault, subType); // Traffic occurring on the base interface is always counted for // both total usage and UID details. @@ -1264,6 +1333,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]); } + /** + * If combine subtype is not enabled. For networks with {@code TRANSPORT_CELLULAR}, get + * subType that obtained through {@link PhoneStateListener}. Otherwise, return 0 given that + * other networks with different transport types do not actually fill this value. + */ + private int getSubTypeForState(@NonNull NetworkState state) { + if (COMBINE_SUBTYPE_ENABLED) return SUBTYPE_COMBINED; + + if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return 0; + } + + // TODO: return different subType for different subscriptions. + return mPhoneListener.mLastCollapsedRatType; + } + private static NetworkIdentitySet findOrCreateNetworkIdentitySet( ArrayMap map, K key) { NetworkIdentitySet ident = map.get(key); From b62cac012f29bf5429733d1532093cbd1471278a Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 20 Dec 2019 16:35:34 +0800 Subject: [PATCH 409/881] [SM04] Support fetching data with NetworkTemplate with subType Add a NetworkTemplate build function that allows user to specify subType. NetworkStats corresponding to the same group would be retrieved. Test: atest FrameworksNetTests Bug: 129082217 Change-Id: Ie2d229be0b6bd239f799989c070475c73a096d71 Merged-In: Ie2d229be0b6bd239f799989c070475c73a096d71 (cherry picked from commit e19045cc4ab1f2cd133ce5dc0c3a38e3275417ad) --- core/java/android/net/NetworkTemplate.java | 60 +++++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 6080d16b9d..cb9463a59d 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,10 +34,13 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.sanitizeSsid; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.NetworkType; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.BackupUtils; import android.util.Log; @@ -74,6 +77,14 @@ public class NetworkTemplate implements Parcelable { public static final int MATCH_BLUETOOTH = 8; public static final int MATCH_PROXY = 9; + /** + * Include all network types when filtering. This is meant to merge in with the + * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. + * + * @hide + */ + public static final int NETWORK_TYPE_ALL = -1; + private static boolean isKnownMatchRule(final int rule) { switch (rule) { case MATCH_MOBILE: @@ -118,7 +129,22 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks, + * Template to match cellular networks with the given IMSI and {@code ratType}. + * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering. + * See {@code TelephonyManager.NETWORK_TYPE_*}. + */ + public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, + @NetworkType int ratType) { + if (TextUtils.isEmpty(subscriberId)) { + return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + } + return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + } + + /** + * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ @UnsupportedAppUsage @@ -127,7 +153,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks, + * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks, * regardless of SSID. */ @UnsupportedAppUsage @@ -193,6 +219,7 @@ public class NetworkTemplate implements Parcelable { private final int mMetered; private final int mRoaming; private final int mDefaultNetwork; + private final int mSubType; @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { @@ -202,11 +229,11 @@ public class NetworkTemplate implements Parcelable { public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL); + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL); } public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String networkId, int metered, int roaming, int defaultNetwork) { + String networkId, int metered, int roaming, int defaultNetwork, int subType) { mMatchRule = matchRule; mSubscriberId = subscriberId; mMatchSubscriberIds = matchSubscriberIds; @@ -214,6 +241,7 @@ public class NetworkTemplate implements Parcelable { mMetered = metered; mRoaming = roaming; mDefaultNetwork = defaultNetwork; + mSubType = subType; if (!isKnownMatchRule(matchRule)) { Log.e(TAG, "Unknown network template rule " + matchRule @@ -229,6 +257,7 @@ public class NetworkTemplate implements Parcelable { mMetered = in.readInt(); mRoaming = in.readInt(); mDefaultNetwork = in.readInt(); + mSubType = in.readInt(); } @Override @@ -240,6 +269,7 @@ public class NetworkTemplate implements Parcelable { dest.writeInt(mMetered); dest.writeInt(mRoaming); dest.writeInt(mDefaultNetwork); + dest.writeInt(mSubType); } @Override @@ -272,13 +302,16 @@ public class NetworkTemplate implements Parcelable { builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( mDefaultNetwork)); } + if (mSubType != NETWORK_TYPE_ALL) { + builder.append(", subType=").append(mSubType); + } return builder.toString(); } @Override public int hashCode() { return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, - mDefaultNetwork); + mDefaultNetwork, mSubType); } @Override @@ -290,7 +323,8 @@ public class NetworkTemplate implements Parcelable { && Objects.equals(mNetworkId, other.mNetworkId) && mMetered == other.mMetered && mRoaming == other.mRoaming - && mDefaultNetwork == other.mDefaultNetwork; + && mDefaultNetwork == other.mDefaultNetwork + && mSubType == other.mSubType; } return false; } @@ -377,6 +411,11 @@ public class NetworkTemplate implements Parcelable { || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); } + private boolean matchesCollapsedRatType(NetworkIdentity ident) { + return mSubType == NETWORK_TYPE_ALL + || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType); + } + public boolean matchesSubscriberId(String subscriberId) { return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); } @@ -389,9 +428,13 @@ public class NetworkTemplate implements Parcelable { // TODO: consider matching against WiMAX subscriber identity return true; } else { + // Only metered mobile network would be matched regardless of metered filter. + // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. + // TODO: Respect metered filter and remove mMetered condition. return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) && !ArrayUtils.isEmpty(mMatchSubscriberIds) - && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); + && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) + && matchesCollapsedRatType(ident); } } @@ -461,7 +504,8 @@ public class NetworkTemplate implements Parcelable { if (ident.mType == TYPE_WIMAX) { return true; } else { - return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered); + return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) + && matchesCollapsedRatType(ident); } } From 3b85859418251660facac984b35d97fbdd47e1fd Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 31 Dec 2019 13:40:15 +0800 Subject: [PATCH 410/881] [SM05] Enable record mobile network stats by collapsed rat type Switch on the recording in device side. Metrics will be collected in follow-up patches which can be independently enabled/disabled. This change also fix the fail in NetworkStatsCollectionTest which caused by enabling this feature, where the rounding problem happened when records are distributed into smaller buckets and categorized into more NetworkIdentity. Test: atest FrameworksNetTests Bug: 129082217 Change-Id: If330e85330a4ff713dd420c98d42fa741eabd90a Merged-In: If330e85330a4ff713dd420c98d42fa741eabd90a (cherry picked from commit 2d4fa2c0fae8c2d79a25093d9f732a33c2f91dd4) --- core/java/android/net/NetworkIdentity.java | 2 +- .../core/java/com/android/server/net/NetworkStatsService.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index b67ad519b4..2cf3531d2f 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -45,7 +45,7 @@ public class NetworkIdentity implements Comparable { * {@link #SUBTYPE_COMBINED}. */ // TODO: make this flag configurable through settings. See http://b/146415925 - public static final boolean COMBINE_SUBTYPE_ENABLED = true; + public static final boolean COMBINE_SUBTYPE_ENABLED = false; public static final int SUBTYPE_COMBINED = -1; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 7c4624d25c..ff4407aa12 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1209,7 +1209,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; - if (LOGV) { + if (LOGD) { Log.d(TAG, "subtype changed for mobile: " + mLastCollapsedRatType + " -> " + collapsedRatType); } @@ -1217,7 +1217,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mHandler.removeMessages(MSG_UPDATE_IFACES); mLastCollapsedRatType = collapsedRatType; mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } } From 1227f32c58a839b6e9a0d765fff73bd9e1a84541 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 2 Jan 2020 19:35:59 +0800 Subject: [PATCH 411/881] [SM07] Make combine subtype configurable from Settings Note that enabling/disabling would not take effect until device reboot. This will be addressed in follow-up patch. Test: 1. atest NetworkStatsServieTest SettingsBackupTest 2. adb shell settings put global netstats_combine_subtype_enabled 1|0 Bug: 146415925 Change-Id: Ic94da540afa479ed18f1b6fbda4ae3216c37476b --- core/java/android/net/NetworkIdentity.java | 11 +-- .../server/net/NetworkStatsService.java | 69 ++++++++++++------- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 2cf3531d2f..0948a4da1a 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -40,13 +40,6 @@ import java.util.Objects; public class NetworkIdentity implements Comparable { private static final String TAG = "NetworkIdentity"; - /** - * When enabled, combine all {@link #mSubType} together under - * {@link #SUBTYPE_COMBINED}. - */ - // TODO: make this flag configurable through settings. See http://b/146415925 - public static final boolean COMBINE_SUBTYPE_ENABLED = false; - public static final int SUBTYPE_COMBINED = -1; final int mType; @@ -61,7 +54,7 @@ public class NetworkIdentity implements Comparable { int type, int subType, String subscriberId, String networkId, boolean roaming, boolean metered, boolean defaultNetwork) { mType = type; - mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType; + mSubType = subType; mSubscriberId = subscriberId; mNetworkId = networkId; mRoaming = roaming; @@ -93,7 +86,7 @@ public class NetworkIdentity implements Comparable { final StringBuilder builder = new StringBuilder("{"); builder.append("type=").append(getNetworkTypeName(mType)); builder.append(", subType="); - if (COMBINE_SUBTYPE_ENABLED) { + if (mSubType == SUBTYPE_COMBINED) { builder.append("COMBINED"); } else { builder.append(mSubType); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index ff4407aa12..d8264b3625 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,7 +27,6 @@ import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; -import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; @@ -52,6 +51,7 @@ import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; +import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED; import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; @@ -240,12 +240,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Settings that can be changed externally. */ public interface NetworkStatsSettings { - public long getPollInterval(); - public long getPollDelay(); - public boolean getSampleEnabled(); - public boolean getAugmentEnabled(); + long getPollInterval(); + long getPollDelay(); + boolean getSampleEnabled(); + boolean getAugmentEnabled(); + /** + * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}. + * When disabled, mobile data is broken down by a granular subtype representative of the + * actual subtype. {@see NetworkTemplate#getCollapsedRatType}. + * Enabling this decreases the level of detail but saves performance, disk space and + * amount of data logged. + */ + boolean getCombineSubtypeEnabled(); - public static class Config { + class Config { public final long bucketDuration; public final long rotateAgeMillis; public final long deleteAgeMillis; @@ -257,16 +265,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public Config getDevConfig(); - public Config getXtConfig(); - public Config getUidConfig(); - public Config getUidTagConfig(); + Config getDevConfig(); + Config getXtConfig(); + Config getUidConfig(); + Config getUidTagConfig(); - public long getGlobalAlertBytes(long def); - public long getDevPersistBytes(long def); - public long getXtPersistBytes(long def); - public long getUidPersistBytes(long def); - public long getUidTagPersistBytes(long def); + long getGlobalAlertBytes(long def); + long getDevPersistBytes(long def); + long getXtPersistBytes(long def); + long getUidPersistBytes(long def); + long getUidTagPersistBytes(long def); } private final Object mStatsLock = new Object(); @@ -509,9 +517,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: listen to changes from all subscriptions. + // TODO: 1. listen to changes from all subscriptions. + // 2. listen to settings changed to support dynamically enable/disable. // watch for networkType changes - if (!COMBINE_SUBTYPE_ENABLED) { + if (!mSettings.getCombineSubtypeEnabled()) { mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); } @@ -535,9 +544,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - if (!COMBINE_SUBTYPE_ENABLED) { - mTeleManager.listen(mPhoneListener, LISTEN_NONE); - } + mTeleManager.listen(mPhoneListener, LISTEN_NONE); final long currentTime = mClock.millis(); @@ -1265,12 +1272,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mLastNetworkStates = states; + final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); - final int subType = getSubTypeForState(state); + final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED + : getSubTypeForState(state); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, isDefault, subType); @@ -1334,13 +1343,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * If combine subtype is not enabled. For networks with {@code TRANSPORT_CELLULAR}, get - * subType that obtained through {@link PhoneStateListener}. Otherwise, return 0 given that - * other networks with different transport types do not actually fill this value. + * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through + * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different + * transport types do not actually fill this value. */ private int getSubTypeForState(@NonNull NetworkState state) { - if (COMBINE_SUBTYPE_ENABLED) return SUBTYPE_COMBINED; - if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return 0; } @@ -1702,6 +1709,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return; } + pw.println("Configs:"); + pw.increaseIndent(); + pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled()); + pw.println(); + pw.decreaseIndent(); + pw.println("Active interfaces:"); pw.increaseIndent(); for (int i = 0; i < mActiveIfaces.size(); i++) { @@ -2130,6 +2143,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true); } @Override + public boolean getCombineSubtypeEnabled() { + return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false); + } + @Override public Config getDevConfig() { return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), From 187a7b1ad85917a03daab13fb504c084b5c3d0d9 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 17 Mar 2020 00:16:13 +0900 Subject: [PATCH 412/881] Make Ethernet interfaces more testable. This CL adds a setIncludeTestInterfaces method to EthernetManager that, when called, causes the Ethernet service to recognize and manage test interfaces created by TestNetworkManager. Bug: 150644681 Test: Tested by EthernetTetheringTest in same topic Change-Id: I86eef7a93267f800dbfc8eafd307effa76a344ca --- core/java/android/net/EthernetManager.java | 15 +++++++++++++++ core/java/android/net/IEthernetManager.aidl | 1 + 2 files changed, 16 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 83b5f63576..d975017f9c 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -199,6 +199,21 @@ public class EthernetManager { } } + /** + * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface} + * as Ethernet interfaces. The effects of this method apply to any test interfaces that are + * already present on the system. + * @hide + */ + @TestApi + public void setIncludeTestInterfaces(boolean include) { + try { + mService.setIncludeTestInterfaces(include); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * A request for a tethered interface. */ diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl index ccc6e35209..e058e5a70c 100644 --- a/core/java/android/net/IEthernetManager.aidl +++ b/core/java/android/net/IEthernetManager.aidl @@ -33,6 +33,7 @@ interface IEthernetManager boolean isAvailable(String iface); void addListener(in IEthernetServiceListener listener); void removeListener(in IEthernetServiceListener listener); + void setIncludeTestInterfaces(boolean include); void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); } From 3845301fc73b9c67ea5de32f49853ede2fab0d13 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 2 Jan 2020 19:35:59 +0800 Subject: [PATCH 413/881] [SM07] Make combine subtype configurable from Settings Note that enabling/disabling would not take effect until device reboot. This will be addressed in follow-up patch. Test: 1. atest NetworkStatsServieTest SettingsBackupTest 2. adb shell settings put global netstats_combine_subtype_enabled 1|0 Bug: 146415925 Change-Id: Ic94da540afa479ed18f1b6fbda4ae3216c37476b Merged-In: Ic94da540afa479ed18f1b6fbda4ae3216c37476b (cherry picked from commit c4f77ac90bf2e48a655ad19b162fe74a23bf3fb0) --- core/java/android/net/NetworkIdentity.java | 11 +-- .../server/net/NetworkStatsService.java | 69 ++++++++++++------- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 2cf3531d2f..0948a4da1a 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -40,13 +40,6 @@ import java.util.Objects; public class NetworkIdentity implements Comparable { private static final String TAG = "NetworkIdentity"; - /** - * When enabled, combine all {@link #mSubType} together under - * {@link #SUBTYPE_COMBINED}. - */ - // TODO: make this flag configurable through settings. See http://b/146415925 - public static final boolean COMBINE_SUBTYPE_ENABLED = false; - public static final int SUBTYPE_COMBINED = -1; final int mType; @@ -61,7 +54,7 @@ public class NetworkIdentity implements Comparable { int type, int subType, String subscriberId, String networkId, boolean roaming, boolean metered, boolean defaultNetwork) { mType = type; - mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType; + mSubType = subType; mSubscriberId = subscriberId; mNetworkId = networkId; mRoaming = roaming; @@ -93,7 +86,7 @@ public class NetworkIdentity implements Comparable { final StringBuilder builder = new StringBuilder("{"); builder.append("type=").append(getNetworkTypeName(mType)); builder.append(", subType="); - if (COMBINE_SUBTYPE_ENABLED) { + if (mSubType == SUBTYPE_COMBINED) { builder.append("COMBINED"); } else { builder.append(mSubType); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index ff4407aa12..d8264b3625 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,7 +27,6 @@ import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; -import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; @@ -52,6 +51,7 @@ import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; +import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED; import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; @@ -240,12 +240,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Settings that can be changed externally. */ public interface NetworkStatsSettings { - public long getPollInterval(); - public long getPollDelay(); - public boolean getSampleEnabled(); - public boolean getAugmentEnabled(); + long getPollInterval(); + long getPollDelay(); + boolean getSampleEnabled(); + boolean getAugmentEnabled(); + /** + * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}. + * When disabled, mobile data is broken down by a granular subtype representative of the + * actual subtype. {@see NetworkTemplate#getCollapsedRatType}. + * Enabling this decreases the level of detail but saves performance, disk space and + * amount of data logged. + */ + boolean getCombineSubtypeEnabled(); - public static class Config { + class Config { public final long bucketDuration; public final long rotateAgeMillis; public final long deleteAgeMillis; @@ -257,16 +265,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public Config getDevConfig(); - public Config getXtConfig(); - public Config getUidConfig(); - public Config getUidTagConfig(); + Config getDevConfig(); + Config getXtConfig(); + Config getUidConfig(); + Config getUidTagConfig(); - public long getGlobalAlertBytes(long def); - public long getDevPersistBytes(long def); - public long getXtPersistBytes(long def); - public long getUidPersistBytes(long def); - public long getUidTagPersistBytes(long def); + long getGlobalAlertBytes(long def); + long getDevPersistBytes(long def); + long getXtPersistBytes(long def); + long getUidPersistBytes(long def); + long getUidTagPersistBytes(long def); } private final Object mStatsLock = new Object(); @@ -509,9 +517,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: listen to changes from all subscriptions. + // TODO: 1. listen to changes from all subscriptions. + // 2. listen to settings changed to support dynamically enable/disable. // watch for networkType changes - if (!COMBINE_SUBTYPE_ENABLED) { + if (!mSettings.getCombineSubtypeEnabled()) { mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); } @@ -535,9 +544,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - if (!COMBINE_SUBTYPE_ENABLED) { - mTeleManager.listen(mPhoneListener, LISTEN_NONE); - } + mTeleManager.listen(mPhoneListener, LISTEN_NONE); final long currentTime = mClock.millis(); @@ -1265,12 +1272,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mLastNetworkStates = states; + final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); - final int subType = getSubTypeForState(state); + final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED + : getSubTypeForState(state); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, isDefault, subType); @@ -1334,13 +1343,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * If combine subtype is not enabled. For networks with {@code TRANSPORT_CELLULAR}, get - * subType that obtained through {@link PhoneStateListener}. Otherwise, return 0 given that - * other networks with different transport types do not actually fill this value. + * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through + * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different + * transport types do not actually fill this value. */ private int getSubTypeForState(@NonNull NetworkState state) { - if (COMBINE_SUBTYPE_ENABLED) return SUBTYPE_COMBINED; - if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return 0; } @@ -1702,6 +1709,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return; } + pw.println("Configs:"); + pw.increaseIndent(); + pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled()); + pw.println(); + pw.decreaseIndent(); + pw.println("Active interfaces:"); pw.increaseIndent(); for (int i = 0; i < mActiveIfaces.size(); i++) { @@ -2130,6 +2143,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true); } @Override + public boolean getCombineSubtypeEnabled() { + return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false); + } + @Override public Config getDevConfig() { return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), From 55962ad9cb8a7285a6238eddde7db4ed03297609 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 12 Dec 2019 19:42:59 +0800 Subject: [PATCH 414/881] [SM02] Support record mobile network stats by collapsed rat type Previously network stats could be recorded by different rat type. However, the feature was disabled by ag/173504 since rat type frequently flapping between HSPA+ and UMTS. Given that this feature might be useful for collecting metrics, re-implement it based on current architecture and reduce the overhead introduced by frequently flapping by: 1. only react when rat type changes between 2G/3G/4G/5G. 2. reduce the number of records by only recording a subset of rat type that represented for a given network class. 3. enforce 1 second rate limit if flapping too much. Note that the feature is still disabled but will be enabled in follow-up patches. Test: manual test Bug: 129082217 Change-Id: Ic6b2f10f2c8b082820e0662eb9cee70d70d28cd6 Merged-In: Ic6b2f10f2c8b082820e0662eb9cee70d70d28cd6 (cherry picked from commit 96105f0d217a9cc168b0dda72f0125c1624ff692) --- core/java/android/net/NetworkIdentity.java | 15 ++-- core/java/android/net/NetworkTemplate.java | 40 +++++++++ .../server/net/NetworkStatsService.java | 89 ++++++++++++++++++- 3 files changed, 134 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index febc730480..1f7defcc82 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.service.NetworkIdentityProto; +import android.telephony.Annotation.NetworkType; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -42,11 +43,8 @@ public class NetworkIdentity implements Comparable { /** * When enabled, combine all {@link #mSubType} together under * {@link #SUBTYPE_COMBINED}. - * - * @deprecated we no longer offer to collect statistics on a per-subtype - * basis; this is always disabled. */ - @Deprecated + // TODO: make this flag configurable through settings. See http://b/146415925 public static final boolean COMBINE_SUBTYPE_ENABLED = true; public static final int SUBTYPE_COMBINED = -1; @@ -187,13 +185,14 @@ public class NetworkIdentity implements Comparable { } /** - * Build a {@link NetworkIdentity} from the given {@link NetworkState}, - * assuming that any mobile networks are using the current IMSI. + * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType}, + * assuming that any mobile networks are using the current IMSI. The subType if applicable, + * should be set as one of the TelephonyManager.NETWORK_TYPE_* constants, or + * {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. */ public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, - boolean defaultNetwork) { + boolean defaultNetwork, @NetworkType int subType) { final int type = state.networkInfo.getType(); - final int subType = state.networkInfo.getSubtype(); String subscriberId = null; String networkId = null; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 5498f74ba2..6080d16b9d 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.TelephonyManager; import android.util.BackupUtils; import android.util.Log; @@ -394,6 +395,45 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types. + * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}. + * + * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. + */ + // TODO: 1. Consider move this to TelephonyManager if used by other modules. + // 2. Consider make this configurable. + // 3. Use TelephonyManager APIs when available. + public static int getCollapsedRatType(int ratType) { + switch (ratType) { + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_GSM: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_IDEN: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_1xRTT: + return TelephonyManager.NETWORK_TYPE_GSM; + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + case TelephonyManager.NETWORK_TYPE_TD_SCDMA: + return TelephonyManager.NETWORK_TYPE_UMTS; + case TelephonyManager.NETWORK_TYPE_LTE: + case TelephonyManager.NETWORK_TYPE_IWLAN: + return TelephonyManager.NETWORK_TYPE_LTE; + case TelephonyManager.NETWORK_TYPE_NR: + return TelephonyManager.NETWORK_TYPE_NR; + default: + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } + /** * Check if matches Wi-Fi network template. */ diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 88fc0a6b11..efa638ad54 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,6 +27,8 @@ import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; +import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; @@ -45,6 +47,7 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; +import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -64,6 +67,9 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; +import static android.telephony.PhoneStateListener.LISTEN_NONE; +import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; +import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -109,6 +115,7 @@ import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.IBinder; import android.os.INetworkManagementService; @@ -125,6 +132,8 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; import android.text.format.DateUtils; @@ -157,6 +166,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -173,6 +183,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int MSG_PERFORM_POLL = 1; // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; + private static final int MSG_UPDATE_IFACES = 3; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -280,6 +291,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; + /** Last states of all networks sent from ConnectivityService. */ + @GuardedBy("mStatsLock") + @Nullable + private NetworkState[] mLastNetworkStates = null; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -355,6 +371,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performPoll(FLAG_PERSIST_ALL); break; } + case MSG_UPDATE_IFACES: { + // If no cached states, ignore. + if (mLastNetworkStates == null) break; + updateIfaces(mDefaultNetworks, mLastNetworkStates, mActiveIface); + break; + } case MSG_PERFORM_POLL_REGISTER_ALERT: { performPoll(FLAG_PERSIST_NETWORK); registerGlobalAlert(); @@ -407,6 +429,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); + mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); } /** @@ -486,6 +509,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); + // TODO: listen to changes from all subscriptions. + // watch for networkType changes + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + } + registerGlobalAlert(); } @@ -506,6 +535,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); + if (!COMBINE_SUBTYPE_ENABLED) { + mTeleManager.listen(mPhoneListener, LISTEN_NONE); + } + final long currentTime = mClock.millis(); // persist any pending stats @@ -1156,6 +1189,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; + /** + * Receiver that watches for {@link TelephonyManager} changes, such as + * transitioning between Radio Access Technology(RAT) types. + */ + @NonNull + private final NetworkTypeListener mPhoneListener; + + class NetworkTypeListener extends PhoneStateListener { + private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; + + NetworkTypeListener(@NonNull Executor executor) { + super(executor); + } + + @Override + public void onServiceStateChanged(@NonNull ServiceState ss) { + final int networkType = ss.getDataNetworkType(); + final int collapsedRatType = getCollapsedRatType(networkType); + if (collapsedRatType == mLastCollapsedRatType) return; + + if (LOGV) { + Log.d(TAG, "subtype changed for mobile: " + + mLastCollapsedRatType + " -> " + collapsedRatType); + } + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mLastCollapsedRatType = collapsedRatType; + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); + } + } + private void updateIfaces( Network[] defaultNetworks, NetworkState[] networkStates, @@ -1177,7 +1242,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(Network[] defaultNetworks, NetworkState[] states) { + private void updateIfacesLocked(@Nullable Network[] defaultNetworks, + @NonNull NetworkState[] states) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1197,13 +1263,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mDefaultNetworks = defaultNetworks; } + mLastNetworkStates = states; + final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); + final int subType = getSubTypeForState(state); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, - isDefault); + isDefault, subType); // Traffic occurring on the base interface is always counted for // both total usage and UID details. @@ -1264,6 +1333,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]); } + /** + * If combine subtype is not enabled. For networks with {@code TRANSPORT_CELLULAR}, get + * subType that obtained through {@link PhoneStateListener}. Otherwise, return 0 given that + * other networks with different transport types do not actually fill this value. + */ + private int getSubTypeForState(@NonNull NetworkState state) { + if (COMBINE_SUBTYPE_ENABLED) return SUBTYPE_COMBINED; + + if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + return 0; + } + + // TODO: return different subType for different subscriptions. + return mPhoneListener.mLastCollapsedRatType; + } + private static NetworkIdentitySet findOrCreateNetworkIdentitySet( ArrayMap map, K key) { NetworkIdentitySet ident = map.get(key); From d83a0e0d1ea5e46582c3ab2fcfbdb6d195fc053b Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 20 Dec 2019 16:35:34 +0800 Subject: [PATCH 415/881] [SM04] Support fetching data with NetworkTemplate with subType Add a NetworkTemplate build function that allows user to specify subType. NetworkStats corresponding to the same group would be retrieved. Test: atest FrameworksNetTests Bug: 129082217 Change-Id: Ie2d229be0b6bd239f799989c070475c73a096d71 Merged-In: Ie2d229be0b6bd239f799989c070475c73a096d71 (cherry picked from commit 82d9f7cbb0e684d2de2911be3a0473c3edbc50df) --- core/java/android/net/NetworkTemplate.java | 60 +++++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 6080d16b9d..cb9463a59d 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,10 +34,13 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.sanitizeSsid; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.NetworkType; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.BackupUtils; import android.util.Log; @@ -74,6 +77,14 @@ public class NetworkTemplate implements Parcelable { public static final int MATCH_BLUETOOTH = 8; public static final int MATCH_PROXY = 9; + /** + * Include all network types when filtering. This is meant to merge in with the + * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. + * + * @hide + */ + public static final int NETWORK_TYPE_ALL = -1; + private static boolean isKnownMatchRule(final int rule) { switch (rule) { case MATCH_MOBILE: @@ -118,7 +129,22 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks, + * Template to match cellular networks with the given IMSI and {@code ratType}. + * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering. + * See {@code TelephonyManager.NETWORK_TYPE_*}. + */ + public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, + @NetworkType int ratType) { + if (TextUtils.isEmpty(subscriberId)) { + return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + } + return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + } + + /** + * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ @UnsupportedAppUsage @@ -127,7 +153,7 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks, + * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks, * regardless of SSID. */ @UnsupportedAppUsage @@ -193,6 +219,7 @@ public class NetworkTemplate implements Parcelable { private final int mMetered; private final int mRoaming; private final int mDefaultNetwork; + private final int mSubType; @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { @@ -202,11 +229,11 @@ public class NetworkTemplate implements Parcelable { public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL); + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL); } public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String networkId, int metered, int roaming, int defaultNetwork) { + String networkId, int metered, int roaming, int defaultNetwork, int subType) { mMatchRule = matchRule; mSubscriberId = subscriberId; mMatchSubscriberIds = matchSubscriberIds; @@ -214,6 +241,7 @@ public class NetworkTemplate implements Parcelable { mMetered = metered; mRoaming = roaming; mDefaultNetwork = defaultNetwork; + mSubType = subType; if (!isKnownMatchRule(matchRule)) { Log.e(TAG, "Unknown network template rule " + matchRule @@ -229,6 +257,7 @@ public class NetworkTemplate implements Parcelable { mMetered = in.readInt(); mRoaming = in.readInt(); mDefaultNetwork = in.readInt(); + mSubType = in.readInt(); } @Override @@ -240,6 +269,7 @@ public class NetworkTemplate implements Parcelable { dest.writeInt(mMetered); dest.writeInt(mRoaming); dest.writeInt(mDefaultNetwork); + dest.writeInt(mSubType); } @Override @@ -272,13 +302,16 @@ public class NetworkTemplate implements Parcelable { builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( mDefaultNetwork)); } + if (mSubType != NETWORK_TYPE_ALL) { + builder.append(", subType=").append(mSubType); + } return builder.toString(); } @Override public int hashCode() { return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, - mDefaultNetwork); + mDefaultNetwork, mSubType); } @Override @@ -290,7 +323,8 @@ public class NetworkTemplate implements Parcelable { && Objects.equals(mNetworkId, other.mNetworkId) && mMetered == other.mMetered && mRoaming == other.mRoaming - && mDefaultNetwork == other.mDefaultNetwork; + && mDefaultNetwork == other.mDefaultNetwork + && mSubType == other.mSubType; } return false; } @@ -377,6 +411,11 @@ public class NetworkTemplate implements Parcelable { || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); } + private boolean matchesCollapsedRatType(NetworkIdentity ident) { + return mSubType == NETWORK_TYPE_ALL + || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType); + } + public boolean matchesSubscriberId(String subscriberId) { return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); } @@ -389,9 +428,13 @@ public class NetworkTemplate implements Parcelable { // TODO: consider matching against WiMAX subscriber identity return true; } else { + // Only metered mobile network would be matched regardless of metered filter. + // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. + // TODO: Respect metered filter and remove mMetered condition. return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) && !ArrayUtils.isEmpty(mMatchSubscriberIds) - && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); + && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) + && matchesCollapsedRatType(ident); } } @@ -461,7 +504,8 @@ public class NetworkTemplate implements Parcelable { if (ident.mType == TYPE_WIMAX) { return true; } else { - return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered); + return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) + && matchesCollapsedRatType(ident); } } From b2067520a2736c6b80ea28b46350946c25e1ad4a Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 31 Dec 2019 13:40:15 +0800 Subject: [PATCH 416/881] [SM05] Enable record mobile network stats by collapsed rat type Switch on the recording in device side. Metrics will be collected in follow-up patches which can be independently enabled/disabled. This change also fix the fail in NetworkStatsCollectionTest which caused by enabling this feature, where the rounding problem happened when records are distributed into smaller buckets and categorized into more NetworkIdentity. Test: atest FrameworksNetTests Bug: 129082217 Change-Id: If330e85330a4ff713dd420c98d42fa741eabd90a Merged-In: If330e85330a4ff713dd420c98d42fa741eabd90a (cherry picked from commit 8413d3c1af0f6bdf5a9dbf0ef28c48e99f599a93) --- core/java/android/net/NetworkIdentity.java | 2 +- .../core/java/com/android/server/net/NetworkStatsService.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 1f7defcc82..4e33770bf2 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -45,7 +45,7 @@ public class NetworkIdentity implements Comparable { * {@link #SUBTYPE_COMBINED}. */ // TODO: make this flag configurable through settings. See http://b/146415925 - public static final boolean COMBINE_SUBTYPE_ENABLED = true; + public static final boolean COMBINE_SUBTYPE_ENABLED = false; public static final int SUBTYPE_COMBINED = -1; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index efa638ad54..8f4c6d02ba 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1209,7 +1209,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; - if (LOGV) { + if (LOGD) { Log.d(TAG, "subtype changed for mobile: " + mLastCollapsedRatType + " -> " + collapsedRatType); } @@ -1217,7 +1217,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mHandler.removeMessages(MSG_UPDATE_IFACES); mLastCollapsedRatType = collapsedRatType; mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } } From f6f863428eedb74d4e4baa56378e6012ceedb9ca Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 2 Jan 2020 19:35:59 +0800 Subject: [PATCH 417/881] [SM07] Make combine subtype configurable from Settings Note that enabling/disabling would not take effect until device reboot. This will be addressed in follow-up patch. Test: 1. atest NetworkStatsServieTest SettingsBackupTest 2. adb shell settings put global netstats_combine_subtype_enabled 1|0 Bug: 146415925 Change-Id: Ic94da540afa479ed18f1b6fbda4ae3216c37476b Merged-In: Ic94da540afa479ed18f1b6fbda4ae3216c37476b (cherry picked from commit 1227f32c58a839b6e9a0d765fff73bd9e1a84541 and fix merge conflict in SettingsBackupTest) --- core/java/android/net/NetworkIdentity.java | 11 +-- .../server/net/NetworkStatsService.java | 69 ++++++++++++------- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 4e33770bf2..4edbcd0ac8 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -40,13 +40,6 @@ import java.util.Objects; public class NetworkIdentity implements Comparable { private static final String TAG = "NetworkIdentity"; - /** - * When enabled, combine all {@link #mSubType} together under - * {@link #SUBTYPE_COMBINED}. - */ - // TODO: make this flag configurable through settings. See http://b/146415925 - public static final boolean COMBINE_SUBTYPE_ENABLED = false; - public static final int SUBTYPE_COMBINED = -1; final int mType; @@ -61,7 +54,7 @@ public class NetworkIdentity implements Comparable { int type, int subType, String subscriberId, String networkId, boolean roaming, boolean metered, boolean defaultNetwork) { mType = type; - mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType; + mSubType = subType; mSubscriberId = subscriberId; mNetworkId = networkId; mRoaming = roaming; @@ -93,7 +86,7 @@ public class NetworkIdentity implements Comparable { final StringBuilder builder = new StringBuilder("{"); builder.append("type=").append(getNetworkTypeName(mType)); builder.append(", subType="); - if (COMBINE_SUBTYPE_ENABLED) { + if (mSubType == SUBTYPE_COMBINED) { builder.append("COMBINED"); } else { builder.append(mSubType); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 8f4c6d02ba..2680858743 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -27,7 +27,6 @@ import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; -import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; @@ -52,6 +51,7 @@ import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; +import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED; import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; @@ -240,12 +240,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Settings that can be changed externally. */ public interface NetworkStatsSettings { - public long getPollInterval(); - public long getPollDelay(); - public boolean getSampleEnabled(); - public boolean getAugmentEnabled(); + long getPollInterval(); + long getPollDelay(); + boolean getSampleEnabled(); + boolean getAugmentEnabled(); + /** + * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}. + * When disabled, mobile data is broken down by a granular subtype representative of the + * actual subtype. {@see NetworkTemplate#getCollapsedRatType}. + * Enabling this decreases the level of detail but saves performance, disk space and + * amount of data logged. + */ + boolean getCombineSubtypeEnabled(); - public static class Config { + class Config { public final long bucketDuration; public final long rotateAgeMillis; public final long deleteAgeMillis; @@ -257,16 +265,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public Config getDevConfig(); - public Config getXtConfig(); - public Config getUidConfig(); - public Config getUidTagConfig(); + Config getDevConfig(); + Config getXtConfig(); + Config getUidConfig(); + Config getUidTagConfig(); - public long getGlobalAlertBytes(long def); - public long getDevPersistBytes(long def); - public long getXtPersistBytes(long def); - public long getUidPersistBytes(long def); - public long getUidTagPersistBytes(long def); + long getGlobalAlertBytes(long def); + long getDevPersistBytes(long def); + long getXtPersistBytes(long def); + long getUidPersistBytes(long def); + long getUidTagPersistBytes(long def); } private final Object mStatsLock = new Object(); @@ -509,9 +517,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: listen to changes from all subscriptions. + // TODO: 1. listen to changes from all subscriptions. + // 2. listen to settings changed to support dynamically enable/disable. // watch for networkType changes - if (!COMBINE_SUBTYPE_ENABLED) { + if (!mSettings.getCombineSubtypeEnabled()) { mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); } @@ -535,9 +544,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - if (!COMBINE_SUBTYPE_ENABLED) { - mTeleManager.listen(mPhoneListener, LISTEN_NONE); - } + mTeleManager.listen(mPhoneListener, LISTEN_NONE); final long currentTime = mClock.millis(); @@ -1265,12 +1272,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mLastNetworkStates = states; + final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); - final int subType = getSubTypeForState(state); + final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED + : getSubTypeForState(state); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, isDefault, subType); @@ -1334,13 +1343,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * If combine subtype is not enabled. For networks with {@code TRANSPORT_CELLULAR}, get - * subType that obtained through {@link PhoneStateListener}. Otherwise, return 0 given that - * other networks with different transport types do not actually fill this value. + * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through + * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different + * transport types do not actually fill this value. */ private int getSubTypeForState(@NonNull NetworkState state) { - if (COMBINE_SUBTYPE_ENABLED) return SUBTYPE_COMBINED; - if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return 0; } @@ -1702,6 +1709,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return; } + pw.println("Configs:"); + pw.increaseIndent(); + pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled()); + pw.println(); + pw.decreaseIndent(); + pw.println("Active interfaces:"); pw.increaseIndent(); for (int i = 0; i < mActiveIfaces.size(); i++) { @@ -2130,6 +2143,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true); } @Override + public boolean getCombineSubtypeEnabled() { + return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false); + } + @Override public Config getDevConfig() { return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), From 9b0d58ee181e7fd679d0e1a15df92f67479fef96 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 17 Mar 2020 00:11:37 +0900 Subject: [PATCH 418/881] Make Ethernet interfaces more testable. This CL adds a setIncludeTestInterfaces method to EthernetManager that, when called, causes the Ethernet service to recognize and manage test interfaces created by TestNetworkManager. Bug: 150644681 Test: Tested by EthernetTetheringTest in same topic Change-Id: I86eef7a93267f800dbfc8eafd307effa76a344ca --- .../server/ethernet/EthernetServiceImpl.java | 13 ++++++-- .../server/ethernet/EthernetTracker.java | 32 ++++++++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 1cf38b45f4..3fc6aab758 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -163,15 +163,24 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker.removeListener(listener); } + @Override + public void setIncludeTestInterfaces(boolean include) { + NetworkStack.checkNetworkStackPermissionOr(mContext, + android.Manifest.permission.NETWORK_SETTINGS); + mTracker.setIncludeTestInterfaces(include); + } + @Override public void requestTetheredInterface(ITetheredInterfaceCallback callback) { - NetworkStack.checkNetworkStackPermission(mContext); + NetworkStack.checkNetworkStackPermissionOr(mContext, + android.Manifest.permission.NETWORK_SETTINGS); mTracker.requestTetheredInterface(callback); } @Override public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { - NetworkStack.checkNetworkStackPermission(mContext); + NetworkStack.checkNetworkStackPermissionOr(mContext, + android.Manifest.permission.NETWORK_SETTINGS); mTracker.releaseTetheredInterface(callback); } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 58803d14fe..91453abe1a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -16,6 +16,8 @@ package com.android.server.ethernet; +import static android.net.TestNetworkManager.TEST_TAP_PREFIX; + import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; @@ -68,8 +70,12 @@ final class EthernetTracker { private final static String TAG = EthernetTracker.class.getSimpleName(); private final static boolean DBG = EthernetNetworkFactory.DBG; - /** Product-dependent regular expression of interface names we track. */ - private final String mIfaceMatch; + /** + * Interface names we track. This is a product-dependent regular expression, plus, + * if setIncludeTestInterfaces is true, any test interfaces. + */ + private String mIfaceMatch; + private boolean mIncludeTestInterfaces = false; /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */ private final ConcurrentHashMap mNetworkCapabilities = @@ -111,8 +117,7 @@ final class EthernetTracker { mNMService = INetworkManagementService.Stub.asInterface(b); // Interface match regex. - mIfaceMatch = context.getResources().getString( - com.android.internal.R.string.config_ethernet_iface_regex); + updateIfaceMatchRegexp(); // Read default Ethernet interface configuration from resources final String[] interfaceConfigs = context.getResources().getStringArray( @@ -187,6 +192,12 @@ final class EthernetTracker { mListeners.unregister(listener); } + public void setIncludeTestInterfaces(boolean include) { + mIncludeTestInterfaces = include; + updateIfaceMatchRegexp(); + trackAvailableInterfaces(); + } + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { mHandler.post(() -> { if (!mTetheredInterfaceRequests.register(callback)) { @@ -348,7 +359,8 @@ final class EthernetTracker { if (DBG) Log.i(TAG, "maybeTrackInterface " + iface); // If we don't already track this interface, and if this interface matches // our regex, start tracking it. - if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface)) { + if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface) + || iface.equals(mDefaultInterface)) { return; } @@ -572,6 +584,16 @@ final class EthernetTracker { return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); } + private void updateIfaceMatchRegexp() { + final String testInterfaceMatch = TEST_TAP_PREFIX + ".*"; + final String match = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_iface_regex); + mIfaceMatch = mIncludeTestInterfaces + ? "(" + match + "|" + TEST_TAP_PREFIX + "\\d+)" + : match; + Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'"); + } + private void postAndWaitForRunnable(Runnable r) { mHandler.runWithScissors(r, 2000L /* timeout */); } From ad35ebfec14320ae59f4a43acadf956b17b1d90a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 19 Mar 2020 11:46:55 +0000 Subject: [PATCH 419/881] Make Ethernet interfaces more testable. This CL adds a setIncludeTestInterfaces method to EthernetManager that, when called, causes the Ethernet service to recognize and manage test interfaces created by TestNetworkManager. Bug: 150644681 Test: Tested by EthernetTetheringTest in same topic Change-Id: I86eef7a93267f800dbfc8eafd307effa76a344ca Merged-In: I86eef7a93267f800dbfc8eafd307effa76a344ca (cherry picked from commit 4978dbd5fb6592fc4e7be08d02783752245da634) --- .../server/ethernet/EthernetServiceImpl.java | 13 ++++++-- .../server/ethernet/EthernetTracker.java | 32 ++++++++++++++++--- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 1cf38b45f4..3fc6aab758 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -163,15 +163,24 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker.removeListener(listener); } + @Override + public void setIncludeTestInterfaces(boolean include) { + NetworkStack.checkNetworkStackPermissionOr(mContext, + android.Manifest.permission.NETWORK_SETTINGS); + mTracker.setIncludeTestInterfaces(include); + } + @Override public void requestTetheredInterface(ITetheredInterfaceCallback callback) { - NetworkStack.checkNetworkStackPermission(mContext); + NetworkStack.checkNetworkStackPermissionOr(mContext, + android.Manifest.permission.NETWORK_SETTINGS); mTracker.requestTetheredInterface(callback); } @Override public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { - NetworkStack.checkNetworkStackPermission(mContext); + NetworkStack.checkNetworkStackPermissionOr(mContext, + android.Manifest.permission.NETWORK_SETTINGS); mTracker.releaseTetheredInterface(callback); } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 58803d14fe..91453abe1a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -16,6 +16,8 @@ package com.android.server.ethernet; +import static android.net.TestNetworkManager.TEST_TAP_PREFIX; + import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; @@ -68,8 +70,12 @@ final class EthernetTracker { private final static String TAG = EthernetTracker.class.getSimpleName(); private final static boolean DBG = EthernetNetworkFactory.DBG; - /** Product-dependent regular expression of interface names we track. */ - private final String mIfaceMatch; + /** + * Interface names we track. This is a product-dependent regular expression, plus, + * if setIncludeTestInterfaces is true, any test interfaces. + */ + private String mIfaceMatch; + private boolean mIncludeTestInterfaces = false; /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */ private final ConcurrentHashMap mNetworkCapabilities = @@ -111,8 +117,7 @@ final class EthernetTracker { mNMService = INetworkManagementService.Stub.asInterface(b); // Interface match regex. - mIfaceMatch = context.getResources().getString( - com.android.internal.R.string.config_ethernet_iface_regex); + updateIfaceMatchRegexp(); // Read default Ethernet interface configuration from resources final String[] interfaceConfigs = context.getResources().getStringArray( @@ -187,6 +192,12 @@ final class EthernetTracker { mListeners.unregister(listener); } + public void setIncludeTestInterfaces(boolean include) { + mIncludeTestInterfaces = include; + updateIfaceMatchRegexp(); + trackAvailableInterfaces(); + } + public void requestTetheredInterface(ITetheredInterfaceCallback callback) { mHandler.post(() -> { if (!mTetheredInterfaceRequests.register(callback)) { @@ -348,7 +359,8 @@ final class EthernetTracker { if (DBG) Log.i(TAG, "maybeTrackInterface " + iface); // If we don't already track this interface, and if this interface matches // our regex, start tracking it. - if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface)) { + if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface) + || iface.equals(mDefaultInterface)) { return; } @@ -572,6 +584,16 @@ final class EthernetTracker { return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); } + private void updateIfaceMatchRegexp() { + final String testInterfaceMatch = TEST_TAP_PREFIX + ".*"; + final String match = mContext.getResources().getString( + com.android.internal.R.string.config_ethernet_iface_regex); + mIfaceMatch = mIncludeTestInterfaces + ? "(" + match + "|" + TEST_TAP_PREFIX + "\\d+)" + : match; + Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'"); + } + private void postAndWaitForRunnable(Runnable r) { mHandler.runWithScissors(r, 2000L /* timeout */); } From 3eacb9682e89de608316e4090822a66ab6193361 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 19 Mar 2020 11:46:55 +0000 Subject: [PATCH 420/881] Make Ethernet interfaces more testable. This CL adds a setIncludeTestInterfaces method to EthernetManager that, when called, causes the Ethernet service to recognize and manage test interfaces created by TestNetworkManager. Bug: 150644681 Test: Tested by EthernetTetheringTest in same topic Change-Id: I86eef7a93267f800dbfc8eafd307effa76a344ca Merged-In: I86eef7a93267f800dbfc8eafd307effa76a344ca (cherry picked from commit 3410fb0aa92bbd4f9d7dc031e89f6f528ff34245) --- core/java/android/net/EthernetManager.java | 15 +++++++++++++++ core/java/android/net/IEthernetManager.aidl | 1 + 2 files changed, 16 insertions(+) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 83b5f63576..d975017f9c 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -199,6 +199,21 @@ public class EthernetManager { } } + /** + * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface} + * as Ethernet interfaces. The effects of this method apply to any test interfaces that are + * already present on the system. + * @hide + */ + @TestApi + public void setIncludeTestInterfaces(boolean include) { + try { + mService.setIncludeTestInterfaces(include); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * A request for a tethered interface. */ diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl index ccc6e35209..e058e5a70c 100644 --- a/core/java/android/net/IEthernetManager.aidl +++ b/core/java/android/net/IEthernetManager.aidl @@ -33,6 +33,7 @@ interface IEthernetManager boolean isAvailable(String iface); void addListener(in IEthernetServiceListener listener); void removeListener(in IEthernetServiceListener listener); + void setIncludeTestInterfaces(boolean include); void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); } From 42cecb0751b5839f60d7835b49ae0bf3a681fe1a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 17 Mar 2020 00:11:37 +0900 Subject: [PATCH 421/881] Support setting the default interface to null again. Currently, the default interface can only ever go from null to non-null. This is correct for fixed interfaces (because they don't get unplugged) and it's generally correct for USB interfaces that use ethX as their device name (because when they are unplugged and plugged in again, the device name won't change). But it is not correct if, for example, the default interface is a test interface. So, allow mDefaultInterface to go back to null. This CL also fixes a crash if a tethered interface request is added and removed when there is no default interface. Also, make dump() report tethered interface requests. Also remove an unused variable that I missed in the previous CL. Bug: 150644681 Test: tested by EthernetTetheringTest in same topic Change-Id: I5109d8da3aeb6c1f6523291d9e2ec92c64b5ad2d --- .../server/ethernet/EthernetTracker.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 91453abe1a..d1f1402311 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -240,17 +240,17 @@ final class EthernetTracker { private void maybeUntetherDefaultInterface() { if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return; - // mDefaultInterface null means that there never was a default interface (it is never set - // to null). - if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT || mDefaultInterface == null) return; - + if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT) return; setDefaultInterfaceMode(INTERFACE_MODE_CLIENT); } private void setDefaultInterfaceMode(int mode) { + Log.d(TAG, "Setting default interface mode to " + mode); mDefaultInterfaceMode = mode; - removeInterface(mDefaultInterface); - addInterface(mDefaultInterface); + if (mDefaultInterface != null) { + removeInterface(mDefaultInterface); + addInterface(mDefaultInterface); + } } private int getInterfaceMode(final String iface) { @@ -264,6 +264,13 @@ final class EthernetTracker { mFactory.removeInterface(iface); } + private void stopTrackingInterface(String iface) { + removeInterface(iface); + if (iface.equals(mDefaultInterface)) { + mDefaultInterface = null; + } + } + private void addInterface(String iface) { InterfaceConfiguration config = null; // Bring up the interface so we get link status indications. @@ -406,7 +413,7 @@ final class EthernetTracker { @Override public void interfaceRemoved(String iface) { - mHandler.post(() -> removeInterface(iface)); + mHandler.post(() -> stopTrackingInterface(iface)); } } @@ -585,7 +592,6 @@ final class EthernetTracker { } private void updateIfaceMatchRegexp() { - final String testInterfaceMatch = TEST_TAP_PREFIX + ".*"; final String match = mContext.getResources().getString( com.android.internal.R.string.config_ethernet_iface_regex); mIfaceMatch = mIncludeTestInterfaces @@ -604,6 +610,8 @@ final class EthernetTracker { pw.println("Ethernet interface name filter: " + mIfaceMatch); pw.println("Default interface: " + mDefaultInterface); pw.println("Default interface mode: " + mDefaultInterfaceMode); + pw.println("Tethered interface requests: " + + mTetheredInterfaceRequests.getRegisteredCallbackCount()); pw.println("Listeners: " + mListeners.getRegisteredCallbackCount()); pw.println("IP Configurations:"); pw.increaseIndent(); From 149860a4269beccf62215e2e06c69066b07b30a9 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 19 Mar 2020 14:36:24 +0900 Subject: [PATCH 422/881] Send tethered interface callbacks based on interface existence. Currently, callbacks for tethered interface availability are sent based on interface link state. This is incorrect: - It is acceptable and expected to be able to enable tethering on an interface that does not yet have link up. - It doesn't seem useful to disable Ethernet tethering if link temporarily goes down. Instead, only base the callbacks on whether an interface exists or not. Bug: 150644681 Test: WIP tests in aosp/1260100 pass Change-Id: I015219cbd03626c38fb5156d0cb2991ba7d7def7 --- .../src/com/android/server/ethernet/EthernetTracker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index d1f1402311..336ddef23a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -262,6 +262,7 @@ final class EthernetTracker { private void removeInterface(String iface) { mFactory.removeInterface(iface); + maybeUpdateServerModeInterfaceState(iface, false); } private void stopTrackingInterface(String iface) { @@ -308,6 +309,8 @@ final class EthernetTracker { Log.d(TAG, "Started tracking interface " + iface); mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + } else { + maybeUpdateServerModeInterfaceState(iface, true); } // Note: if the interface already has link (e.g., if we crashed and got @@ -341,12 +344,9 @@ final class EthernetTracker { } mListeners.finishBroadcast(); } - - updateServerModeInterfaceState(iface, up, mode); } - private void updateServerModeInterfaceState(String iface, boolean up, int mode) { - final boolean available = up && (mode == INTERFACE_MODE_SERVER); + private void maybeUpdateServerModeInterfaceState(String iface, boolean available) { if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); From 356cf6ab8263ce25263846891f8b95d8ba136c43 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 19 Mar 2020 15:52:03 +0000 Subject: [PATCH 423/881] Support setting the default interface to null again. Currently, the default interface can only ever go from null to non-null. This is correct for fixed interfaces (because they don't get unplugged) and it's generally correct for USB interfaces that use ethX as their device name (because when they are unplugged and plugged in again, the device name won't change). But it is not correct if, for example, the default interface is a test interface. So, allow mDefaultInterface to go back to null. This CL also fixes a crash if a tethered interface request is added and removed when there is no default interface. Also, make dump() report tethered interface requests. Also remove an unused variable that I missed in the previous CL. Bug: 150644681 Test: tested by EthernetTetheringTest in same topic Change-Id: I5109d8da3aeb6c1f6523291d9e2ec92c64b5ad2d Merged-In: I5109d8da3aeb6c1f6523291d9e2ec92c64b5ad2d (cherry picked from commit cc156c2f7793731b2699e194d4b164138ee4cf62) --- .../server/ethernet/EthernetTracker.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 91453abe1a..d1f1402311 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -240,17 +240,17 @@ final class EthernetTracker { private void maybeUntetherDefaultInterface() { if (mTetheredInterfaceRequests.getRegisteredCallbackCount() > 0) return; - // mDefaultInterface null means that there never was a default interface (it is never set - // to null). - if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT || mDefaultInterface == null) return; - + if (mDefaultInterfaceMode == INTERFACE_MODE_CLIENT) return; setDefaultInterfaceMode(INTERFACE_MODE_CLIENT); } private void setDefaultInterfaceMode(int mode) { + Log.d(TAG, "Setting default interface mode to " + mode); mDefaultInterfaceMode = mode; - removeInterface(mDefaultInterface); - addInterface(mDefaultInterface); + if (mDefaultInterface != null) { + removeInterface(mDefaultInterface); + addInterface(mDefaultInterface); + } } private int getInterfaceMode(final String iface) { @@ -264,6 +264,13 @@ final class EthernetTracker { mFactory.removeInterface(iface); } + private void stopTrackingInterface(String iface) { + removeInterface(iface); + if (iface.equals(mDefaultInterface)) { + mDefaultInterface = null; + } + } + private void addInterface(String iface) { InterfaceConfiguration config = null; // Bring up the interface so we get link status indications. @@ -406,7 +413,7 @@ final class EthernetTracker { @Override public void interfaceRemoved(String iface) { - mHandler.post(() -> removeInterface(iface)); + mHandler.post(() -> stopTrackingInterface(iface)); } } @@ -585,7 +592,6 @@ final class EthernetTracker { } private void updateIfaceMatchRegexp() { - final String testInterfaceMatch = TEST_TAP_PREFIX + ".*"; final String match = mContext.getResources().getString( com.android.internal.R.string.config_ethernet_iface_regex); mIfaceMatch = mIncludeTestInterfaces @@ -604,6 +610,8 @@ final class EthernetTracker { pw.println("Ethernet interface name filter: " + mIfaceMatch); pw.println("Default interface: " + mDefaultInterface); pw.println("Default interface mode: " + mDefaultInterfaceMode); + pw.println("Tethered interface requests: " + + mTetheredInterfaceRequests.getRegisteredCallbackCount()); pw.println("Listeners: " + mListeners.getRegisteredCallbackCount()); pw.println("IP Configurations:"); pw.increaseIndent(); From a45861dd6763eb0c210ad03d8065c264f80ad64f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 19 Mar 2020 15:52:09 +0000 Subject: [PATCH 424/881] Send tethered interface callbacks based on interface existence. Currently, callbacks for tethered interface availability are sent based on interface link state. This is incorrect: - It is acceptable and expected to be able to enable tethering on an interface that does not yet have link up. - It doesn't seem useful to disable Ethernet tethering if link temporarily goes down. Instead, only base the callbacks on whether an interface exists or not. Bug: 150644681 Test: WIP tests in aosp/1260100 pass Change-Id: I015219cbd03626c38fb5156d0cb2991ba7d7def7 Merged-In: I015219cbd03626c38fb5156d0cb2991ba7d7def7 (cherry picked from commit 64d12ea20ce3cd822518e0f15ed7483a2fb91a50) --- .../src/com/android/server/ethernet/EthernetTracker.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index d1f1402311..336ddef23a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -262,6 +262,7 @@ final class EthernetTracker { private void removeInterface(String iface) { mFactory.removeInterface(iface); + maybeUpdateServerModeInterfaceState(iface, false); } private void stopTrackingInterface(String iface) { @@ -308,6 +309,8 @@ final class EthernetTracker { Log.d(TAG, "Started tracking interface " + iface); mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + } else { + maybeUpdateServerModeInterfaceState(iface, true); } // Note: if the interface already has link (e.g., if we crashed and got @@ -341,12 +344,9 @@ final class EthernetTracker { } mListeners.finishBroadcast(); } - - updateServerModeInterfaceState(iface, up, mode); } - private void updateServerModeInterfaceState(String iface, boolean up, int mode) { - final boolean available = up && (mode == INTERFACE_MODE_SERVER); + private void maybeUpdateServerModeInterfaceState(String iface, boolean available) { if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); From 782c7307aa15c5052a81e024838f25f2b7f8a251 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 11 Feb 2020 14:59:38 +0800 Subject: [PATCH 425/881] [SM06] Collect mobile NetworkStats metrics by collapsed rat type Test: adb shell cmd stats pull-source 10000~10003 adb shell dumpsys netstats --uid Bug: 129082217 Change-Id: I726e74f5c63a6ed456cb13ea259b58c7a33bec76 --- core/java/android/net/NetworkTemplate.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cb9463a59d..eba7ff3483 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,6 +34,7 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.sanitizeSsid; +import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -52,6 +53,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -477,6 +480,32 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Return all supported collapsed RAT types that could be returned by + * {@link #getCollapsedRatType(int)}. + */ + @NonNull + public static final int[] getAllCollapsedRatTypes() { + final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); + final HashSet collapsedRatTypes = new HashSet<>(); + for (final int ratType : ratTypes) { + collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); + } + // Ensure that unknown type is returned. + collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); + return toIntArray(collapsedRatTypes); + } + + @NonNull + private static int[] toIntArray(@NonNull Collection list) { + final int[] array = new int[list.size()]; + int i = 0; + for (final Integer item : list) { + array[i++] = item; + } + return array; + } + /** * Check if matches Wi-Fi network template. */ From ebda17c88452be0566a17422a96332aa8ac955aa Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Wed, 25 Mar 2020 00:49:05 +0000 Subject: [PATCH 426/881] Relax IPsec resource count restrictions. IPsec resource counts were selected to be conservative, due to unknowns about device capabilities. Since then, it appears that we no longer need such stringent quotas, and this can be relaxed. Bug: 152368091 Test: FrameworksNetTest passing Change-Id: Id53d14e5698e5fcc410868424176b00350c7ae79 Merged-In: Id53d14e5698e5fcc410868424176b00350c7ae79 (cherry picked from commit 224699fc0b485dd75e6157a88f66a53d64e5a6fd) --- .../core/java/com/android/server/IpSecService.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 9540f43364..599485b11c 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -359,10 +359,14 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting static final class UserRecord { /* Maximum number of each type of resource that a single UID may possess */ - public static final int MAX_NUM_TUNNEL_INTERFACES = 2; - public static final int MAX_NUM_ENCAP_SOCKETS = 2; - public static final int MAX_NUM_TRANSFORMS = 4; - public static final int MAX_NUM_SPIS = 8; + + // Up to 4 active VPNs/IWLAN with potential soft handover. + public static final int MAX_NUM_TUNNEL_INTERFACES = 8; + public static final int MAX_NUM_ENCAP_SOCKETS = 16; + + // SPIs and Transforms are both cheap, and are 1:1 correlated. + public static final int MAX_NUM_TRANSFORMS = 64; + public static final int MAX_NUM_SPIS = 64; /** * Store each of the OwnedResource types in an (thinly wrapped) sparse array for indexing From d497ed73f0d68405cf4b9ec79128c4603524ac55 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 25 Mar 2020 05:50:51 +0000 Subject: [PATCH 427/881] Automatically set IPsec tunnel interface as up This change makes IPsec tunnel interfaces automatically get brought up once they are created. Originally this was considered to be an additional safety check, as they would not be start routing traffic until explicitly brought up. However, in the intervening time, the NetworkManagementController now requires the NETWORK_STACK permission to set an interface as up. Additionally, that call is a hidden API, and thus not usable for use cases such as IWLAN. Bug: 149348618 Test: FrameworksNetTests, CtsNetTestCases passing. Change-Id: I55b63a748463a388e1e2991d2d5d6b3023545e60 Merged-In: I55b63a748463a388e1e2991d2d5d6b3023545e60 (cherry picked from commit 7c5704d177a903034ae1b6ae4800cc3b8457977a) --- .../java/com/android/server/IpSecService.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 599485b11c..905c489e1d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -46,6 +46,7 @@ import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; +import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -114,6 +115,9 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; + /* NetworkManager instance */ + private final INetworkManagementService mNetworkManager; + /** * The next non-repeating global ID for tracking resources between users, this service, and * kernel data structures. Accessing this variable is not thread safe, so it is only read or @@ -992,12 +996,13 @@ public class IpSecService extends IIpSecService.Stub { * * @param context Binder context for this service */ - private IpSecService(Context context) { - this(context, IpSecServiceConfiguration.GETSRVINSTANCE); + private IpSecService(Context context, INetworkManagementService networkManager) { + this(context, networkManager, IpSecServiceConfiguration.GETSRVINSTANCE); } - static IpSecService create(Context context) throws InterruptedException { - final IpSecService service = new IpSecService(context); + static IpSecService create(Context context, INetworkManagementService networkManager) + throws InterruptedException { + final IpSecService service = new IpSecService(context, networkManager); service.connectNativeNetdService(); return service; } @@ -1011,9 +1016,11 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, IpSecServiceConfiguration config) { + public IpSecService(Context context, INetworkManagementService networkManager, + IpSecServiceConfiguration config) { this( context, + networkManager, config, (fd, uid) -> { try { @@ -1027,9 +1034,10 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService( - Context context, IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { + public IpSecService(Context context, INetworkManagementService networkManager, + IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { mContext = context; + mNetworkManager = Objects.requireNonNull(networkManager); mSrvConfig = config; mUidFdTagger = uidFdTagger; } @@ -1308,6 +1316,10 @@ public class IpSecService extends IIpSecService.Stub { final INetd netd = mSrvConfig.getNetdInstance(); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); + Binder.withCleanCallingIdentity(() -> { + mNetworkManager.setInterfaceUp(intfName); + }); + for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. netd.ipSecAddSecurityPolicy( From 158b69aad6902d801320034b6b8cf61f21f4bd6b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 25 Mar 2020 01:20:03 +0900 Subject: [PATCH 428/881] Don't call maybeTrackInterface on the wrong thread. Bug: 150644681 Test: atest TetheringIntegrationTests:EthernetTetheringTest --rerun-until-failure 100 Change-Id: Ia2cb265f8d4de96210f1462339c10ad2947eec65 --- .../server/ethernet/EthernetTracker.java | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 336ddef23a..c8c3bdfb59 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -193,9 +193,11 @@ final class EthernetTracker { } public void setIncludeTestInterfaces(boolean include) { - mIncludeTestInterfaces = include; - updateIfaceMatchRegexp(); - trackAvailableInterfaces(); + mHandler.post(() -> { + mIncludeTestInterfaces = include; + updateIfaceMatchRegexp(); + mHandler.post(() -> trackAvailableInterfaces()); + }); } public void requestTetheredInterface(ITetheredInterfaceCallback callback) { @@ -307,7 +309,7 @@ final class EthernetTracker { ipConfiguration = createDefaultIpConfiguration(); } - Log.d(TAG, "Started tracking interface " + iface); + Log.d(TAG, "Tracking interface in client mode: " + iface); mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); } else { maybeUpdateServerModeInterfaceState(iface, true); @@ -349,6 +351,9 @@ final class EthernetTracker { private void maybeUpdateServerModeInterfaceState(String iface, boolean available) { if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; + Log.d(TAG, (available ? "Tracking" : "No longer tracking") + + " interface in server mode: " + iface); + final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); for (int i = 0; i < pendingCbs; i++) { ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i); @@ -363,14 +368,18 @@ final class EthernetTracker { } private void maybeTrackInterface(String iface) { - if (DBG) Log.i(TAG, "maybeTrackInterface " + iface); - // If we don't already track this interface, and if this interface matches - // our regex, start tracking it. - if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface) - || iface.equals(mDefaultInterface)) { + if (!iface.matches(mIfaceMatch)) { return; } + // If we don't already track this interface, and if this interface matches + // our regex, start tracking it. + if (mFactory.hasInterface(iface) || iface.equals(mDefaultInterface)) { + if (DBG) Log.w(TAG, "Ignoring already-tracked interface " + iface); + return; + } + if (DBG) Log.i(TAG, "maybeTrackInterface: " + iface); + // TODO: avoid making an interface default if it has configured NetworkCapabilities. if (mDefaultInterface == null) { mDefaultInterface = iface; From 85d2df81607d270d8737ae3f02417ac4658bbc52 Mon Sep 17 00:00:00 2001 From: Daulet Zhanguzin Date: Thu, 26 Mar 2020 12:30:39 +0000 Subject: [PATCH 429/881] Replace com.android.internal.util.Preconditions.checkNotNull with java.util.Objects.requireNonNull Bug: 126528330 Bug: 149348618 Test: Treehugger Change-Id: Idb1b6ba41af3b52f3376b1157259af3c30328c4e Merged-In: Idb1b6ba41af3b52f3376b1157259af3c30328c4e --- .../java/com/android/server/IpSecService.java | 18 ++++++++---------- .../android/server/NativeDaemonConnector.java | 3 ++- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 424407a957..905c489e1d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -25,8 +25,6 @@ import static android.system.OsConstants.EINVAL; import static android.system.OsConstants.IPPROTO_UDP; import static android.system.OsConstants.SOCK_DGRAM; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; @@ -575,7 +573,7 @@ public class IpSecService extends IIpSecService.Stub { } void put(int key, RefcountedResource obj) { - checkNotNull(obj, "Null resources cannot be added"); + Objects.requireNonNull(obj, "Null resources cannot be added"); mArray.put(key, obj); } @@ -1114,7 +1112,7 @@ public class IpSecService extends IIpSecService.Stub { if (requestedSpi > 0 && requestedSpi < 256) { throw new IllegalArgumentException("ESP SPI must not be in the range of 0-255."); } - checkNotNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); + Objects.requireNonNull(binder, "Null Binder passed to allocateSecurityParameterIndex"); int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); @@ -1231,7 +1229,7 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException( "Specified port number must be a valid non-reserved UDP port"); } - checkNotNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); + Objects.requireNonNull(binder, "Null Binder passed to openUdpEncapsulationSocket"); int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); @@ -1291,8 +1289,8 @@ public class IpSecService extends IIpSecService.Stub { String localAddr, String remoteAddr, Network underlyingNetwork, IBinder binder, String callingPackage) { enforceTunnelFeatureAndPermissions(callingPackage); - checkNotNull(binder, "Null Binder passed to createTunnelInterface"); - checkNotNull(underlyingNetwork, "No underlying network was specified"); + Objects.requireNonNull(binder, "Null Binder passed to createTunnelInterface"); + Objects.requireNonNull(underlyingNetwork, "No underlying network was specified"); checkInetAddress(localAddr); checkInetAddress(remoteAddr); @@ -1573,7 +1571,7 @@ public class IpSecService extends IIpSecService.Stub { "IPsec Tunnel Mode requires PackageManager.FEATURE_IPSEC_TUNNELS"); } - checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels"); + Objects.requireNonNull(callingPackage, "Null calling package cannot create IpSec tunnels"); // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS @@ -1642,12 +1640,12 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized IpSecTransformResponse createTransform( IpSecConfig c, IBinder binder, String callingPackage) throws RemoteException { - checkNotNull(c); + Objects.requireNonNull(c); if (c.getMode() == IpSecTransform.MODE_TUNNEL) { enforceTunnelFeatureAndPermissions(callingPackage); } checkIpSecConfig(c); - checkNotNull(binder, "Null Binder passed to createTransform"); + Objects.requireNonNull(binder, "Null Binder passed to createTransform"); final int resourceId = mNextResourceId++; UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java index ad02aad6e4..eac767f735 100644 --- a/services/core/java/com/android/server/NativeDaemonConnector.java +++ b/services/core/java/com/android/server/NativeDaemonConnector.java @@ -46,6 +46,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.LinkedList; +import java.util.Objects; /** * Generic connector class for interfacing with a native daemon which uses the @@ -126,7 +127,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ public void setWarnIfHeld(Object warnIfHeld) { Preconditions.checkState(mWarnIfHeld == null); - mWarnIfHeld = Preconditions.checkNotNull(warnIfHeld); + mWarnIfHeld = Objects.requireNonNull(warnIfHeld); } @Override From ea4574dfd56b3e6eaa7173a97e600d35cdea955b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 26 Mar 2020 22:38:21 +0900 Subject: [PATCH 430/881] Fix querying Ethernet availability for unprivileged callers. Both EthernetManager#getAvailableInterfaces() and the no-arg version of EthernetManager#isAvailable() end up calling EthernetServiceImpl#getAvailableInterfaces. This method attempts to filter out restricted interfaces if the caller does not have the CONNECTIVITY_USE_RESTRICTED_NETWORKS permission. Unfortunately EthernetNetworkFactory's notion of a restricted interface is the opposite of what it should be. This means that while privileged callers can see all interfaces, unprivileged callers can only see restricted interfaces which they cannot use. Fix this by correcting NetworkInterfaceState#isRestricted(), so that unprivileged callers can see only unrestricted interfaces. Privileged callers are unaffected. This bug probably went unnoticed because restricted Ethernet interfaces are rare (likely used only on auto devices) and because the callers that care about those restricted interfaces are generally privileged. Bug: 148824036 Test: atest android.net.EthernetTetheringTest#testPhysicalEthernet Change-Id: Idff3b05a193a80c581d80d0e4fe9c2d3fc0d8a25 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 28f46061af..ab2cfc772d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -396,7 +396,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } boolean isRestricted() { - return mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + return !mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } /** From ff69882124fcf2959520afe3df82e2a0507d85cf Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 27 Mar 2020 15:02:17 +0900 Subject: [PATCH 431/881] Address further API council comments. Test: FrameworksNetTests NetworkStackTests Bug: 152238712 Change-Id: I7c27f76c54a76abeae46dcdcddaeb3ca48afa358 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 1c835062ba..3d5385aa48 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -481,7 +481,7 @@ public class EthernetNetworkFactory extends NetworkFactory { }; mNetworkAgent.register(); mNetworkAgent.setLegacyExtraInfo(mHwAddress); - mNetworkAgent.setConnected(); + mNetworkAgent.markConnected(); } void onIpLayerStopped(LinkProperties linkProperties) { From e6f49eda89f4671ee7673d7ea99b633c918f72fc Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 27 Mar 2020 09:06:27 +0000 Subject: [PATCH 432/881] Fix querying Ethernet availability for unprivileged callers. Both EthernetManager#getAvailableInterfaces() and the no-arg version of EthernetManager#isAvailable() end up calling EthernetServiceImpl#getAvailableInterfaces. This method attempts to filter out restricted interfaces if the caller does not have the CONNECTIVITY_USE_RESTRICTED_NETWORKS permission. Unfortunately EthernetNetworkFactory's notion of a restricted interface is the opposite of what it should be. This means that while privileged callers can see all interfaces, unprivileged callers can only see restricted interfaces which they cannot use. Fix this by correcting NetworkInterfaceState#isRestricted(), so that unprivileged callers can see only unrestricted interfaces. Privileged callers are unaffected. This bug probably went unnoticed because restricted Ethernet interfaces are rare (likely used only on auto devices) and because the callers that care about those restricted interfaces are generally privileged. Bug: 148824036 Test: atest android.net.EthernetTetheringTest#testPhysicalEthernet Merged-In: Idff3b05a193a80c581d80d0e4fe9c2d3fc0d8a25 Change-Id: Idff3b05a193a80c581d80d0e4fe9c2d3fc0d8a25 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 1c835062ba..f5ab8b7692 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -391,7 +391,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } boolean isRestricted() { - return mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + return !mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } /** From 60539ad8bca47ced5ea8e784794f41454f03056a Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 11 Feb 2020 14:59:38 +0800 Subject: [PATCH 433/881] [SM06] Collect mobile NetworkStats metrics by collapsed rat type Test: adb shell cmd stats pull-source 10000~10003 adb shell dumpsys netstats --uid Bug: 129082217 Change-Id: I726e74f5c63a6ed456cb13ea259b58c7a33bec76 Merged-In: I726e74f5c63a6ed456cb13ea259b58c7a33bec76 (cherry picked from commit c82dfeb4225e1a8a17eedc969a90f921e0bf845c) --- core/java/android/net/NetworkTemplate.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cb9463a59d..eba7ff3483 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,6 +34,7 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.sanitizeSsid; +import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -52,6 +53,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -477,6 +480,32 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Return all supported collapsed RAT types that could be returned by + * {@link #getCollapsedRatType(int)}. + */ + @NonNull + public static final int[] getAllCollapsedRatTypes() { + final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); + final HashSet collapsedRatTypes = new HashSet<>(); + for (final int ratType : ratTypes) { + collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); + } + // Ensure that unknown type is returned. + collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); + return toIntArray(collapsedRatTypes); + } + + @NonNull + private static int[] toIntArray(@NonNull Collection list) { + final int[] array = new int[list.size()]; + int i = 0; + for (final Integer item : list) { + array[i++] = item; + } + return array; + } + /** * Check if matches Wi-Fi network template. */ From 110e2b8da4efdd9cccecf1089cc2e62ff9097f30 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 31 Mar 2020 14:56:01 +0800 Subject: [PATCH 434/881] [SP26.2] add a method in NetworkStats that removes empty entries In current design, entries with zeros are preserved after addition/subtraction. These entries are not very useful and lead to difficulty of verifying the result of addition/subtraction. However, change the behavior in the original NetworkStats is considered risky in current stage. Thus, this change provide a function that could remove these empty entries in tests. Test: atest FrameworksNetTests Bug: 152827872 Bug: 150644692 Change-Id: I40a76935d55712b8083ee1e17e137a8a4ef5e029 --- core/java/android/net/NetworkStats.java | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9c1fb41ecc..b7fb280efd 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1195,18 +1195,24 @@ public final class NetworkStats implements Parcelable { /** * Remove all rows that match one of specified UIDs. + * This mutates the original structure in place. * @hide */ public void removeUids(int[] uids) { - int nextOutputEntry = 0; - for (int i = 0; i < size; i++) { - if (!ArrayUtils.contains(uids, uid[i])) { - maybeCopyEntry(nextOutputEntry, i); - nextOutputEntry++; - } - } + filter(e -> !ArrayUtils.contains(uids, e.uid)); + } - size = nextOutputEntry; + /** + * Remove all rows that match one of specified UIDs. + * @return the result object. + * @hide + */ + @NonNull + public NetworkStats removeEmptyEntries() { + final NetworkStats ret = this.clone(); + ret.filter(e -> e.rxBytes != 0 || e.rxPackets != 0 || e.txBytes != 0 || e.txPackets != 0 + || e.operations != 0); + return ret; } /** From 41b191332fea349e680a1745d858c4f66f9f88eb Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 22 Jan 2020 16:47:43 +0900 Subject: [PATCH 435/881] Convert the Ethernet factory to the new network agent This is a combination of ag/10147368 and ag/10438581. ag/10147368 implemented this conversion together with using the planned NetworkScore API, while ag/10438581 reverted the parts that had to do with NetworkScore. This is just a squash of these two patches and it brings the factory in line with the code in rvc-dev. Test: FrameworksNetTests NetworkStackTests EthernetTetheringTest Change-Id: Ib214fbbd042f2c0ebd01cf5b0ec33d922629677e Merged-In: Ie7b70750ef0e17141080f4266dea6155c3601569 --- .../ethernet/EthernetNetworkFactory.java | 56 +++++++------------ 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index ab2cfc772d..f5ab8b7692 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,7 +16,6 @@ package com.android.server.ethernet; -import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; import static com.android.internal.util.Preconditions.checkNotNull; @@ -29,10 +28,9 @@ import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkProperties; import android.net.NetworkAgent; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; -import android.net.NetworkInfo; -import android.net.NetworkInfo.DetailedState; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.StringNetworkSpecifier; @@ -52,7 +50,6 @@ import android.util.SparseArray; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; -import java.lang.Math; import java.util.concurrent.ConcurrentHashMap; import java.util.Objects; @@ -221,12 +218,12 @@ public class EthernetNetworkFactory extends NetworkFactory { NetworkInterfaceState network = null; if (!TextUtils.isEmpty(requestedIface)) { NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface); - if (n != null && n.statisified(request.networkCapabilities)) { + if (n != null && n.satisfied(request.networkCapabilities)) { network = n; } } else { for (NetworkInterfaceState n : mTrackingInterfaces.values()) { - if (n.statisified(request.networkCapabilities) && n.mLinkUp) { + if (n.satisfied(request.networkCapabilities) && n.mLinkUp) { network = n; break; } @@ -247,8 +244,8 @@ public class EthernetNetworkFactory extends NetworkFactory { private final NetworkCapabilities mCapabilities; private final Handler mHandler; private final Context mContext; - private final NetworkInfo mNetworkInfo; private final NetworkFactory mNetworkFactory; + private final int mLegacyType; private static String sTcpBufferSizes = null; // Lazy initialized. @@ -375,9 +372,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } mHwAddress = hwAddress; - mNetworkInfo = new NetworkInfo(legacyType, 0, NETWORK_TYPE, ""); - mNetworkInfo.setExtraInfo(mHwAddress); - mNetworkInfo.setIsAvailable(true); + mLegacyType = legacyType; } void setIpConfig(IpConfiguration ipConfig) { @@ -386,12 +381,12 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } this.mIpConfig = ipConfig; - if (mNetworkInfo.getDetailedState() != DetailedState.DISCONNECTED) { + if (mNetworkAgent != null) { restart(); } } - boolean statisified(NetworkCapabilities requestedCapabilities) { + boolean satisfied(NetworkCapabilities requestedCapabilities) { return requestedCapabilities.satisfiedByNetworkCapabilities(mCapabilities); } @@ -446,11 +441,9 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } if (DBG) { - Log.d(TAG, String.format("starting IpClient(%s): mNetworkInfo=%s", name, - mNetworkInfo)); + Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name)); } - mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddress); mIpClientCallback = new IpClientCallbacksImpl(); IpClientUtil.makeIpClient(mContext, name, mIpClientCallback); mIpClientCallback.awaitIpClientStart(); @@ -468,13 +461,15 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } mLinkProperties = linkProperties; - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddress); - mNetworkInfo.setIsAvailable(true); // Create our NetworkAgent. - mNetworkAgent = new NetworkAgent(mHandler.getLooper(), mContext, - NETWORK_TYPE, mNetworkInfo, mCapabilities, mLinkProperties, - getNetworkScore(), mNetworkFactory.getSerialNumber()) { + final NetworkAgentConfig config = new NetworkAgentConfig.Builder() + .setLegacyType(mLegacyType) + .setLegacyTypeName(NETWORK_TYPE) + .build(); + mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(), + NETWORK_TYPE, mCapabilities, mLinkProperties, + getNetworkScore(), config, mNetworkFactory.getProvider()) { public void unwanted() { if (this == mNetworkAgent) { stop(); @@ -484,6 +479,9 @@ public class EthernetNetworkFactory extends NetworkFactory { } // Otherwise, we've already called stop. } }; + mNetworkAgent.register(); + mNetworkAgent.setLegacyExtraInfo(mHwAddress); + mNetworkAgent.setConnected(); } void onIpLayerStopped(LinkProperties linkProperties) { @@ -526,16 +524,11 @@ public class EthernetNetworkFactory extends NetworkFactory { } mIpClientCallback = null; - // ConnectivityService will only forget our NetworkAgent if we send it a NetworkInfo object - // with a state of DISCONNECTED or SUSPENDED. So we can't simply clear our NetworkInfo here: - // that sets the state to IDLE, and ConnectivityService will still think we're connected. - // - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, mHwAddress); if (mNetworkAgent != null) { - updateAgent(); + mNetworkAgent.unregister(); mNetworkAgent = null; } - clear(); + mLinkProperties.clear(); } private void updateAgent() { @@ -543,11 +536,9 @@ public class EthernetNetworkFactory extends NetworkFactory { if (DBG) { Log.i(TAG, "Updating mNetworkAgent with: " + mCapabilities + ", " + - mNetworkInfo + ", " + mLinkProperties); } mNetworkAgent.sendNetworkCapabilities(mCapabilities); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); mNetworkAgent.sendLinkProperties(mLinkProperties); // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now @@ -556,12 +547,6 @@ public class EthernetNetworkFactory extends NetworkFactory { mNetworkAgent.sendNetworkScore(getNetworkScore()); } - private void clear() { - mLinkProperties.clear(); - mNetworkInfo.setDetailedState(DetailedState.IDLE, null, null); - mNetworkInfo.setIsAvailable(false); - } - private static void provisionIpClient(IIpClient ipClient, IpConfiguration config, String tcpBufferSizes) { if (config.getProxySettings() == ProxySettings.STATIC || @@ -612,7 +597,6 @@ public class EthernetNetworkFactory extends NetworkFactory { + "iface: " + name + ", " + "up: " + mLinkUp + ", " + "hwAddress: " + mHwAddress + ", " - + "networkInfo: " + mNetworkInfo + ", " + "networkCapabilities: " + mCapabilities + ", " + "networkAgent: " + mNetworkAgent + ", " + "score: " + getNetworkScore() + ", " From 5507f2183c1004180b2953fb27f5c8c73e6fc876 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 27 Mar 2020 15:02:17 +0900 Subject: [PATCH 436/881] Address further API council comments. Test: FrameworksNetTests NetworkStackTests Bug: 152238712 Copy from ag/10857997 Change-Id: I7c27f76c54a76abeae46dcdcddaeb3ca48afa358 Merged-In: I7c27f76c54a76abeae46dcdcddaeb3ca48afa358 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index f5ab8b7692..793b284676 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -481,7 +481,7 @@ public class EthernetNetworkFactory extends NetworkFactory { }; mNetworkAgent.register(); mNetworkAgent.setLegacyExtraInfo(mHwAddress); - mNetworkAgent.setConnected(); + mNetworkAgent.markConnected(); } void onIpLayerStopped(LinkProperties linkProperties) { From 3c94b3b16243134bb89418ffde12e4b39fe1fc30 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 2 Apr 2020 18:36:24 +0000 Subject: [PATCH 437/881] [SP26.2] add a method in NetworkStats that removes empty entries In current design, entries with zeros are preserved after addition/subtraction. These entries are not very useful and lead to difficulty of verifying the result of addition/subtraction. However, change the behavior in the original NetworkStats is considered risky in current stage. Thus, this change provide a function that could remove these empty entries in tests. Test: atest FrameworksNetTests Bug: 152827872 Bug: 150644692 Change-Id: I40a76935d55712b8083ee1e17e137a8a4ef5e029 Merged-In: I40a76935d55712b8083ee1e17e137a8a4ef5e029 (cherry picked from commit 6c7bef3064dbe949b7b213036b8e70c125ddd343) --- core/java/android/net/NetworkStats.java | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 9c1fb41ecc..b7fb280efd 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1195,18 +1195,24 @@ public final class NetworkStats implements Parcelable { /** * Remove all rows that match one of specified UIDs. + * This mutates the original structure in place. * @hide */ public void removeUids(int[] uids) { - int nextOutputEntry = 0; - for (int i = 0; i < size; i++) { - if (!ArrayUtils.contains(uids, uid[i])) { - maybeCopyEntry(nextOutputEntry, i); - nextOutputEntry++; - } - } + filter(e -> !ArrayUtils.contains(uids, e.uid)); + } - size = nextOutputEntry; + /** + * Remove all rows that match one of specified UIDs. + * @return the result object. + * @hide + */ + @NonNull + public NetworkStats removeEmptyEntries() { + final NetworkStats ret = this.clone(); + ret.filter(e -> e.rxBytes != 0 || e.rxPackets != 0 || e.txBytes != 0 || e.txPackets != 0 + || e.operations != 0); + return ret; } /** From 90ae726ee1ad0cce6e9cbeefcf8897bc4382b976 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 4 Mar 2020 12:48:50 +0800 Subject: [PATCH 438/881] [SM09] Add helper class to monitor RAT type change per sub In current design, Rat type change in NSS is only for default subscription. This is only correct for single sim project. However, it does not correct for multi-sim scenarios such as CBRS or DSDS, given that all data usage will be attributed to the Rat type of default sub. Thus, add a helper class to monitor subscription change event, and register/unregister dynamically for Rat type change for every subscription. Note that unit test of the helper class will be addressed in follow-up patch. Test: m -j Bug: 146415925 Change-Id: I0055f6b55c209a073ce997fc7a144477f9db7069 --- .../net/NetworkStatsSubscriptionsMonitor.java | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java new file mode 100644 index 0000000000..0bdf3f22ee --- /dev/null +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import static android.net.NetworkTemplate.getCollapsedRatType; + +import android.annotation.NonNull; +import android.content.Context; +import android.telephony.Annotation; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; + +/** + * Helper class that watches for events that are triggered per subscription. + */ +// TODO (b/152176562): Write tests to verify subscription changes generate corresponding +// register/unregister calls. +public class NetworkStatsSubscriptionsMonitor extends + SubscriptionManager.OnSubscriptionsChangedListener { + + /** + * Interface that this monitor uses to delegate event handling to NetworkStatsService. + */ + public interface Delegate { + /** + * Notify that the collapsed RAT type has been changed for any subscription. The method + * will also be triggered for any existing sub when start and stop monitoring. + * + * @param subscriberId IMSI of the subscription. + * @param collapsedRatType collapsed RAT type. + * @see android.net.NetworkTemplate#getCollapsedRatType(int). + */ + void onCollapsedRatTypeChanged(@NonNull String subscriberId, + @Annotation.NetworkType int collapsedRatType); + } + private final Delegate mDelegate; + + /** + * Receivers that watches for {@link ServiceState} changes for each subscription, to + * monitor the transitioning between Radio Access Technology(RAT) types for each sub. + */ + @NonNull + private final CopyOnWriteArrayList mRatListeners = + new CopyOnWriteArrayList<>(); + + @NonNull + private final SubscriptionManager mSubscriptionManager; + @NonNull + private final TelephonyManager mTeleManager; + + @NonNull + private final Executor mExecutor; + + NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor, + @NonNull Delegate delegate) { + super(); + mSubscriptionManager = (SubscriptionManager) context.getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE); + mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mExecutor = executor; + mDelegate = delegate; + } + + @Override + public void onSubscriptionsChanged() { + // Collect active subId list, hidden subId such as opportunistic subscriptions are + // also needed to track CBRS. + final List newSubs = getActiveSubIdList(mSubscriptionManager); + + for (final int subId : newSubs) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> it.mSubId == subId); + if (match != null) continue; + + // Create listener for every newly added sub. Also store subscriberId into it to + // prevent binder call to telephony when querying RAT. + final String subscriberId = mTeleManager.getSubscriberId(subId); + if (TextUtils.isEmpty(subscriberId)) { + Log.wtf(NetworkStatsService.TAG, + "Empty subscriberId for newly added sub: " + subId); + } + final RatTypeListener listener = + new RatTypeListener(mExecutor, this, subId, subscriberId); + mRatListeners.add(listener); + + // Register listener to the telephony manager that associated with specific sub. + mTeleManager.createForSubscriptionId(subId) + .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + } + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + // If the new list contains the subId of the listener, keeps it. + final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId); + if (match != null) continue; + + handleRemoveRatTypeListener(listener); + } + } + + @NonNull + private List getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) { + final ArrayList ret = new ArrayList<>(); + final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList(); + for (int id : ids) ret.add(id); + return ret; + } + + /** + * Get a collapsed RatType for the given subscriberId. + * + * @param subscriberId the target subscriberId + * @return collapsed RatType for the given subscriberId + */ + public int getRatTypeForSubscriberId(@NonNull String subscriberId) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> TextUtils.equals(subscriberId, it.mSubscriberId)); + return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + /** + * Start monitoring events that triggered per subscription. + */ + public void start() { + mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this); + } + + /** + * Unregister subscription changes and all listeners for each subscription. + */ + public void stop() { + mSubscriptionManager.removeOnSubscriptionsChangedListener(this); + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + handleRemoveRatTypeListener(listener); + } + } + + private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { + mTeleManager.createForSubscriptionId(listener.mSubId) + .listen(listener, PhoneStateListener.LISTEN_NONE); + mRatListeners.remove(listener); + + // Removal of subscriptions doesn't generate RAT changed event, fire it for every + // RatTypeListener. + mDelegate.onCollapsedRatTypeChanged( + listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN); + } + + static class RatTypeListener extends PhoneStateListener { + // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}. + @NonNull + private final int mSubId; + + // IMSI to identifying the corresponding network from {@link NetworkState}. + // See {@link TelephonyManager#getSubscriberId}. + @NonNull + private final String mSubscriberId; + + private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + @NonNull + private final NetworkStatsSubscriptionsMonitor mMonitor; + + RatTypeListener(@NonNull Executor executor, + @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, + @NonNull String subscriberId) { + super(executor); + mSubId = subId; + mSubscriberId = subscriberId; + mMonitor = monitor; + } + + @Override + public void onServiceStateChanged(@NonNull ServiceState ss) { + final int networkType = ss.getDataNetworkType(); + final int collapsedRatType = getCollapsedRatType(networkType); + if (collapsedRatType == mLastCollapsedRatType) return; + + if (NetworkStatsService.LOGD) { + Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): " + + mLastCollapsedRatType + " -> " + collapsedRatType); + } + mLastCollapsedRatType = collapsedRatType; + mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType); + } + } +} From d217223e3f3a3e09e4c1d1614b4a027213ad061c Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 4 Mar 2020 12:48:50 +0800 Subject: [PATCH 439/881] [SM09] Add helper class to monitor RAT type change per sub In current design, Rat type change in NSS is only for default subscription. This is only correct for single sim project. However, it does not correct for multi-sim scenarios such as CBRS or DSDS, given that all data usage will be attributed to the Rat type of default sub. Thus, add a helper class to monitor subscription change event, and register/unregister dynamically for Rat type change for every subscription. Note that unit test of the helper class will be addressed in follow-up patch. Test: m -j Bug: 146415925 Change-Id: I0055f6b55c209a073ce997fc7a144477f9db7069 Merged-In: I0055f6b55c209a073ce997fc7a144477f9db7069 (cherry picked from commit 306de26c138ec135846f2a74a952464cf00dce54) --- .../net/NetworkStatsSubscriptionsMonitor.java | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java new file mode 100644 index 0000000000..0bdf3f22ee --- /dev/null +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import static android.net.NetworkTemplate.getCollapsedRatType; + +import android.annotation.NonNull; +import android.content.Context; +import android.telephony.Annotation; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; + +/** + * Helper class that watches for events that are triggered per subscription. + */ +// TODO (b/152176562): Write tests to verify subscription changes generate corresponding +// register/unregister calls. +public class NetworkStatsSubscriptionsMonitor extends + SubscriptionManager.OnSubscriptionsChangedListener { + + /** + * Interface that this monitor uses to delegate event handling to NetworkStatsService. + */ + public interface Delegate { + /** + * Notify that the collapsed RAT type has been changed for any subscription. The method + * will also be triggered for any existing sub when start and stop monitoring. + * + * @param subscriberId IMSI of the subscription. + * @param collapsedRatType collapsed RAT type. + * @see android.net.NetworkTemplate#getCollapsedRatType(int). + */ + void onCollapsedRatTypeChanged(@NonNull String subscriberId, + @Annotation.NetworkType int collapsedRatType); + } + private final Delegate mDelegate; + + /** + * Receivers that watches for {@link ServiceState} changes for each subscription, to + * monitor the transitioning between Radio Access Technology(RAT) types for each sub. + */ + @NonNull + private final CopyOnWriteArrayList mRatListeners = + new CopyOnWriteArrayList<>(); + + @NonNull + private final SubscriptionManager mSubscriptionManager; + @NonNull + private final TelephonyManager mTeleManager; + + @NonNull + private final Executor mExecutor; + + NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor, + @NonNull Delegate delegate) { + super(); + mSubscriptionManager = (SubscriptionManager) context.getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE); + mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mExecutor = executor; + mDelegate = delegate; + } + + @Override + public void onSubscriptionsChanged() { + // Collect active subId list, hidden subId such as opportunistic subscriptions are + // also needed to track CBRS. + final List newSubs = getActiveSubIdList(mSubscriptionManager); + + for (final int subId : newSubs) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> it.mSubId == subId); + if (match != null) continue; + + // Create listener for every newly added sub. Also store subscriberId into it to + // prevent binder call to telephony when querying RAT. + final String subscriberId = mTeleManager.getSubscriberId(subId); + if (TextUtils.isEmpty(subscriberId)) { + Log.wtf(NetworkStatsService.TAG, + "Empty subscriberId for newly added sub: " + subId); + } + final RatTypeListener listener = + new RatTypeListener(mExecutor, this, subId, subscriberId); + mRatListeners.add(listener); + + // Register listener to the telephony manager that associated with specific sub. + mTeleManager.createForSubscriptionId(subId) + .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + } + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + // If the new list contains the subId of the listener, keeps it. + final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId); + if (match != null) continue; + + handleRemoveRatTypeListener(listener); + } + } + + @NonNull + private List getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) { + final ArrayList ret = new ArrayList<>(); + final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList(); + for (int id : ids) ret.add(id); + return ret; + } + + /** + * Get a collapsed RatType for the given subscriberId. + * + * @param subscriberId the target subscriberId + * @return collapsed RatType for the given subscriberId + */ + public int getRatTypeForSubscriberId(@NonNull String subscriberId) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> TextUtils.equals(subscriberId, it.mSubscriberId)); + return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + /** + * Start monitoring events that triggered per subscription. + */ + public void start() { + mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this); + } + + /** + * Unregister subscription changes and all listeners for each subscription. + */ + public void stop() { + mSubscriptionManager.removeOnSubscriptionsChangedListener(this); + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + handleRemoveRatTypeListener(listener); + } + } + + private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { + mTeleManager.createForSubscriptionId(listener.mSubId) + .listen(listener, PhoneStateListener.LISTEN_NONE); + mRatListeners.remove(listener); + + // Removal of subscriptions doesn't generate RAT changed event, fire it for every + // RatTypeListener. + mDelegate.onCollapsedRatTypeChanged( + listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN); + } + + static class RatTypeListener extends PhoneStateListener { + // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}. + @NonNull + private final int mSubId; + + // IMSI to identifying the corresponding network from {@link NetworkState}. + // See {@link TelephonyManager#getSubscriberId}. + @NonNull + private final String mSubscriberId; + + private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + @NonNull + private final NetworkStatsSubscriptionsMonitor mMonitor; + + RatTypeListener(@NonNull Executor executor, + @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, + @NonNull String subscriberId) { + super(executor); + mSubId = subId; + mSubscriberId = subscriberId; + mMonitor = monitor; + } + + @Override + public void onServiceStateChanged(@NonNull ServiceState ss) { + final int networkType = ss.getDataNetworkType(); + final int collapsedRatType = getCollapsedRatType(networkType); + if (collapsedRatType == mLastCollapsedRatType) return; + + if (NetworkStatsService.LOGD) { + Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): " + + mLastCollapsedRatType + " -> " + collapsedRatType); + } + mLastCollapsedRatType = collapsedRatType; + mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType); + } + } +} From 20dc3e71c2db351c9f5b1651d00d2955c30c896d Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 4 Mar 2020 12:48:50 +0800 Subject: [PATCH 440/881] [SM09] Add helper class to monitor RAT type change per sub In current design, Rat type change in NSS is only for default subscription. This is only correct for single sim project. However, it does not correct for multi-sim scenarios such as CBRS or DSDS, given that all data usage will be attributed to the Rat type of default sub. Thus, add a helper class to monitor subscription change event, and register/unregister dynamically for Rat type change for every subscription. Note that unit test of the helper class will be addressed in follow-up patch. Test: m -j Bug: 146415925 Change-Id: I0055f6b55c209a073ce997fc7a144477f9db7069 Merged-In: I0055f6b55c209a073ce997fc7a144477f9db7069 (cherry picked from ag/10977156 and fixed conflict) --- .../net/NetworkStatsSubscriptionsMonitor.java | 211 ++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java new file mode 100644 index 0000000000..16a63d5436 --- /dev/null +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import static android.net.NetworkTemplate.getCollapsedRatType; + +import android.annotation.NonNull; +import android.content.Context; +import android.telephony.Annotation; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; + +/** + * Helper class that watches for events that are triggered per subscription. + */ +// TODO (b/152176562): Write tests to verify subscription changes generate corresponding +// register/unregister calls. +public class NetworkStatsSubscriptionsMonitor extends + SubscriptionManager.OnSubscriptionsChangedListener { + + /** + * Interface that this monitor uses to delegate event handling to NetworkStatsService. + */ + public interface Delegate { + /** + * Notify that the collapsed RAT type has been changed for any subscription. The method + * will also be triggered for any existing sub when start and stop monitoring. + * + * @param subscriberId IMSI of the subscription. + * @param collapsedRatType collapsed RAT type. + * @see android.net.NetworkTemplate#getCollapsedRatType(int). + */ + void onCollapsedRatTypeChanged(@NonNull String subscriberId, + @Annotation.NetworkType int collapsedRatType); + } + private final Delegate mDelegate; + + /** + * Receivers that watches for {@link ServiceState} changes for each subscription, to + * monitor the transitioning between Radio Access Technology(RAT) types for each sub. + */ + @NonNull + private final CopyOnWriteArrayList mRatListeners = + new CopyOnWriteArrayList<>(); + + @NonNull + private final SubscriptionManager mSubscriptionManager; + @NonNull + private final TelephonyManager mTeleManager; + + @NonNull + private final Executor mExecutor; + + NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor, + @NonNull Delegate delegate) { + super(); + mSubscriptionManager = (SubscriptionManager) context.getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE); + mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mExecutor = executor; + mDelegate = delegate; + } + + @Override + public void onSubscriptionsChanged() { + // Collect active subId list, hidden subId such as opportunistic subscriptions are + // also needed to track CBRS. + final List newSubs = getActiveSubIdList(mSubscriptionManager); + + for (final int subId : newSubs) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> it.mSubId == subId); + if (match != null) continue; + + // Create listener for every newly added sub. Also store subscriberId into it to + // prevent binder call to telephony when querying RAT. + final String subscriberId = mTeleManager.getSubscriberId(subId); + if (TextUtils.isEmpty(subscriberId)) { + Log.wtf(NetworkStatsService.TAG, + "Empty subscriberId for newly added sub: " + subId); + } + final RatTypeListener listener = + new RatTypeListener(mExecutor, this, subId, subscriberId); + mRatListeners.add(listener); + + // Register listener to the telephony manager that associated with specific sub. + mTeleManager.createForSubscriptionId(subId) + .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + } + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + // If the new list contains the subId of the listener, keeps it. + final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId); + if (match != null) continue; + + handleRemoveRatTypeListener(listener); + } + } + + @NonNull + private List getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) { + final ArrayList ret = new ArrayList<>(); + final int[] ids = subscriptionManager.getActiveAndHiddenSubscriptionIdList(); + for (int id : ids) ret.add(id); + return ret; + } + + /** + * Get a collapsed RatType for the given subscriberId. + * + * @param subscriberId the target subscriberId + * @return collapsed RatType for the given subscriberId + */ + public int getRatTypeForSubscriberId(@NonNull String subscriberId) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> TextUtils.equals(subscriberId, it.mSubscriberId)); + return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + /** + * Start monitoring events that triggered per subscription. + */ + public void start() { + mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this); + } + + /** + * Unregister subscription changes and all listeners for each subscription. + */ + public void stop() { + mSubscriptionManager.removeOnSubscriptionsChangedListener(this); + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + handleRemoveRatTypeListener(listener); + } + } + + private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { + mTeleManager.createForSubscriptionId(listener.mSubId) + .listen(listener, PhoneStateListener.LISTEN_NONE); + mRatListeners.remove(listener); + + // Removal of subscriptions doesn't generate RAT changed event, fire it for every + // RatTypeListener. + mDelegate.onCollapsedRatTypeChanged( + listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN); + } + + static class RatTypeListener extends PhoneStateListener { + // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}. + @NonNull + private final int mSubId; + + // IMSI to identifying the corresponding network from {@link NetworkState}. + // See {@link TelephonyManager#getSubscriberId}. + @NonNull + private final String mSubscriberId; + + private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + @NonNull + private final NetworkStatsSubscriptionsMonitor mMonitor; + + RatTypeListener(@NonNull Executor executor, + @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, + @NonNull String subscriberId) { + super(executor); + mSubId = subId; + mSubscriberId = subscriberId; + mMonitor = monitor; + } + + @Override + public void onServiceStateChanged(@NonNull ServiceState ss) { + final int networkType = ss.getDataNetworkType(); + final int collapsedRatType = getCollapsedRatType(networkType); + if (collapsedRatType == mLastCollapsedRatType) return; + + if (NetworkStatsService.LOGD) { + Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): " + + mLastCollapsedRatType + " -> " + collapsedRatType); + } + mLastCollapsedRatType = collapsedRatType; + mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType); + } + } +} From 61dcf1f41f7df37fecb86d0474ef8f9ae6b69afc Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 4 Mar 2020 12:58:00 +0800 Subject: [PATCH 441/881] [SM10] Adopt helper class to monitor RAT type change per sub Test: atest NetworkStatsServiceTest Bug: 146415925 Change-Id: I45c3aa9046b316c8cd0943543d620a22e4afefd1 --- .../server/net/NetworkStatsService.java | 86 ++++++++----------- 1 file changed, 37 insertions(+), 49 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index d8264b3625..f7d0d4ee16 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -46,7 +46,6 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -67,9 +66,6 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; -import static android.telephony.PhoneStateListener.LISTEN_NONE; -import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; -import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -133,9 +129,7 @@ import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; -import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -206,7 +200,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; private final Clock mClock; - private final TelephonyManager mTeleManager; private final NetworkStatsSettings mSettings; private final NetworkStatsObservers mStatsObservers; @@ -352,6 +345,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final Dependencies mDeps; + @NonNull + private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -401,8 +397,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), + final NetworkStatsService service = new NetworkStatsService(context, networkManager, + alarmManager, wakeLock, getDefaultClock(), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -416,16 +412,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, - TelephonyManager teleManager, NetworkStatsSettings settings, - NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, - File baseDir, @NonNull Dependencies deps) { + NetworkStatsSettings settings, NetworkStatsFactory factory, + NetworkStatsObservers statsObservers, File systemDir, File baseDir, + @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); mNetworkManager = Objects.requireNonNull(networkManager, - "missing INetworkManagementService"); + "missing INetworkManagementService"); mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager"); mClock = Objects.requireNonNull(clock, "missing Clock"); mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings"); - mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager"); mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock"); mStatsFactory = Objects.requireNonNull(factory, "missing factory"); mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers"); @@ -437,7 +432,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); - mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); + mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, + new HandlerExecutor(mHandler), this); } /** @@ -453,6 +449,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public HandlerThread makeHandlerThread() { return new HandlerThread(TAG); } + + /** + * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change + * event in NetworkStatsService. + */ + @NonNull + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, + @NonNull Executor executor, @NonNull NetworkStatsService service) { + // TODO: Update RatType passively in NSS, instead of querying into the monitor + // when forceUpdateIface. + return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> + service.handleOnCollapsedRatTypeChanged()); + } } private void registerLocalService() { @@ -517,11 +526,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: 1. listen to changes from all subscriptions. - // 2. listen to settings changed to support dynamically enable/disable. + // TODO: listen to settings changed to support dynamically enable/disable. // watch for networkType changes if (!mSettings.getCombineSubtypeEnabled()) { - mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + mNetworkStatsSubscriptionsMonitor.start(); } registerGlobalAlert(); @@ -544,7 +552,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - mTeleManager.listen(mPhoneListener, LISTEN_NONE); + if (!mSettings.getCombineSubtypeEnabled()) { + mNetworkStatsSubscriptionsMonitor.stop(); + } final long currentTime = mClock.millis(); @@ -1197,35 +1207,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { }; /** - * Receiver that watches for {@link TelephonyManager} changes, such as - * transitioning between Radio Access Technology(RAT) types. + * Handle collapsed RAT type changed event. */ - @NonNull - private final NetworkTypeListener mPhoneListener; - - class NetworkTypeListener extends PhoneStateListener { - private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; - - NetworkTypeListener(@NonNull Executor executor) { - super(executor); - } - - @Override - public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); - final int collapsedRatType = getCollapsedRatType(networkType); - if (collapsedRatType == mLastCollapsedRatType) return; - - if (LOGD) { - Log.d(TAG, "subtype changed for mobile: " - + mLastCollapsedRatType + " -> " + collapsedRatType); - } - // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); - mLastCollapsedRatType = collapsedRatType; - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); - } + @VisibleForTesting + public void handleOnCollapsedRatTypeChanged() { + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } private void updateIfaces( @@ -1352,8 +1341,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return 0; } - // TODO: return different subType for different subscriptions. - return mPhoneListener.mLastCollapsedRatType; + return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.subscriberId); } private static NetworkIdentitySet findOrCreateNetworkIdentitySet( From 8bc2a49fd5901aa384e5f0962dabee0d13e89ee0 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 10 Apr 2020 13:54:43 -0600 Subject: [PATCH 442/881] Narrow access to getDataLayerSnapshotForUid(). This method is used in TrafficStats to obtain the snapshot for the calling UID, so narrow it to only return data for that specific case. We might be tempted to throw an exception or adjust the method signature, but apps are using the raw AIDL in the greylist, so we return them an empty NetworkStats if they ask about other UIDs. Bug: 119672472 Test: manual Change-Id: I3064630039f1d8473d6425dd663f17813a4ae3a1 --- .../core/java/com/android/server/net/NetworkStatsService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index d8264b3625..c3a1a883e5 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -16,7 +16,6 @@ package com.android.server.net; -import static android.Manifest.permission.ACCESS_NETWORK_STATE; import static android.Manifest.permission.NETWORK_STATS_PROVIDER; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.UPDATE_DEVICE_STATS; @@ -845,7 +844,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException { if (Binder.getCallingUid() != uid) { - mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); + Log.w(TAG, "Snapshots only available for calling UID"); + return new NetworkStats(SystemClock.elapsedRealtime(), 0); } // TODO: switch to data layer stats once kernel exports From 97d9567cb6d055936b247db36763302077b1802c Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 4 Mar 2020 12:58:00 +0800 Subject: [PATCH 443/881] [SM10] Adopt helper class to monitor RAT type change per sub Test: atest NetworkStatsServiceTest Bug: 146415925 Change-Id: I45c3aa9046b316c8cd0943543d620a22e4afefd1 Merged-In: I45c3aa9046b316c8cd0943543d620a22e4afefd1 (cherry picked from commit 219faff07bdc58c14fe58fc525e86383db1f8167) --- .../server/net/NetworkStatsService.java | 86 ++++++++----------- 1 file changed, 37 insertions(+), 49 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index d8264b3625..f7d0d4ee16 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -46,7 +46,6 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -67,9 +66,6 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; -import static android.telephony.PhoneStateListener.LISTEN_NONE; -import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; -import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -133,9 +129,7 @@ import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; -import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -206,7 +200,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; private final Clock mClock; - private final TelephonyManager mTeleManager; private final NetworkStatsSettings mSettings; private final NetworkStatsObservers mStatsObservers; @@ -352,6 +345,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final Dependencies mDeps; + @NonNull + private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -401,8 +397,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), + final NetworkStatsService service = new NetworkStatsService(context, networkManager, + alarmManager, wakeLock, getDefaultClock(), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -416,16 +412,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, - TelephonyManager teleManager, NetworkStatsSettings settings, - NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, - File baseDir, @NonNull Dependencies deps) { + NetworkStatsSettings settings, NetworkStatsFactory factory, + NetworkStatsObservers statsObservers, File systemDir, File baseDir, + @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); mNetworkManager = Objects.requireNonNull(networkManager, - "missing INetworkManagementService"); + "missing INetworkManagementService"); mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager"); mClock = Objects.requireNonNull(clock, "missing Clock"); mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings"); - mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager"); mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock"); mStatsFactory = Objects.requireNonNull(factory, "missing factory"); mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers"); @@ -437,7 +432,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); - mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); + mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, + new HandlerExecutor(mHandler), this); } /** @@ -453,6 +449,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public HandlerThread makeHandlerThread() { return new HandlerThread(TAG); } + + /** + * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change + * event in NetworkStatsService. + */ + @NonNull + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, + @NonNull Executor executor, @NonNull NetworkStatsService service) { + // TODO: Update RatType passively in NSS, instead of querying into the monitor + // when forceUpdateIface. + return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> + service.handleOnCollapsedRatTypeChanged()); + } } private void registerLocalService() { @@ -517,11 +526,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: 1. listen to changes from all subscriptions. - // 2. listen to settings changed to support dynamically enable/disable. + // TODO: listen to settings changed to support dynamically enable/disable. // watch for networkType changes if (!mSettings.getCombineSubtypeEnabled()) { - mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + mNetworkStatsSubscriptionsMonitor.start(); } registerGlobalAlert(); @@ -544,7 +552,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - mTeleManager.listen(mPhoneListener, LISTEN_NONE); + if (!mSettings.getCombineSubtypeEnabled()) { + mNetworkStatsSubscriptionsMonitor.stop(); + } final long currentTime = mClock.millis(); @@ -1197,35 +1207,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { }; /** - * Receiver that watches for {@link TelephonyManager} changes, such as - * transitioning between Radio Access Technology(RAT) types. + * Handle collapsed RAT type changed event. */ - @NonNull - private final NetworkTypeListener mPhoneListener; - - class NetworkTypeListener extends PhoneStateListener { - private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; - - NetworkTypeListener(@NonNull Executor executor) { - super(executor); - } - - @Override - public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); - final int collapsedRatType = getCollapsedRatType(networkType); - if (collapsedRatType == mLastCollapsedRatType) return; - - if (LOGD) { - Log.d(TAG, "subtype changed for mobile: " - + mLastCollapsedRatType + " -> " + collapsedRatType); - } - // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); - mLastCollapsedRatType = collapsedRatType; - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); - } + @VisibleForTesting + public void handleOnCollapsedRatTypeChanged() { + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } private void updateIfaces( @@ -1352,8 +1341,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return 0; } - // TODO: return different subType for different subscriptions. - return mPhoneListener.mLastCollapsedRatType; + return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.subscriberId); } private static NetworkIdentitySet findOrCreateNetworkIdentitySet( From a7339886efecd7f0abb96cb31d3ea5baad691d3e Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 26 Mar 2020 09:58:55 +0000 Subject: [PATCH 444/881] Don't call maybeTrackInterface on the wrong thread. Bug: 150644681 Test: atest TetheringIntegrationTests:EthernetTetheringTest --rerun-until-failure 100 Merged-In: Ia2cb265f8d4de96210f1462339c10ad2947eec65 Change-Id: Ia2cb265f8d4de96210f1462339c10ad2947eec65 --- .../server/ethernet/EthernetTracker.java | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 336ddef23a..c8c3bdfb59 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -193,9 +193,11 @@ final class EthernetTracker { } public void setIncludeTestInterfaces(boolean include) { - mIncludeTestInterfaces = include; - updateIfaceMatchRegexp(); - trackAvailableInterfaces(); + mHandler.post(() -> { + mIncludeTestInterfaces = include; + updateIfaceMatchRegexp(); + mHandler.post(() -> trackAvailableInterfaces()); + }); } public void requestTetheredInterface(ITetheredInterfaceCallback callback) { @@ -307,7 +309,7 @@ final class EthernetTracker { ipConfiguration = createDefaultIpConfiguration(); } - Log.d(TAG, "Started tracking interface " + iface); + Log.d(TAG, "Tracking interface in client mode: " + iface); mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); } else { maybeUpdateServerModeInterfaceState(iface, true); @@ -349,6 +351,9 @@ final class EthernetTracker { private void maybeUpdateServerModeInterfaceState(String iface, boolean available) { if (available == mTetheredInterfaceWasAvailable || !iface.equals(mDefaultInterface)) return; + Log.d(TAG, (available ? "Tracking" : "No longer tracking") + + " interface in server mode: " + iface); + final int pendingCbs = mTetheredInterfaceRequests.beginBroadcast(); for (int i = 0; i < pendingCbs; i++) { ITetheredInterfaceCallback item = mTetheredInterfaceRequests.getBroadcastItem(i); @@ -363,14 +368,18 @@ final class EthernetTracker { } private void maybeTrackInterface(String iface) { - if (DBG) Log.i(TAG, "maybeTrackInterface " + iface); - // If we don't already track this interface, and if this interface matches - // our regex, start tracking it. - if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface) - || iface.equals(mDefaultInterface)) { + if (!iface.matches(mIfaceMatch)) { return; } + // If we don't already track this interface, and if this interface matches + // our regex, start tracking it. + if (mFactory.hasInterface(iface) || iface.equals(mDefaultInterface)) { + if (DBG) Log.w(TAG, "Ignoring already-tracked interface " + iface); + return; + } + if (DBG) Log.i(TAG, "maybeTrackInterface: " + iface); + // TODO: avoid making an interface default if it has configured NetworkCapabilities. if (mDefaultInterface == null) { mDefaultInterface = iface; From e3cff5ba69d7b3c77901cb9de0b1925f129dbd34 Mon Sep 17 00:00:00 2001 From: Chenbo Feng Date: Mon, 17 Jun 2019 16:22:28 -0700 Subject: [PATCH 445/881] Enforce permission check in getUidStats function The NetworkStatsService.getUidStats() currently doesn't have any permission check to make sure unpriviledged apps cannot read the stats of a different uid. It will protentially have security problem since apps with ACCESS_NETWORK_STATS permission can directly calling into NetworkStatsService and bypass the check in TrafficStats. Move the uid check from TrafficStats to NetworkStatsService to fix the problem. Bug: 129151407 Test: atest AppSecurityTests#testAppFailAccessPrivateData_full Test: atest AppSecurityTests#testAppFailAccessPrivateData_instant Test: atest android.app.usage.cts.NetworkUsageStatsTest Test: atest NetworkStatsBinderTest Change-Id: Iae85676cfe5f114da69ec278afc2c904bc907234 --- core/java/android/net/TrafficStats.java | 60 +++++-------------- .../server/net/NetworkStatsService.java | 5 ++ 2 files changed, 21 insertions(+), 44 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 8108cf08d5..e7bba69dbb 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -775,17 +775,10 @@ public class TrafficStats { * @see android.content.pm.ApplicationInfo#uid */ public static long getUidTxBytes(int uid) { - // This isn't actually enforcing any security; it just returns the - // unsupported value. The real filtering is done at the kernel level. - final int callingUid = android.os.Process.myUid(); - if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - try { - return getStatsService().getUidStats(uid, TYPE_TX_BYTES); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } else { - return UNSUPPORTED; + try { + return getStatsService().getUidStats(uid, TYPE_TX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -808,17 +801,10 @@ public class TrafficStats { * @see android.content.pm.ApplicationInfo#uid */ public static long getUidRxBytes(int uid) { - // This isn't actually enforcing any security; it just returns the - // unsupported value. The real filtering is done at the kernel level. - final int callingUid = android.os.Process.myUid(); - if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - try { - return getStatsService().getUidStats(uid, TYPE_RX_BYTES); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } else { - return UNSUPPORTED; + try { + return getStatsService().getUidStats(uid, TYPE_RX_BYTES); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -841,17 +827,10 @@ public class TrafficStats { * @see android.content.pm.ApplicationInfo#uid */ public static long getUidTxPackets(int uid) { - // This isn't actually enforcing any security; it just returns the - // unsupported value. The real filtering is done at the kernel level. - final int callingUid = android.os.Process.myUid(); - if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - try { - return getStatsService().getUidStats(uid, TYPE_TX_PACKETS); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } else { - return UNSUPPORTED; + try { + return getStatsService().getUidStats(uid, TYPE_TX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -874,17 +853,10 @@ public class TrafficStats { * @see android.content.pm.ApplicationInfo#uid */ public static long getUidRxPackets(int uid) { - // This isn't actually enforcing any security; it just returns the - // unsupported value. The real filtering is done at the kernel level. - final int callingUid = android.os.Process.myUid(); - if (callingUid == android.os.Process.SYSTEM_UID || callingUid == uid) { - try { - return getStatsService().getUidStats(uid, TYPE_RX_PACKETS); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } else { - return UNSUPPORTED; + try { + return getStatsService().getUidStats(uid, TYPE_RX_PACKETS); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index d8264b3625..003e7fc837 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -49,6 +49,7 @@ import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; +import static android.net.TrafficStats.UNSUPPORTED; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED; @@ -1021,6 +1022,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getUidStats(int uid, int type) { + final int callingUid = Binder.getCallingUid(); + if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) { + return UNSUPPORTED; + } return nativeGetUidStat(uid, type, checkBpfStatsEnable()); } From 350b80ef71a84ad4f64171fa95af1b7eac34118b Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 28 Apr 2020 22:15:56 +0800 Subject: [PATCH 446/881] Filter debug entries for each vpn NetworkStats calculation needs to filter out debug entries to prevent over counting. While NetworkStatsFactory migrates data usage over a VPN to the TUN network, NetworkStatsFactory does not filter out debug entries per vpn which will cause debug entries left and cause exception. Bug: 152678151 Test: atest com.android.server.net.NetworkStatsFactoryTest and verify no exception Change-Id: I3525edc385b07858b48c7add2d331c4b5a2e84ad --- .../java/com/android/server/net/NetworkStatsFactory.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 75ffe35674..3dac106418 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -385,11 +385,10 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); } - // Filter out debug entries as that may lead to over counting. - delta.filterDebugEntries(); - // Update mTunAnd464xlatAdjustedStats with migrated delta. mTunAnd464xlatAdjustedStats.combineAllValues(delta); mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); From 2e1eda79f3a0a53a693985b9d3601e12f23a568c Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 28 Apr 2020 22:15:56 +0800 Subject: [PATCH 447/881] Filter debug entries for each vpn NetworkStats calculation needs to filter out debug entries to prevent over counting. While NetworkStatsFactory migrates data usage over a VPN to the TUN network, NetworkStatsFactory does not filter out debug entries per vpn which will cause debug entries left and cause exception. Bug: 152678151 Test: atest com.android.server.net.NetworkStatsFactoryTest and verify no exception Change-Id: I3525edc385b07858b48c7add2d331c4b5a2e84ad Merged-In: I3525edc385b07858b48c7add2d331c4b5a2e84ad --- .../java/com/android/server/net/NetworkStatsFactory.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 75ffe35674..3dac106418 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -385,11 +385,10 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + // Filter out debug entries as that may lead to over counting. + delta.filterDebugEntries(); } - // Filter out debug entries as that may lead to over counting. - delta.filterDebugEntries(); - // Update mTunAnd464xlatAdjustedStats with migrated delta. mTunAnd464xlatAdjustedStats.combineAllValues(delta); mTunAnd464xlatAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime()); From e77cc5a7b1ef167ec41b3d9cacefacdaef12bd71 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 29 Apr 2020 18:25:32 +0800 Subject: [PATCH 448/881] Use CopyOnWriteArrayList to store list of NetworkStatsProviderCb In NetworkStatsService, mStatsLock will be held when iterating through the provider list. This is to protect the list from concurrent broadcast that triggered by NetworkPolicyManagerService. This is not good since the binder call is oneway, it does not make sense to block every access to the providers. This change also remove unuse variable and reduce verbose log. Test: atest FrameworksNetTests TetheringTests Bug: 150418178 Change-Id: If74e9f2ea597a0d5ae4668c3358bc687f342bbb5 --- .../server/net/NetworkStatsService.java | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 2680858743..76f7df5579 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -123,7 +123,6 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; @@ -166,6 +165,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -230,12 +230,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String PREFIX_UID = "uid"; private static final String PREFIX_UID_TAG = "uid_tag"; - /** - * Virtual network interface for video telephony. This is for VT data usage counting purpose. - */ - // TODO: Remove this after no one is using it. - public static final String VT_INTERFACE = NetworkStats.IFACE_VT; - /** * Settings that can be changed externally. */ @@ -308,8 +302,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { new DropBoxNonMonotonicObserver(); private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100; - private final RemoteCallbackList mStatsProviderCbList = - new RemoteCallbackList<>(); + private final CopyOnWriteArrayList mStatsProviderCbList = + new CopyOnWriteArrayList<>(); /** Semaphore used to wait for stats provider to respond to request stats update. */ private final Semaphore mStatsProviderSem = new Semaphore(0, true); @@ -1463,10 +1457,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; // Request asynchronous stats update from all providers for next poll. And wait a bit of - // time to allow providers report-in given that normally binder call should be fast. + // time to allow providers report-in given that normally binder call should be fast. Note + // that size of list might be changed because addition/removing at the same time. For + // addition, the stats of the missed provider can only be collected in next poll; + // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS + // once that happened. // TODO: request with a valid token. Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); - final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount(); + final int registeredCallbackCount = mStatsProviderCbList.size(); mStatsProviderSem.drainPermits(); invokeForAllStatsProviderCallbacks( (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); @@ -1643,7 +1641,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { - Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); + if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); } } @@ -1934,7 +1932,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl( tag, provider, mStatsProviderSem, mAlertObserver, mStatsProviderCbList); - mStatsProviderCbList.register(callback); + mStatsProviderCbList.add(callback); Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid=" + getCallingUid() + "/" + getCallingPid()); return callback; @@ -1958,20 +1956,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void invokeForAllStatsProviderCallbacks( @NonNull ThrowingConsumer task) { - synchronized (mStatsLock) { - final int length = mStatsProviderCbList.beginBroadcast(); + for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) { try { - for (int i = 0; i < length; i++) { - final NetworkStatsProviderCallbackImpl cb = - mStatsProviderCbList.getBroadcastItem(i); - try { - task.accept(cb); - } catch (RemoteException e) { - Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); - } - } - } finally { - mStatsProviderCbList.finishBroadcast(); + task.accept(cb); + } catch (RemoteException e) { + Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); } } } @@ -1983,7 +1972,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull final INetworkStatsProvider mProvider; @NonNull private final Semaphore mSemaphore; @NonNull final INetworkManagementEventObserver mAlertObserver; - @NonNull final RemoteCallbackList mStatsProviderCbList; + @NonNull final CopyOnWriteArrayList mStatsProviderCbList; @NonNull private final Object mProviderStatsLock = new Object(); @@ -1997,7 +1986,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull String tag, @NonNull INetworkStatsProvider provider, @NonNull Semaphore semaphore, @NonNull INetworkManagementEventObserver alertObserver, - @NonNull RemoteCallbackList cbList) + @NonNull CopyOnWriteArrayList cbList) throws RemoteException { mTag = tag; mProvider = provider; @@ -2054,13 +2043,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void binderDied() { Log.d(TAG, mTag + ": binderDied"); - mStatsProviderCbList.unregister(this); + mStatsProviderCbList.remove(this); } @Override public void unregister() { Log.d(TAG, mTag + ": unregister"); - mStatsProviderCbList.unregister(this); + mStatsProviderCbList.remove(this); } } From d9d1a9f98a40e3b473ab0749fe1510470850a64e Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 4 Mar 2020 12:58:00 +0800 Subject: [PATCH 449/881] [SM10] Adopt helper class to monitor RAT type change per sub Test: atest NetworkStatsServiceTest Bug: 146415925 Change-Id: I45c3aa9046b316c8cd0943543d620a22e4afefd1 Merged-In: I45c3aa9046b316c8cd0943543d620a22e4afefd1 (cherry picked from commit 61dcf1f41f7df37fecb86d0474ef8f9ae6b69afc) --- .../server/net/NetworkStatsService.java | 86 ++++++++----------- 1 file changed, 37 insertions(+), 49 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 2680858743..34e8f62324 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -46,7 +46,6 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.NetworkTemplate.getCollapsedRatType; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.os.Trace.TRACE_TAG_NETWORK; @@ -67,9 +66,6 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; -import static android.telephony.PhoneStateListener.LISTEN_NONE; -import static android.telephony.PhoneStateListener.LISTEN_SERVICE_STATE; -import static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -133,9 +129,7 @@ import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; -import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -206,7 +200,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; private final Clock mClock; - private final TelephonyManager mTeleManager; private final NetworkStatsSettings mSettings; private final NetworkStatsObservers mStatsObservers; @@ -352,6 +345,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final Dependencies mDeps; + @NonNull + private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -401,8 +397,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, - wakeLock, getDefaultClock(), context.getSystemService(TelephonyManager.class), + final NetworkStatsService service = new NetworkStatsService(context, networkManager, + alarmManager, wakeLock, getDefaultClock(), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -416,16 +412,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, - TelephonyManager teleManager, NetworkStatsSettings settings, - NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, - File baseDir, @NonNull Dependencies deps) { + NetworkStatsSettings settings, NetworkStatsFactory factory, + NetworkStatsObservers statsObservers, File systemDir, File baseDir, + @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); mNetworkManager = Objects.requireNonNull(networkManager, - "missing INetworkManagementService"); + "missing INetworkManagementService"); mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager"); mClock = Objects.requireNonNull(clock, "missing Clock"); mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings"); - mTeleManager = Objects.requireNonNull(teleManager, "missing TelephonyManager"); mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock"); mStatsFactory = Objects.requireNonNull(factory, "missing factory"); mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers"); @@ -437,7 +432,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final HandlerThread handlerThread = mDeps.makeHandlerThread(); handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); - mPhoneListener = new NetworkTypeListener(new HandlerExecutor(mHandler)); + mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, + new HandlerExecutor(mHandler), this); } /** @@ -453,6 +449,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public HandlerThread makeHandlerThread() { return new HandlerThread(TAG); } + + /** + * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change + * event in NetworkStatsService. + */ + @NonNull + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, + @NonNull Executor executor, @NonNull NetworkStatsService service) { + // TODO: Update RatType passively in NSS, instead of querying into the monitor + // when forceUpdateIface. + return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> + service.handleOnCollapsedRatTypeChanged()); + } } private void registerLocalService() { @@ -517,11 +526,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: 1. listen to changes from all subscriptions. - // 2. listen to settings changed to support dynamically enable/disable. + // TODO: listen to settings changed to support dynamically enable/disable. // watch for networkType changes if (!mSettings.getCombineSubtypeEnabled()) { - mTeleManager.listen(mPhoneListener, LISTEN_SERVICE_STATE); + mNetworkStatsSubscriptionsMonitor.start(); } registerGlobalAlert(); @@ -544,7 +552,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mShutdownReceiver); - mTeleManager.listen(mPhoneListener, LISTEN_NONE); + if (!mSettings.getCombineSubtypeEnabled()) { + mNetworkStatsSubscriptionsMonitor.stop(); + } final long currentTime = mClock.millis(); @@ -1197,35 +1207,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { }; /** - * Receiver that watches for {@link TelephonyManager} changes, such as - * transitioning between Radio Access Technology(RAT) types. + * Handle collapsed RAT type changed event. */ - @NonNull - private final NetworkTypeListener mPhoneListener; - - class NetworkTypeListener extends PhoneStateListener { - private volatile int mLastCollapsedRatType = NETWORK_TYPE_UNKNOWN; - - NetworkTypeListener(@NonNull Executor executor) { - super(executor); - } - - @Override - public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); - final int collapsedRatType = getCollapsedRatType(networkType); - if (collapsedRatType == mLastCollapsedRatType) return; - - if (LOGD) { - Log.d(TAG, "subtype changed for mobile: " - + mLastCollapsedRatType + " -> " + collapsedRatType); - } - // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); - mLastCollapsedRatType = collapsedRatType; - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); - } + @VisibleForTesting + public void handleOnCollapsedRatTypeChanged() { + // Protect service from frequently updating. Remove pending messages if any. + mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.sendMessageDelayed( + mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); } private void updateIfaces( @@ -1352,8 +1341,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return 0; } - // TODO: return different subType for different subscriptions. - return mPhoneListener.mLastCollapsedRatType; + return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.subscriberId); } private static NetworkIdentitySet findOrCreateNetworkIdentitySet( From d1028a599531c6e4597f6a541c9e58f561ae1159 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Wed, 6 May 2020 15:35:54 +0800 Subject: [PATCH 450/881] Broadcast ACTION_NETWORK_STATS_UPDATED in NetworkStatsHandler There is a corner case which may cause the deadlock: When NetworkStatsService tried to broadcast the intent, NetworkStatsService was waiting for a lock which was hold by ActivityManagerService. In the same time, ActivityManagerService was waiting for ActiveService#startServiceInnerLocked() to get a lock which was hold by ConnectivityService. ConnectivityService was waiting for a lock which was hold by BatteryStatsImpl. BatteryStatsImpl was waiting for a lock which was hold by NetworkStatsService, and the lock was locked by NetworkStatsService when NetworkStatsService tried to broadcast the intent. To prevent deadlock when broadcasting the intent in performPollLocked(), move the intent broadcasting from performPollLocked() to NetworkStatsHandler. Bug: 150418178 Bug: 155155473 Test: 1. Create the second user and see if the device will do factory reset or not. 2. Factory reset manually and see if there is a deadlock. Change-Id: Icf88d3e7a38562ab15187f6c71bc8fb0486d37c0 --- .../android/server/net/NetworkStatsService.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 34e8f62324..e21a01d204 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -178,6 +178,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; private static final int MSG_UPDATE_IFACES = 3; + // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent + // deadlock. + private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -386,6 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { registerGlobalAlert(); break; } + case MSG_BROADCAST_NETWORK_STATS_UPDATED: { + final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); + updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, + READ_NETWORK_USAGE_HISTORY); + break; + } } } } @@ -1508,10 +1518,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // finally, dispatch updated event to any listeners - final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); - updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, - READ_NETWORK_USAGE_HISTORY); + mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED)); Trace.traceEnd(TRACE_TAG_NETWORK); } From ac2db1662c774c56c8633b208c1e5a1050886aec Mon Sep 17 00:00:00 2001 From: Lucas Lin Date: Thu, 7 May 2020 10:12:30 +0000 Subject: [PATCH 451/881] Broadcast ACTION_NETWORK_STATS_UPDATED in NetworkStatsHandler There is a corner case which may cause the deadlock: When NetworkStatsService tried to broadcast the intent, NetworkStatsService was waiting for a lock which was hold by ActivityManagerService. In the same time, ActivityManagerService was waiting for ActiveService#startServiceInnerLocked() to get a lock which was hold by ConnectivityService. ConnectivityService was waiting for a lock which was hold by BatteryStatsImpl. BatteryStatsImpl was waiting for a lock which was hold by NetworkStatsService, and the lock was locked by NetworkStatsService when NetworkStatsService tried to broadcast the intent. To prevent deadlock when broadcasting the intent in performPollLocked(), move the intent broadcasting from performPollLocked() to NetworkStatsHandler. Bug: 150418178 Bug: 155155473 Test: 1. Create the second user and see if the device will do factory reset or not. 2. Factory reset manually and see if there is a deadlock. Change-Id: I80569cb4388beb3fd6cbf64a7885bccee8b1c53c Merged-In: Icf88d3e7a38562ab15187f6c71bc8fb0486d37c0 (cherry picked from commit 3f8ab0350450202910ea702799570c538e96d5cd) --- .../android/server/net/NetworkStatsService.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 1951fc071d..adf017633c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -178,6 +178,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; private static final int MSG_UPDATE_IFACES = 3; + // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent + // deadlock. + private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; /** Flags to control detail level of poll event. */ private static final int FLAG_PERSIST_NETWORK = 0x1; @@ -386,6 +389,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { registerGlobalAlert(); break; } + case MSG_BROADCAST_NETWORK_STATS_UPDATED: { + final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); + updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, + READ_NETWORK_USAGE_HISTORY); + break; + } } } } @@ -1513,10 +1523,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // finally, dispatch updated event to any listeners - final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); - updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, - READ_NETWORK_USAGE_HISTORY); + mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED)); Trace.traceEnd(TRACE_TAG_NETWORK); } From 6a1701dba8dc1e5cf3859a928d7f89a0523dee16 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 3 Oct 2019 11:09:00 -0700 Subject: [PATCH 452/881] Use TransformRecord to get SPI instead of SpiRecord IpSecService.applyTunnelModeTransform() currently does not take an SpiRecord instance, yet implicitly requires that the SpiRecord instance is still alive based on the stored SpiRecord resourceId in the TransformRecord's IpSecConfig. This check is unnecessary, as the SpiRecord has been subsumed into the TransformRecord, and the kernel resources are kept alive whether or not the SpiRecord is still held by the user. This allows users of the IpSecManager API to allocate short-lived SPIs during the creation of an IpSecTransform, without having to keep track of both of them (even though the SPI is no longer usable). The TransformRecord.getSpiRecord() call is already used in multiple other places in the same method. Bug: 142072071 Test: New tests added, passing. Change-Id: I1959f3080946267243564459ff4207647922566e Merged-In: I1959f3080946267243564459ff4207647922566e (cherry picked from commit 1678614ca751a1574609150901278573fd3824fd) --- services/core/java/com/android/server/IpSecService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 905c489e1d..6402e07bdd 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1776,7 +1776,7 @@ public class IpSecService extends IIpSecService.Stub { socketRecord = userRecord.mEncapSocketRecords.getResourceOrThrow(c.getEncapSocketResourceId()); } - SpiRecord spiRecord = userRecord.mSpiRecords.getResourceOrThrow(c.getSpiResourceId()); + SpiRecord spiRecord = transformInfo.getSpiRecord(); int mark = (direction == IpSecManager.DIRECTION_OUT) @@ -1809,7 +1809,7 @@ public class IpSecService extends IIpSecService.Stub { // Set outbound SPI only. We want inbound to use any valid SA (old, new) on rekeys, // but want to guarantee outbound packets are sent over the new SA. - spi = transformInfo.getSpiRecord().getSpi(); + spi = spiRecord.getSpi(); } // Always update the policy with the relevant XFRM_IF_ID From e6213a6283fb23361ffa0d19d1b61fd28c5b82ca Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 11 May 2020 11:20:00 +0900 Subject: [PATCH 453/881] Add capability they should always have to eth networks. There is a stopgap hack in ConnectivityService doing this automatically, but individual agents should be doing this themselves. Test: FrameworksNetTests NetworkStackTests Bug: 150570873 Change-Id: I6f75e2b26eb9f554243bc418142a4dc18839aa79 --- .../src/com/android/server/ethernet/EthernetTracker.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index c8c3bdfb59..d37e0c9c86 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -464,6 +464,7 @@ final class EthernetTracker { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); return nc; } @@ -542,6 +543,11 @@ final class EthernetTracker { } } } + // Ethernet networks have no way to update the following capabilities, so they always + // have them. + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); return nc; } From 5b1f5ccfaa878dbc4112ec969e0f8415235460da Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Tue, 12 May 2020 11:06:23 +0000 Subject: [PATCH 454/881] Use CopyOnWriteArrayList to store list of NetworkStatsProviderCb In NetworkStatsService, mStatsLock will be held when iterating through the provider list. This is to protect the list from concurrent broadcast that triggered by NetworkPolicyManagerService. This is not good since the binder call is oneway, it does not make sense to block every access to the providers. This change also remove unuse variable and reduce verbose log. Test: atest FrameworksNetTests TetheringTests Bug: 150418178 Change-Id: If74e9f2ea597a0d5ae4668c3358bc687f342bbb5 Merged-In: If74e9f2ea597a0d5ae4668c3358bc687f342bbb5 (cherry picked from commit 5d8f96c6967d5b1a42ba374521078e75a9e6f187) --- .../server/net/NetworkStatsService.java | 49 +++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index adf017633c..dcbdfdf7a2 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -119,7 +119,6 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; -import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; @@ -160,6 +159,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; @@ -226,12 +226,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String PREFIX_UID = "uid"; private static final String PREFIX_UID_TAG = "uid_tag"; - /** - * Virtual network interface for video telephony. This is for VT data usage counting purpose. - */ - // TODO: Remove this after no one is using it. - public static final String VT_INTERFACE = NetworkStats.IFACE_VT; - /** * Settings that can be changed externally. */ @@ -304,8 +298,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { new DropBoxNonMonotonicObserver(); private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100; - private final RemoteCallbackList mStatsProviderCbList = - new RemoteCallbackList<>(); + private final CopyOnWriteArrayList mStatsProviderCbList = + new CopyOnWriteArrayList<>(); /** Semaphore used to wait for stats provider to respond to request stats update. */ private final Semaphore mStatsProviderSem = new Semaphore(0, true); @@ -1466,10 +1460,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; // Request asynchronous stats update from all providers for next poll. And wait a bit of - // time to allow providers report-in given that normally binder call should be fast. + // time to allow providers report-in given that normally binder call should be fast. Note + // that size of list might be changed because addition/removing at the same time. For + // addition, the stats of the missed provider can only be collected in next poll; + // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS + // once that happened. // TODO: request with a valid token. Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); - final int registeredCallbackCount = mStatsProviderCbList.getRegisteredCallbackCount(); + final int registeredCallbackCount = mStatsProviderCbList.size(); mStatsProviderSem.drainPermits(); invokeForAllStatsProviderCallbacks( (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); @@ -1643,7 +1641,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { - Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); + if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); } } @@ -1934,7 +1932,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl( tag, provider, mStatsProviderSem, mAlertObserver, mStatsProviderCbList); - mStatsProviderCbList.register(callback); + mStatsProviderCbList.add(callback); Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid=" + getCallingUid() + "/" + getCallingPid()); return callback; @@ -1958,20 +1956,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void invokeForAllStatsProviderCallbacks( @NonNull ThrowingConsumer task) { - synchronized (mStatsLock) { - final int length = mStatsProviderCbList.beginBroadcast(); + for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) { try { - for (int i = 0; i < length; i++) { - final NetworkStatsProviderCallbackImpl cb = - mStatsProviderCbList.getBroadcastItem(i); - try { - task.accept(cb); - } catch (RemoteException e) { - Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); - } - } - } finally { - mStatsProviderCbList.finishBroadcast(); + task.accept(cb); + } catch (RemoteException e) { + Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); } } } @@ -1983,7 +1972,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull final INetworkStatsProvider mProvider; @NonNull private final Semaphore mSemaphore; @NonNull final INetworkManagementEventObserver mAlertObserver; - @NonNull final RemoteCallbackList mStatsProviderCbList; + @NonNull final CopyOnWriteArrayList mStatsProviderCbList; @NonNull private final Object mProviderStatsLock = new Object(); @@ -1997,7 +1986,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull String tag, @NonNull INetworkStatsProvider provider, @NonNull Semaphore semaphore, @NonNull INetworkManagementEventObserver alertObserver, - @NonNull RemoteCallbackList cbList) + @NonNull CopyOnWriteArrayList cbList) throws RemoteException { mTag = tag; mProvider = provider; @@ -2054,13 +2043,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void binderDied() { Log.d(TAG, mTag + ": binderDied"); - mStatsProviderCbList.unregister(this); + mStatsProviderCbList.remove(this); } @Override public void unregister() { Log.d(TAG, mTag + ": unregister"); - mStatsProviderCbList.unregister(this); + mStatsProviderCbList.remove(this); } } From 42d016fdb0c078eeb41fea940607dd2342cf37bf Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 11 May 2020 12:31:01 +0000 Subject: [PATCH 455/881] Add capability they should always have to eth networks. There is a stopgap hack in ConnectivityService doing this automatically, but individual agents should be doing this themselves. Test: FrameworksNetTests NetworkStackTests Bug: 150570873 Original-Change: https://android-review.googlesource.com/1307433 Merged-In: I6f75e2b26eb9f554243bc418142a4dc18839aa79 Change-Id: I6f75e2b26eb9f554243bc418142a4dc18839aa79 --- .../src/com/android/server/ethernet/EthernetTracker.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index c8c3bdfb59..d37e0c9c86 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -464,6 +464,7 @@ final class EthernetTracker { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); return nc; } @@ -542,6 +543,11 @@ final class EthernetTracker { } } } + // Ethernet networks have no way to update the following capabilities, so they always + // have them. + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); return nc; } From 43081c92663646286465e98c4868299b7155c628 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 27 May 2020 12:35:40 +0900 Subject: [PATCH 456/881] Add TRANSPORT_TEST to test ethernet interfaces Because they operate on test interfaces, ethernet interfaces included with setIncludeTestInterfaces should have TRANSPORT_TEST. Bug: 156319532 Test: atest CaptivePortalApiTest Change-Id: Ife3eab06432cabf3ee626de49abc31c8349b4316 --- .../android/server/ethernet/EthernetTracker.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index d37e0c9c86..d7fd408b69 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -70,6 +70,8 @@ final class EthernetTracker { private final static String TAG = EthernetTracker.class.getSimpleName(); private final static boolean DBG = EthernetNetworkFactory.DBG; + private static final String TEST_IFACE_REGEXP = TEST_TAP_PREFIX + "\\d+"; + /** * Interface names we track. This is a product-dependent regular expression, plus, * if setIncludeTestInterfaces is true, any test interfaces. @@ -298,7 +300,8 @@ final class EthernetTracker { // Try to resolve using mac address nc = mNetworkCapabilities.get(hwAddress); if (nc == null) { - nc = createDefaultNetworkCapabilities(); + final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP); + nc = createDefaultNetworkCapabilities(isTestIface); } } @@ -457,15 +460,20 @@ final class EthernetTracker { } } - private static NetworkCapabilities createDefaultNetworkCapabilities() { + private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) { NetworkCapabilities nc = createNetworkCapabilities(false /* clear default capabilities */); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); + if (isTestIface) { + nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST); + } else { + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + } + return nc; } @@ -610,7 +618,7 @@ final class EthernetTracker { final String match = mContext.getResources().getString( com.android.internal.R.string.config_ethernet_iface_regex); mIfaceMatch = mIncludeTestInterfaces - ? "(" + match + "|" + TEST_TAP_PREFIX + "\\d+)" + ? "(" + match + "|" + TEST_IFACE_REGEXP + ")" : match; Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'"); } From bb4f409b5067c4518538c01390ff00c062411e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Mon, 23 Dec 2019 14:37:31 -0800 Subject: [PATCH 457/881] NetworkStatsService - xt_qtaguid non-ebpf - account stacked interface stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: atest bpf_module_test clatd_test libbpf_android_test libnetdbpf_test netd_integration_test netd_unit_test netdutils_test Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I297fcad0a83bd8c32c0fa6c6a77d83b42cd8c428 --- .../server/net/NetworkStatsService.java | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 5d1cc2a5c2..823717c7d2 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1306,21 +1306,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // Traffic occurring on stacked interfaces is usually clatd. - // UID stats are always counted on the stacked interface and never - // on the base interface, because the packets on the base interface - // do not actually match application sockets until they are translated. // - // Interface stats are more complicated. Packets subject to BPF offload - // never appear on the base interface and only appear on the stacked - // interface, so to ensure those packets increment interface stats, interface - // stats from stacked interfaces must be collected. + // UID stats are always counted on the stacked interface and never on the base + // interface, because the packets on the base interface do not actually match + // application sockets (they're not IPv4) and thus the app uid is not known. + // For receive this is obvious: packets must be translated from IPv6 to IPv4 + // before the application socket can be found. + // For transmit: either they go through the clat daemon which by virtue of going + // through userspace strips the original socket association during the IPv4 to + // IPv6 translation process, or they are offloaded by eBPF, which doesn't: + // However, on an ebpf device the accounting is done in cgroup ebpf hooks, + // which don't trigger again post ebpf translation. + // (as such stats accounted to the clat uid are ignored) + // + // Interface stats are more complicated. + // + // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus + // *all* statistics are collected by iptables on the stacked v4-* interface. + // + // Additionally for ingress all packets bound for the clat IPv6 address are dropped + // in ip6tables raw prerouting and thus even non-offloaded packets are only + // accounted for on the stacked interface. + // + // For egress, packets subject to eBPF offload never appear on the base interface + // and only appear on the stacked interface. Thus to ensure packets increment + // interface stats, we must collate data from stacked interfaces. For xt_qtaguid + // (or non eBPF offloaded) TX they would appear on both, however egress interface + // accounting is explicitly bypassed for traffic from the clat uid. + // final List stackedLinks = state.linkProperties.getStackedLinks(); for (LinkProperties stackedLink : stackedLinks) { final String stackedIface = stackedLink.getInterfaceName(); if (stackedIface != null) { - if (mUseBpfTrafficStats) { - findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); - } + findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); if (isMobile) { mobileIfaces.add(stackedIface); From 7b69833232b45f09f57ac1f48e5b158ac847790b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 00:58:07 +0000 Subject: [PATCH 458/881] NetworkStatsService - xt_qtaguid non-ebpf - account stacked interface stats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: atest bpf_module_test clatd_test libbpf_android_test libnetdbpf_test netd_integration_test netd_unit_test netdutils_test Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I297fcad0a83bd8c32c0fa6c6a77d83b42cd8c428 Merged-In: I297fcad0a83bd8c32c0fa6c6a77d83b42cd8c428 --- .../server/net/NetworkStatsService.java | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index dcbdfdf7a2..cf5a412321 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1311,21 +1311,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // Traffic occurring on stacked interfaces is usually clatd. - // UID stats are always counted on the stacked interface and never - // on the base interface, because the packets on the base interface - // do not actually match application sockets until they are translated. // - // Interface stats are more complicated. Packets subject to BPF offload - // never appear on the base interface and only appear on the stacked - // interface, so to ensure those packets increment interface stats, interface - // stats from stacked interfaces must be collected. + // UID stats are always counted on the stacked interface and never on the base + // interface, because the packets on the base interface do not actually match + // application sockets (they're not IPv4) and thus the app uid is not known. + // For receive this is obvious: packets must be translated from IPv6 to IPv4 + // before the application socket can be found. + // For transmit: either they go through the clat daemon which by virtue of going + // through userspace strips the original socket association during the IPv4 to + // IPv6 translation process, or they are offloaded by eBPF, which doesn't: + // However, on an ebpf device the accounting is done in cgroup ebpf hooks, + // which don't trigger again post ebpf translation. + // (as such stats accounted to the clat uid are ignored) + // + // Interface stats are more complicated. + // + // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus + // *all* statistics are collected by iptables on the stacked v4-* interface. + // + // Additionally for ingress all packets bound for the clat IPv6 address are dropped + // in ip6tables raw prerouting and thus even non-offloaded packets are only + // accounted for on the stacked interface. + // + // For egress, packets subject to eBPF offload never appear on the base interface + // and only appear on the stacked interface. Thus to ensure packets increment + // interface stats, we must collate data from stacked interfaces. For xt_qtaguid + // (or non eBPF offloaded) TX they would appear on both, however egress interface + // accounting is explicitly bypassed for traffic from the clat uid. + // final List stackedLinks = state.linkProperties.getStackedLinks(); for (LinkProperties stackedLink : stackedLinks) { final String stackedIface = stackedLink.getInterfaceName(); if (stackedIface != null) { - if (mUseBpfTrafficStats) { - findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); - } + findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); if (isMobile) { mobileIfaces.add(stackedIface); From 7b964ba2c04479158b85b351d3291782e19af147 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Tue, 24 Dec 2019 02:50:35 -0800 Subject: [PATCH 459/881] NetworkStats - no need for xt_qtaguid clat bw fixups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is due to the previous addition of the ip6tables raw PREROUTING drop rules for incoming ipv6 clat traffic pre-translation to ipv4. Since we no longer double account, we no longer need these fixups. Test: atest bpf_module_test clatd_test libbpf_android_test libnetdbpf_test netd_integration_test netd_unit_test netdutils_test Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: Ia171b7797cdc99367064d0649bf1293c71579941 --- core/java/android/net/NetworkStats.java | 64 ++++++++++--------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index b7fb280efd..3141320a16 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1047,22 +1047,22 @@ public final class NetworkStats implements Parcelable { } /** - * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * Calculate and apply adjustments to captured statistics for 464xlat traffic. * - *

This mutates both base and stacked traffic stats, to account respectively for - * double-counted traffic and IPv4/IPv6 header size difference. + *

This mutates stacked traffic stats, to account for IPv4/IPv6 header size difference. * - *

For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 - * packet on the stacked interface, and once as translated to an IPv6 packet on the - * base interface. For correct stats accounting on the base interface, if using xt_qtaguid, - * every rx 464xlat packet needs to be subtracted from the root UID on the base interface - * (http://b/12249687, http:/b/33681750), and every tx 464xlat packet which was counted onto - * clat uid should be ignored. + *

UID stats, which are only accounted on the stacked interface, need to be increased + * by 20 bytes/packet to account for translation overhead. * - * As for eBPF, the per uid stats is collected by different hook, the rx packets on base - * interface will not be counted. Thus, the adjustment on root uid is not needed. However, the - * tx traffic counted in the same way xt_qtaguid does, so the traffic on clat uid still - * needs to be ignored. + *

The potential additional overhead of 8 bytes/packet for ip fragments is ignored. + * + *

Interface stats need to sum traffic on both stacked and base interface because: + * - eBPF offloaded packets appear only on the stacked interface + * - Non-offloaded ingress packets appear only on the stacked interface + * (due to iptables raw PREROUTING drop rules) + * - Non-offloaded egress packets appear only on the stacked interface + * (due to ignoring traffic from clat daemon by uid match) + * (and of course the 20 bytes/packet overhead needs to be applied to stacked interface stats) * *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only * {@code ConcurrentHashMap} @@ -1074,46 +1074,34 @@ public final class NetworkStats implements Parcelable { */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { - // Total 464xlat traffic to subtract from uid 0 on all base interfaces. - // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. - final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); - // For recycling Entry entry = null; - Entry adjust = new NetworkStats.Entry(IFACE_ALL, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); - for (int i = 0; i < stackedTraffic.size; i++) { entry = stackedTraffic.getValues(i, entry); - if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { - continue; - } - final String baseIface = stackedIfaces.get(entry.iface); - if (baseIface == null) { - continue; - } - // Subtract xt_qtaguid 464lat rx traffic seen for the root UID on the current base - // interface. As for eBPF, the per uid stats is collected by different hook, the rx - // packets on base interface will not be counted. - adjust.iface = baseIface; - if (!useBpfStats) { - adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets = -entry.rxPackets; - } - adjustments.combineValues(adjust); + if (entry == null) continue; + if (entry.iface == null) continue; + if (!entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) continue; // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes // difference for all packets (http://b/12249687, http:/b/33681750). + // + // Note: this doesn't account for LRO/GRO/GSO/TSO (ie. >mtu) traffic correctly, nor + // does it correctly account for the 8 extra bytes in the IPv6 fragmentation header. + // + // While the ebpf code path does try to simulate proper post segmentation packet + // counts, we have nothing of the sort of xt_qtaguid stats. entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA; entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA; stackedTraffic.setValues(i, entry); } - // Traffic on clat uid is v6 tx traffic that is already counted with app uid on the stacked - // v4 interface, so it needs to be removed to avoid double-counting. + // Theoretically there should be no traffic accounted to the clat daemon's uid: + // see ebpf program 'netd.c's early returns + // and iptables '-m owner --uid-owner clat -j RETURN' rules prior to accounting + // TODO: remove this - should definitely be safe once ebpf only. baseTraffic.removeUids(new int[] {CLAT_UID}); - baseTraffic.combineAllValues(adjustments); } /** From 7c8b7b14ea357a1fe8cb4afae815aa50c8a6431a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 01:06:28 -0700 Subject: [PATCH 460/881] NetworkStats: apply464xlatAdjustments - remove useBpfStats parameter. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: atest NetworkStatsTest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I0121a4ac7ee824adc5930bab786d550b2f00b05b --- core/java/android/net/NetworkStats.java | 7 +++---- .../com/android/server/net/NetworkStatsFactory.java | 10 ++++------ .../com/android/server/net/NetworkStatsService.java | 5 ++--- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 3141320a16..ea0889276c 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1069,11 +1069,10 @@ public final class NetworkStats implements Parcelable { * @param baseTraffic Traffic on the base interfaces. Will be mutated. * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. - * @param useBpfStats True if eBPF is in use. * @hide */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { + NetworkStats stackedTraffic, Map stackedIfaces) { // For recycling Entry entry = null; for (int i = 0; i < stackedTraffic.size; i++) { @@ -1113,8 +1112,8 @@ public final class NetworkStats implements Parcelable { * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. * @hide */ - public void apply464xlatAdjustments(Map stackedIfaces, boolean useBpfStats) { - apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats); + public void apply464xlatAdjustments(Map stackedIfaces) { + apply464xlatAdjustments(this, this, stackedIfaces); } /** diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 3dac106418..86ad0b3086 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -152,12 +152,10 @@ public class NetworkStatsFactory { /** * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. - * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) + * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map) */ - public void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic, boolean useBpfStats) { - NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces, - useBpfStats); + public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic) { + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces); } public NetworkStatsFactory() { @@ -380,7 +378,7 @@ public class NetworkStatsFactory { // network, the overhead is their fault. // No locking here: apply464xlatAdjustments behaves fine with an add-only // ConcurrentHashMap. - delta.apply464xlatAdjustments(mStackedIfaces, mUseBpfStats); + delta.apply464xlatAdjustments(mStackedIfaces); // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 823717c7d2..ba538e1cd8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1877,14 +1877,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); - mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, - mUseBpfTrafficStats); + mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); uidSnapshot.combineAllValues(tetherSnapshot); // get a stale copy of uid stats snapshot provided by providers. final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID); providerStats.filter(UID_ALL, ifaces, TAG_ALL); - mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats, mUseBpfTrafficStats); + mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats); uidSnapshot.combineAllValues(providerStats); uidSnapshot.combineAllValues(mUidOperations); From d03416842c26a5fbeeca041aa6e6498b93147c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 01:33:52 -0700 Subject: [PATCH 461/881] NetworkStats: apply464xlatAdjustments - don't remove CLAT_UID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should no longer be needed after all the cleanups. Test: atest NetworkStatsTest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I289d935f84b616ed857ef4c5a7427d57c282d00c --- core/java/android/net/NetworkStats.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index ea0889276c..34e48eb44f 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -16,8 +16,6 @@ package android.net; -import static android.os.Process.CLAT_UID; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -1095,12 +1093,6 @@ public final class NetworkStats implements Parcelable { entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA; stackedTraffic.setValues(i, entry); } - - // Theoretically there should be no traffic accounted to the clat daemon's uid: - // see ebpf program 'netd.c's early returns - // and iptables '-m owner --uid-owner clat -j RETURN' rules prior to accounting - // TODO: remove this - should definitely be safe once ebpf only. - baseTraffic.removeUids(new int[] {CLAT_UID}); } /** From cbc6c27d2037260b8f698dbde740af8f4f5e461e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Tue, 24 Dec 2019 02:50:35 -0800 Subject: [PATCH 462/881] NetworkStats - no need for xt_qtaguid clat bw fixups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is due to the previous addition of the ip6tables raw PREROUTING drop rules for incoming ipv6 clat traffic pre-translation to ipv4. Since we no longer double account, we no longer need these fixups. Test: atest bpf_module_test clatd_test libbpf_android_test libnetdbpf_test netd_integration_test netd_unit_test netdutils_test Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: Ia171b7797cdc99367064d0649bf1293c71579941 Merged-In: Ia171b7797cdc99367064d0649bf1293c71579941 --- core/java/android/net/NetworkStats.java | 64 ++++++++++--------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index b7fb280efd..3141320a16 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1047,22 +1047,22 @@ public final class NetworkStats implements Parcelable { } /** - * Calculate and apply adjustments to captured statistics for 464xlat traffic counted twice. + * Calculate and apply adjustments to captured statistics for 464xlat traffic. * - *

This mutates both base and stacked traffic stats, to account respectively for - * double-counted traffic and IPv4/IPv6 header size difference. + *

This mutates stacked traffic stats, to account for IPv4/IPv6 header size difference. * - *

For 464xlat traffic, xt_qtaguid sees every IPv4 packet twice, once as a native IPv4 - * packet on the stacked interface, and once as translated to an IPv6 packet on the - * base interface. For correct stats accounting on the base interface, if using xt_qtaguid, - * every rx 464xlat packet needs to be subtracted from the root UID on the base interface - * (http://b/12249687, http:/b/33681750), and every tx 464xlat packet which was counted onto - * clat uid should be ignored. + *

UID stats, which are only accounted on the stacked interface, need to be increased + * by 20 bytes/packet to account for translation overhead. * - * As for eBPF, the per uid stats is collected by different hook, the rx packets on base - * interface will not be counted. Thus, the adjustment on root uid is not needed. However, the - * tx traffic counted in the same way xt_qtaguid does, so the traffic on clat uid still - * needs to be ignored. + *

The potential additional overhead of 8 bytes/packet for ip fragments is ignored. + * + *

Interface stats need to sum traffic on both stacked and base interface because: + * - eBPF offloaded packets appear only on the stacked interface + * - Non-offloaded ingress packets appear only on the stacked interface + * (due to iptables raw PREROUTING drop rules) + * - Non-offloaded egress packets appear only on the stacked interface + * (due to ignoring traffic from clat daemon by uid match) + * (and of course the 20 bytes/packet overhead needs to be applied to stacked interface stats) * *

This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only * {@code ConcurrentHashMap} @@ -1074,46 +1074,34 @@ public final class NetworkStats implements Parcelable { */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { - // Total 464xlat traffic to subtract from uid 0 on all base interfaces. - // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically. - final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size()); - // For recycling Entry entry = null; - Entry adjust = new NetworkStats.Entry(IFACE_ALL, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); - for (int i = 0; i < stackedTraffic.size; i++) { entry = stackedTraffic.getValues(i, entry); - if (entry.iface == null || !entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) { - continue; - } - final String baseIface = stackedIfaces.get(entry.iface); - if (baseIface == null) { - continue; - } - // Subtract xt_qtaguid 464lat rx traffic seen for the root UID on the current base - // interface. As for eBPF, the per uid stats is collected by different hook, the rx - // packets on base interface will not be counted. - adjust.iface = baseIface; - if (!useBpfStats) { - adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); - adjust.rxPackets = -entry.rxPackets; - } - adjustments.combineValues(adjust); + if (entry == null) continue; + if (entry.iface == null) continue; + if (!entry.iface.startsWith(CLATD_INTERFACE_PREFIX)) continue; // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes // difference for all packets (http://b/12249687, http:/b/33681750). + // + // Note: this doesn't account for LRO/GRO/GSO/TSO (ie. >mtu) traffic correctly, nor + // does it correctly account for the 8 extra bytes in the IPv6 fragmentation header. + // + // While the ebpf code path does try to simulate proper post segmentation packet + // counts, we have nothing of the sort of xt_qtaguid stats. entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA; entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA; stackedTraffic.setValues(i, entry); } - // Traffic on clat uid is v6 tx traffic that is already counted with app uid on the stacked - // v4 interface, so it needs to be removed to avoid double-counting. + // Theoretically there should be no traffic accounted to the clat daemon's uid: + // see ebpf program 'netd.c's early returns + // and iptables '-m owner --uid-owner clat -j RETURN' rules prior to accounting + // TODO: remove this - should definitely be safe once ebpf only. baseTraffic.removeUids(new int[] {CLAT_UID}); - baseTraffic.combineAllValues(adjustments); } /** From c9d2d396386522e1a070495cf8556fccfcd5bef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 01:06:28 -0700 Subject: [PATCH 463/881] NetworkStats: apply464xlatAdjustments - remove useBpfStats parameter. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: atest NetworkStatsTest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I0121a4ac7ee824adc5930bab786d550b2f00b05b Merged-In: I0121a4ac7ee824adc5930bab786d550b2f00b05b --- core/java/android/net/NetworkStats.java | 7 +++---- .../com/android/server/net/NetworkStatsFactory.java | 10 ++++------ .../com/android/server/net/NetworkStatsService.java | 5 ++--- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 3141320a16..ea0889276c 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -1069,11 +1069,10 @@ public final class NetworkStats implements Parcelable { * @param baseTraffic Traffic on the base interfaces. Will be mutated. * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated. * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. - * @param useBpfStats True if eBPF is in use. * @hide */ public static void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic, Map stackedIfaces, boolean useBpfStats) { + NetworkStats stackedTraffic, Map stackedIfaces) { // For recycling Entry entry = null; for (int i = 0; i < stackedTraffic.size; i++) { @@ -1113,8 +1112,8 @@ public final class NetworkStats implements Parcelable { * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both. * @hide */ - public void apply464xlatAdjustments(Map stackedIfaces, boolean useBpfStats) { - apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats); + public void apply464xlatAdjustments(Map stackedIfaces) { + apply464xlatAdjustments(this, this, stackedIfaces); } /** diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 3dac106418..86ad0b3086 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -152,12 +152,10 @@ public class NetworkStatsFactory { /** * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}. - * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean) + * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map) */ - public void apply464xlatAdjustments(NetworkStats baseTraffic, - NetworkStats stackedTraffic, boolean useBpfStats) { - NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces, - useBpfStats); + public void apply464xlatAdjustments(NetworkStats baseTraffic, NetworkStats stackedTraffic) { + NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces); } public NetworkStatsFactory() { @@ -380,7 +378,7 @@ public class NetworkStatsFactory { // network, the overhead is their fault. // No locking here: apply464xlatAdjustments behaves fine with an add-only // ConcurrentHashMap. - delta.apply464xlatAdjustments(mStackedIfaces, mUseBpfStats); + delta.apply464xlatAdjustments(mStackedIfaces); // Migrate data usage over a VPN to the TUN network. for (VpnInfo info : vpnArray) { diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index cf5a412321..ba9f486092 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1882,14 +1882,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // fold tethering stats and operations into uid snapshot final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); - mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot, - mUseBpfTrafficStats); + mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); uidSnapshot.combineAllValues(tetherSnapshot); // get a stale copy of uid stats snapshot provided by providers. final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID); providerStats.filter(UID_ALL, ifaces, TAG_ALL); - mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats, mUseBpfTrafficStats); + mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats); uidSnapshot.combineAllValues(providerStats); uidSnapshot.combineAllValues(mUidOperations); From 212334b7b9dd274eb46b1212816d787d4fc0130c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 01:33:52 -0700 Subject: [PATCH 464/881] NetworkStats: apply464xlatAdjustments - don't remove CLAT_UID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should no longer be needed after all the cleanups. Test: atest NetworkStatsTest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I289d935f84b616ed857ef4c5a7427d57c282d00c Merged-In: I289d935f84b616ed857ef4c5a7427d57c282d00c --- core/java/android/net/NetworkStats.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index ea0889276c..34e48eb44f 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -16,8 +16,6 @@ package android.net; -import static android.os.Process.CLAT_UID; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -1095,12 +1093,6 @@ public final class NetworkStats implements Parcelable { entry.txBytes += entry.txPackets * IPV4V6_HEADER_DELTA; stackedTraffic.setValues(i, entry); } - - // Theoretically there should be no traffic accounted to the clat daemon's uid: - // see ebpf program 'netd.c's early returns - // and iptables '-m owner --uid-owner clat -j RETURN' rules prior to accounting - // TODO: remove this - should definitely be safe once ebpf only. - baseTraffic.removeUids(new int[] {CLAT_UID}); } /** From 41f01184802278488ed0b4cb9a50e84ab103b6d2 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 29 May 2020 22:09:13 +0000 Subject: [PATCH 465/881] Add TRANSPORT_TEST to test ethernet interfaces Because they operate on test interfaces, ethernet interfaces included with setIncludeTestInterfaces should have TRANSPORT_TEST. Bug: 156319532 Test: atest CaptivePortalApiTest Original-Change: https://android-review.googlesource.com/1318214 Merged-In: Ife3eab06432cabf3ee626de49abc31c8349b4316 Change-Id: Ife3eab06432cabf3ee626de49abc31c8349b4316 --- .../android/server/ethernet/EthernetTracker.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index d37e0c9c86..d7fd408b69 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -70,6 +70,8 @@ final class EthernetTracker { private final static String TAG = EthernetTracker.class.getSimpleName(); private final static boolean DBG = EthernetNetworkFactory.DBG; + private static final String TEST_IFACE_REGEXP = TEST_TAP_PREFIX + "\\d+"; + /** * Interface names we track. This is a product-dependent regular expression, plus, * if setIncludeTestInterfaces is true, any test interfaces. @@ -298,7 +300,8 @@ final class EthernetTracker { // Try to resolve using mac address nc = mNetworkCapabilities.get(hwAddress); if (nc == null) { - nc = createDefaultNetworkCapabilities(); + final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP); + nc = createDefaultNetworkCapabilities(isTestIface); } } @@ -457,15 +460,20 @@ final class EthernetTracker { } } - private static NetworkCapabilities createDefaultNetworkCapabilities() { + private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) { NetworkCapabilities nc = createNetworkCapabilities(false /* clear default capabilities */); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); + if (isTestIface) { + nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST); + } else { + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + } + return nc; } @@ -610,7 +618,7 @@ final class EthernetTracker { final String match = mContext.getResources().getString( com.android.internal.R.string.config_ethernet_iface_regex); mIfaceMatch = mIncludeTestInterfaces - ? "(" + match + "|" + TEST_TAP_PREFIX + "\\d+)" + ? "(" + match + "|" + TEST_IFACE_REGEXP + ")" : match; Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'"); } From 7acca65e50dc73698ff736bf3a6ea66298ffb74f Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 28 Apr 2020 18:07:42 +0800 Subject: [PATCH 466/881] Add unit test for NetworkStatsSubscriptionsMonitor Bug: 154080205 Test: atest FrameworksNetTests:com.android.server.net.NetworkStatsSubscriptionsMonitorTest Change-Id: I4ef3f1ab2e5ea1322133edd80db3ccd0022e9c91 --- .../server/net/NetworkStatsSubscriptionsMonitor.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 0bdf3f22ee..a0ab5eae73 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -28,6 +28,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.CollectionUtils; import java.util.ArrayList; @@ -38,8 +39,6 @@ import java.util.concurrent.Executor; /** * Helper class that watches for events that are triggered per subscription. */ -// TODO (b/152176562): Write tests to verify subscription changes generate corresponding -// register/unregister calls. public class NetworkStatsSubscriptionsMonitor extends SubscriptionManager.OnSubscriptionsChangedListener { @@ -207,5 +206,10 @@ public class NetworkStatsSubscriptionsMonitor extends mLastCollapsedRatType = collapsedRatType; mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType); } + + @VisibleForTesting + public int getSubId() { + return mSubId; + } } } From 03e98293ed7ba54e31a018efa724c1ee061a79db Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 28 Apr 2020 18:07:42 +0800 Subject: [PATCH 467/881] Add unit test for NetworkStatsSubscriptionsMonitor Bug: 154080205 Test: atest FrameworksNetTests:com.android.server.net.NetworkStatsSubscriptionsMonitorTest (copy from ag/11788484 but getActiveAndHiddenSubscriptionIdList() since it's renamed in internal) Change-Id: Ia162f36efe96d90b2f6f70190d9fa855bba34484 Merged-In: I4ef3f1ab2e5ea1322133edd80db3ccd0022e9c91 --- .../server/net/NetworkStatsSubscriptionsMonitor.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 16a63d5436..dc3c30a18a 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -28,6 +28,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.CollectionUtils; import java.util.ArrayList; @@ -38,8 +39,6 @@ import java.util.concurrent.Executor; /** * Helper class that watches for events that are triggered per subscription. */ -// TODO (b/152176562): Write tests to verify subscription changes generate corresponding -// register/unregister calls. public class NetworkStatsSubscriptionsMonitor extends SubscriptionManager.OnSubscriptionsChangedListener { @@ -207,5 +206,10 @@ public class NetworkStatsSubscriptionsMonitor extends mLastCollapsedRatType = collapsedRatType; mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType); } + + @VisibleForTesting + public int getSubId() { + return mSubId; + } } } From 46f32c01aa2847367ddf70f22a59a79abcf8d808 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 20 May 2020 15:21:28 +0800 Subject: [PATCH 468/881] Dynamically enable/disable watch for RAT type changes Add ContentObserver to observe the status of NETSTATS_COMBINE_SUBTYPE_ENABLED to determine that NetworkStatsSubscriptionsMonitor start or stop monitoring data usage per RAT type changes. Bug: 154080515 Test: atest NetworkStatsServiceTest#testDynamicWatchForNetworkRatTypeChanges Change-Id: I272d589633c9186b45753228b05aa0b40b7c7b89 --- .../server/net/NetworkStatsService.java | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index ba538e1cd8..6e01592c51 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -87,6 +87,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.database.ContentObserver; import android.net.DataUsageRequest; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; @@ -103,6 +104,7 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.net.Uri; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; @@ -213,6 +215,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final boolean mUseBpfTrafficStats; + private final ContentObserver mContentObserver; + private final ContentResolver mContentResolver; + @VisibleForTesting public static final String ACTION_NETWORK_STATS_POLL = "com.android.server.action.NETWORK_STATS_POLL"; @@ -438,6 +443,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mHandler = new NetworkStatsHandler(handlerThread.getLooper()); mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, new HandlerExecutor(mHandler), this); + mContentResolver = mContext.getContentResolver(); + mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, + mNetworkStatsSubscriptionsMonitor); } /** @@ -466,6 +474,25 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged()); } + + /** + * Create a ContentObserver instance which is used to observe settings changes, + * and dispatch onChange events on handler thread. + */ + public @NonNull ContentObserver makeContentObserver(@NonNull Handler handler, + @NonNull NetworkStatsSettings settings, + @NonNull NetworkStatsSubscriptionsMonitor monitor) { + return new ContentObserver(handler) { + @Override + public void onChange(boolean selfChange, @NonNull Uri uri) { + if (!settings.getCombineSubtypeEnabled()) { + monitor.start(); + } else { + monitor.stop(); + } + } + }; + } } private void registerLocalService() { @@ -530,11 +557,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, mSettings.getPollInterval(), pollIntent); - // TODO: listen to settings changed to support dynamically enable/disable. - // watch for networkType changes - if (!mSettings.getCombineSubtypeEnabled()) { - mNetworkStatsSubscriptionsMonitor.start(); - } + mContentResolver.registerContentObserver(Settings.Global + .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED), + false /* notifyForDescendants */, mContentObserver); + + // Post a runnable on handler thread to call onChange(). It's for getting current value of + // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes. + mHandler.post(() -> mContentObserver.onChange(false, Settings.Global + .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED))); registerGlobalAlert(); } @@ -560,6 +590,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mNetworkStatsSubscriptionsMonitor.stop(); } + mContentResolver.unregisterContentObserver(mContentObserver); + final long currentTime = mClock.millis(); // persist any pending stats From 8ef2a47c500bd4b889352e9a63ca884f8b67cf9d Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 17 Jun 2020 18:25:35 +0800 Subject: [PATCH 469/881] Address comments from aosp/1298476 This patch addresses the followings, - Pass Looper to NetworkStatsSubscriptionsMonitor constructor - Replace Looper with TestLooper in unit test - Assert fail if result of condition check is not expected. Bug: 154080205 Test: atest FrameworksNetTests:com.android.server.net.NetworkStatsServiceTest atest FrameworksNetTests:com.android.server.net.NetworkStatsSubscriptionsMonitorTest Change-Id: Ibcaba2b38af80cc0ec9a4e428a3b3a1538bc4325 --- .../java/com/android/server/net/NetworkStatsService.java | 9 +++++---- .../server/net/NetworkStatsSubscriptionsMonitor.java | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 6e01592c51..fd8ac061bb 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -442,7 +442,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, - new HandlerExecutor(mHandler), this); + mHandler.getLooper(), new HandlerExecutor(mHandler), this); mContentResolver = mContext.getContentResolver(); mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, mNetworkStatsSubscriptionsMonitor); @@ -468,11 +468,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ @NonNull public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, - @NonNull Executor executor, @NonNull NetworkStatsService service) { + @NonNull Looper looper, @NonNull Executor executor, + @NonNull NetworkStatsService service) { // TODO: Update RatType passively in NSS, instead of querying into the monitor // when forceUpdateIface. - return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> - service.handleOnCollapsedRatTypeChanged()); + return new NetworkStatsSubscriptionsMonitor(context, looper, executor, + (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged()); } /** diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index dc3c30a18a..7711c6a21d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -20,6 +20,7 @@ import static android.net.NetworkTemplate.getCollapsedRatType; import android.annotation.NonNull; import android.content.Context; +import android.os.Looper; import android.telephony.Annotation; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; @@ -75,9 +76,9 @@ public class NetworkStatsSubscriptionsMonitor extends @NonNull private final Executor mExecutor; - NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor, - @NonNull Delegate delegate) { - super(); + NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Looper looper, + @NonNull Executor executor, @NonNull Delegate delegate) { + super(looper); mSubscriptionManager = (SubscriptionManager) context.getSystemService( Context.TELEPHONY_SUBSCRIPTION_SERVICE); mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); From a38ff0a96e11d48a6ad6cba0815c9ad5b49a6e8d Mon Sep 17 00:00:00 2001 From: Michael Groover Date: Fri, 19 Jun 2020 19:48:07 -0700 Subject: [PATCH 470/881] Update docs for methods that require subscriberId In Android 10 additional restrictions were required to access the subscriberId. The NetworkStatsManager has several methods that accept a subscriberId of the mobile network for which usage should be queried. This commit updates the docs for these methods to reference the new access restrictions and offer null as an option to obtain the usage for all mobile networks. Fixes: 157871064 Test: m docs Change-Id: I95c730c9418fced6312eb3ba4e0d69e6299f3ded --- .../app/usage/NetworkStatsManager.java | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index d6e77624a9..fc8248e101 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -41,6 +41,7 @@ import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; +import android.telephony.TelephonyManager; import android.util.DataUnit; import android.util.Log; @@ -198,6 +199,12 @@ public class NetworkStatsManager { * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} * etc. * @param subscriberId If applicable, the subscriber id of the network interface. + *

Starting with API level 29, the {@code subscriberId} is guarded by + * additional restrictions. Calling apps that do not meet the new + * requirements to access the {@code subscriberId} can provide a {@code + * null} value when querying for the mobile network type to receive usage + * for all mobile networks. For additional details see {@link + * TelephonyManager#getSubscriberId()}. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -231,6 +238,12 @@ public class NetworkStatsManager { * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} * etc. * @param subscriberId If applicable, the subscriber id of the network interface. + *

Starting with API level 29, the {@code subscriberId} is guarded by + * additional restrictions. Calling apps that do not meet the new + * requirements to access the {@code subscriberId} can provide a {@code + * null} value when querying for the mobile network type to receive usage + * for all mobile networks. For additional details see {@link + * TelephonyManager#getSubscriberId()}. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -268,6 +281,12 @@ public class NetworkStatsManager { * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} * etc. * @param subscriberId If applicable, the subscriber id of the network interface. + *

Starting with API level 29, the {@code subscriberId} is guarded by + * additional restrictions. Calling apps that do not meet the new + * requirements to access the {@code subscriberId} can provide a {@code + * null} value when querying for the mobile network type to receive usage + * for all mobile networks. For additional details see {@link + * TelephonyManager#getSubscriberId()}. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -301,7 +320,7 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid. * - * #see queryDetailsForUidTagState(int, String, long, long, int, int, int) + * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ public NetworkStats queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid) throws SecurityException { @@ -319,7 +338,7 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid and tag. * - * #see queryDetailsForUidTagState(int, String, long, long, int, int, int) + * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag) throws SecurityException { @@ -344,6 +363,12 @@ public class NetworkStatsManager { * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} * etc. * @param subscriberId If applicable, the subscriber id of the network interface. + *

Starting with API level 29, the {@code subscriberId} is guarded by + * additional restrictions. Calling apps that do not meet the new + * requirements to access the {@code subscriberId} can provide a {@code + * null} value when querying for the mobile network type to receive usage + * for all mobile networks. For additional details see {@link + * TelephonyManager#getSubscriberId()}. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -398,6 +423,12 @@ public class NetworkStatsManager { * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} * etc. * @param subscriberId If applicable, the subscriber id of the network interface. + *

Starting with API level 29, the {@code subscriberId} is guarded by + * additional restrictions. Calling apps that do not meet the new + * requirements to access the {@code subscriberId} can provide a {@code + * null} value when querying for the mobile network type to receive usage + * for all mobile networks. For additional details see {@link + * TelephonyManager#getSubscriberId()}. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -455,7 +486,7 @@ public class NetworkStatsManager { /** * Registers to receive notifications about data usage on specified networks. * - * #see registerUsageCallback(int, String[], long, UsageCallback, Handler) + * @see #registerUsageCallback(int, String, long, UsageCallback, Handler) */ public void registerUsageCallback(int networkType, String subscriberId, long thresholdBytes, UsageCallback callback) { @@ -472,6 +503,12 @@ public class NetworkStatsManager { * @param networkType Type of network to monitor. Either {@link ConnectivityManager#TYPE_MOBILE} or {@link ConnectivityManager#TYPE_WIFI}. * @param subscriberId If applicable, the subscriber id of the network interface. + *

Starting with API level 29, the {@code subscriberId} is guarded by + * additional restrictions. Calling apps that do not meet the new + * requirements to access the {@code subscriberId} can provide a {@code + * null} value when registering for the mobile network type to receive + * notifications for all mobile networks. For additional details see {@link + * TelephonyManager#getSubscriberId()}. * @param thresholdBytes Threshold in bytes to be notified on. * @param callback The {@link UsageCallback} that the system will call when data usage * has exceeded the specified threshold. From 6bdfba28ab299dadffa650fd7b859fe70da40da6 Mon Sep 17 00:00:00 2001 From: Robin Lee Date: Thu, 2 Jul 2020 10:52:18 +0000 Subject: [PATCH 471/881] ITetheredInterfaceCallback is a oneway interface This is sent from the system server, and the system server doesn't like being blocked by apps. Change-Id: I603be3038831974baf1dc392ff0d062e9db91b63 Test: atest CtsTetheringTest Bug: 160389275 --- core/java/android/net/ITetheredInterfaceCallback.aidl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/core/java/android/net/ITetheredInterfaceCallback.aidl index e3d075988c..14aa0237f2 100644 --- a/core/java/android/net/ITetheredInterfaceCallback.aidl +++ b/core/java/android/net/ITetheredInterfaceCallback.aidl @@ -17,7 +17,7 @@ package android.net; /** @hide */ -interface ITetheredInterfaceCallback { +oneway interface ITetheredInterfaceCallback { void onAvailable(in String iface); void onUnavailable(); } \ No newline at end of file From c37e3d08b1e9009da9e91354b7a7c531904ce888 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 18 Oct 2019 18:42:19 +0800 Subject: [PATCH 472/881] Remove ProxyInfo(String) and update callers to use ProxyInfo(Uri) Update all callers to use ProxyInfo(Uri) and remove ProxyInfo(String). Bug: 160557668 Test: build pass atest FrameworksNetTests Change-Id: I4c980764c8839c48acf03208bb68cd53eb910121 --- services/core/java/com/android/server/net/IpConfigStore.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index e3e02e32ad..f0bf5c0975 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -24,6 +24,7 @@ import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.StaticIpConfiguration; +import android.net.Uri; import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; @@ -372,7 +373,7 @@ public class IpConfigStore { config.httpProxy = proxyInfo; break; case PAC: - ProxyInfo proxyPacProperties = new ProxyInfo(pacFileUrl); + ProxyInfo proxyPacProperties = new ProxyInfo(Uri.parse(pacFileUrl)); config.proxySettings = proxySettings; config.httpProxy = proxyPacProperties; break; From eaa76fbd45731e06a5397892b61cc5f6b5ad30cd Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 8 Jul 2020 18:48:00 +0800 Subject: [PATCH 473/881] Attribute data usage to 5G for 5G non-standalone mode Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Bug: 160727498 Change-Id: I563df14500caeb3602b381479afaf5163ad8e6a1 --- .../net/NetworkStatsSubscriptionsMonitor.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 7711c6a21d..dc64393bbf 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -22,6 +22,7 @@ import android.annotation.NonNull; import android.content.Context; import android.os.Looper; import android.telephony.Annotation; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -196,7 +197,19 @@ public class NetworkStatsSubscriptionsMonitor extends @Override public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); + // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony + // would report RAT = 5G_NR. + // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and + // network allocates a secondary 5G cell so telephony reports RAT = LTE along with + // NR state as connected. In such case, attributes the data usage to NR. + // See b/160727498. + final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE + || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) + && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; + + final int networkType = + (is5GNsa ? TelephonyManager.NETWORK_TYPE_NR : ss.getDataNetworkType()); + final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; From cdf050d08f0a533a01fa7fb1d254dfc03bfdd78a Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 10 Jul 2020 03:40:35 +0000 Subject: [PATCH 474/881] Revert "Attribute data usage to 5G for 5G non-standalone mode" This reverts commit eaa76fbd45731e06a5397892b61cc5f6b5ad30cd. Reason for revert: Revert and wait for the design is settled down. Change-Id: I10fdfc37d6456678de1886698cd6ad08bf8aa810 --- .../net/NetworkStatsSubscriptionsMonitor.java | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index dc64393bbf..7711c6a21d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -22,7 +22,6 @@ import android.annotation.NonNull; import android.content.Context; import android.os.Looper; import android.telephony.Annotation; -import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -197,19 +196,7 @@ public class NetworkStatsSubscriptionsMonitor extends @Override public void onServiceStateChanged(@NonNull ServiceState ss) { - // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony - // would report RAT = 5G_NR. - // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and - // network allocates a secondary 5G cell so telephony reports RAT = LTE along with - // NR state as connected. In such case, attributes the data usage to NR. - // See b/160727498. - final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE - || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) - && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; - - final int networkType = - (is5GNsa ? TelephonyManager.NETWORK_TYPE_NR : ss.getDataNetworkType()); - + final int networkType = ss.getDataNetworkType(); final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; From 37c58e61b4f6818bcf678d7c8ade802aebac8a10 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 16 Jul 2020 13:48:09 +0800 Subject: [PATCH 475/881] Attribute data usage to virtual RAT type for 5G non-standalone mode Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Bug: 160727498 Change-Id: I8753e68140c0993773017c9a49bd8a666a364071 --- core/java/android/net/NetworkTemplate.java | 12 ++++++++++++ .../net/NetworkStatsSubscriptionsMonitor.java | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index eba7ff3483..7234eb1d81 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -87,6 +87,15 @@ public class NetworkTemplate implements Parcelable { * @hide */ public static final int NETWORK_TYPE_ALL = -1; + /** + * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is + * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along + * with NR state as connected. This should not be overlapped with any of the + * {@code TelephonyManager.NETWORK_TYPE_*} constants. + * + * @hide + */ + public static final int NETWORK_TYPE_5G_NSA = -2; private static boolean isKnownMatchRule(final int rule) { switch (rule) { @@ -475,6 +484,9 @@ public class NetworkTemplate implements Parcelable { return TelephonyManager.NETWORK_TYPE_LTE; case TelephonyManager.NETWORK_TYPE_NR: return TelephonyManager.NETWORK_TYPE_NR; + // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + case NetworkTemplate.NETWORK_TYPE_5G_NSA: + return NetworkTemplate.NETWORK_TYPE_5G_NSA; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index db553ee795..0575ac6315 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -16,12 +16,14 @@ package com.android.server.net; +import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; import static android.net.NetworkTemplate.getCollapsedRatType; import android.annotation.NonNull; import android.content.Context; import android.os.Looper; import android.telephony.Annotation; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -196,7 +198,18 @@ public class NetworkStatsSubscriptionsMonitor extends @Override public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); + // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony + // would report RAT = 5G_NR. + // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and + // network allocates a secondary 5G cell so telephony reports RAT = LTE along with + // NR state as connected. In such case, attributes the data usage to NR. + // See b/160727498. + final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE + || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) + && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; + + final int networkType = + (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType()); final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; From 4f635a08502d27df924906b3eff883b3be29e5ab Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 16 Jul 2020 13:48:09 +0800 Subject: [PATCH 476/881] Attribute data usage to virtual RAT type for 5G non-standalone mode Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Bug: 160727498 Change-Id: I8753e68140c0993773017c9a49bd8a666a364071 Merged-In: I8753e68140c0993773017c9a49bd8a666a364071 (cherry-picked from ag/12167624) --- core/java/android/net/NetworkTemplate.java | 12 ++++++++++++ .../net/NetworkStatsSubscriptionsMonitor.java | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index eba7ff3483..7234eb1d81 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -87,6 +87,15 @@ public class NetworkTemplate implements Parcelable { * @hide */ public static final int NETWORK_TYPE_ALL = -1; + /** + * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is + * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along + * with NR state as connected. This should not be overlapped with any of the + * {@code TelephonyManager.NETWORK_TYPE_*} constants. + * + * @hide + */ + public static final int NETWORK_TYPE_5G_NSA = -2; private static boolean isKnownMatchRule(final int rule) { switch (rule) { @@ -475,6 +484,9 @@ public class NetworkTemplate implements Parcelable { return TelephonyManager.NETWORK_TYPE_LTE; case TelephonyManager.NETWORK_TYPE_NR: return TelephonyManager.NETWORK_TYPE_NR; + // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + case NetworkTemplate.NETWORK_TYPE_5G_NSA: + return NetworkTemplate.NETWORK_TYPE_5G_NSA; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index a0ab5eae73..cb1c7e4fd0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -16,11 +16,13 @@ package com.android.server.net; +import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; import static android.net.NetworkTemplate.getCollapsedRatType; import android.annotation.NonNull; import android.content.Context; import android.telephony.Annotation; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -195,7 +197,18 @@ public class NetworkStatsSubscriptionsMonitor extends @Override public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); + // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony + // would report RAT = 5G_NR. + // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and + // network allocates a secondary 5G cell so telephony reports RAT = LTE along with + // NR state as connected. In such case, attributes the data usage to NR. + // See b/160727498. + final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE + || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) + && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; + + final int networkType = + (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType()); final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; From 6595b08d8da8aabe640ef4dddde4a500b231f356 Mon Sep 17 00:00:00 2001 From: Peter Wang Date: Mon, 16 Mar 2020 04:45:23 -0700 Subject: [PATCH 477/881] [Telephony Mainline] Rename getActiveAndHiddenSubscriptionIdList and guard with permission Bug: 150878235 Fix: 150878235 Test: Build Change-Id: I7f3b1f5170e032336d9b39b322c49e2b92573586 Merged-In: I7f3b1f5170e032336d9b39b322c49e2b92573586 --- .../android/server/net/NetworkStatsSubscriptionsMonitor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 7711c6a21d..db553ee795 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -125,7 +125,7 @@ public class NetworkStatsSubscriptionsMonitor extends @NonNull private List getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) { final ArrayList ret = new ArrayList<>(); - final int[] ids = subscriptionManager.getActiveAndHiddenSubscriptionIdList(); + final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList(); for (int id : ids) ret.add(id); return ret; } From 7fd64dee0f5558232ea0b3df268f06e6b3a1bd4f Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 16 Jul 2020 13:48:09 +0800 Subject: [PATCH 478/881] Attribute data usage to virtual RAT type for 5G non-standalone mode Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Bug: 160727498 Change-Id: I8753e68140c0993773017c9a49bd8a666a364071 Merged-In: I8753e68140c0993773017c9a49bd8a666a364071 (cherry-picked from ag/12167624) --- core/java/android/net/NetworkTemplate.java | 12 ++++++++++++ .../net/NetworkStatsSubscriptionsMonitor.java | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cb9463a59d..4b806e714f 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -84,6 +84,15 @@ public class NetworkTemplate implements Parcelable { * @hide */ public static final int NETWORK_TYPE_ALL = -1; + /** + * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is + * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along + * with NR state as connected. This should not be overlapped with any of the + * {@code TelephonyManager.NETWORK_TYPE_*} constants. + * + * @hide + */ + public static final int NETWORK_TYPE_5G_NSA = -2; private static boolean isKnownMatchRule(final int rule) { switch (rule) { @@ -472,6 +481,9 @@ public class NetworkTemplate implements Parcelable { return TelephonyManager.NETWORK_TYPE_LTE; case TelephonyManager.NETWORK_TYPE_NR: return TelephonyManager.NETWORK_TYPE_NR; + // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + case NetworkTemplate.NETWORK_TYPE_5G_NSA: + return NetworkTemplate.NETWORK_TYPE_5G_NSA; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 7711c6a21d..5f2c4a38b4 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -16,12 +16,14 @@ package com.android.server.net; +import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; import static android.net.NetworkTemplate.getCollapsedRatType; import android.annotation.NonNull; import android.content.Context; import android.os.Looper; import android.telephony.Annotation; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -196,7 +198,18 @@ public class NetworkStatsSubscriptionsMonitor extends @Override public void onServiceStateChanged(@NonNull ServiceState ss) { - final int networkType = ss.getDataNetworkType(); + // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony + // would report RAT = 5G_NR. + // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and + // network allocates a secondary 5G cell so telephony reports RAT = LTE along with + // NR state as connected. In such case, attributes the data usage to NR. + // See b/160727498. + final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE + || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) + && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; + + final int networkType = + (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType()); final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; From f4e77ac570c1a571378da92410ec99ab73c32c12 Mon Sep 17 00:00:00 2001 From: Pavan Kumar M Date: Tue, 21 Jul 2020 14:18:23 +0530 Subject: [PATCH 479/881] Gracefully handle integer overflows. Avoid recording negative data by doing integer-based math as much as possible, but switch to double-based math if we detect that we'd end up causing an overflow. Test : - Builds, Boots - High data throughput scenarios - NetworkStatsHistoryTest, NetworkStatsCollectionTest, NetworkStatsTest Bug: 119527458 Change-Id: I55d4aa649bea3ae201ad513074ff2b71cb918dad --- .../java/android/net/NetworkStatsHistory.java | 36 ++++++++++----- .../server/net/NetworkStatsCollection.java | 46 +++++-------------- 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index c82c288222..897b67cbaf 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -26,6 +26,7 @@ import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray; import static android.net.NetworkStatsHistory.Entry.UNKNOWN; import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; +import static android.net.NetworkUtils.multiplySafeByRational; import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; @@ -364,11 +365,12 @@ public class NetworkStatsHistory implements Parcelable { if (overlap <= 0) continue; // integer math each time is faster than floating point - final long fracRxBytes = rxBytes * overlap / duration; - final long fracRxPackets = rxPackets * overlap / duration; - final long fracTxBytes = txBytes * overlap / duration; - final long fracTxPackets = txPackets * overlap / duration; - final long fracOperations = operations * overlap / duration; + final long fracRxBytes = multiplySafeByRational(rxBytes, overlap, duration); + final long fracRxPackets = multiplySafeByRational(rxPackets, overlap, duration); + final long fracTxBytes = multiplySafeByRational(txBytes, overlap, duration); + final long fracTxPackets = multiplySafeByRational(txPackets, overlap, duration); + final long fracOperations = multiplySafeByRational(operations, overlap, duration); + addLong(activeTime, i, overlap); addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes; @@ -568,12 +570,24 @@ public class NetworkStatsHistory implements Parcelable { if (overlap <= 0) continue; // integer math each time is faster than floating point - if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketSpan; - if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketSpan; - if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketSpan; - if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketSpan; - if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketSpan; - if (operations != null) entry.operations += operations[i] * overlap / bucketSpan; + if (activeTime != null) { + entry.activeTime += multiplySafeByRational(activeTime[i], overlap, bucketSpan); + } + if (rxBytes != null) { + entry.rxBytes += multiplySafeByRational(rxBytes[i], overlap, bucketSpan); + } + if (rxPackets != null) { + entry.rxPackets += multiplySafeByRational(rxPackets[i], overlap, bucketSpan); + } + if (txBytes != null) { + entry.txBytes += multiplySafeByRational(txBytes[i], overlap, bucketSpan); + } + if (txPackets != null) { + entry.txPackets += multiplySafeByRational(txPackets[i], overlap, bucketSpan); + } + if (operations != null) { + entry.operations += multiplySafeByRational(operations[i], overlap, bucketSpan); + } } return entry; } diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index ab525237db..ba3cea768c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -28,6 +28,7 @@ import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; +import static android.net.NetworkUtils.multiplySafeByRational; import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static com.android.server.net.NetworkStatsService.TAG; @@ -185,35 +186,6 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } - /** - * Safely multiple a value by a rational. - *

- * Internally it uses integer-based math whenever possible, but switches - * over to double-based math if values would overflow. - */ - @VisibleForTesting - public static long multiplySafe(long value, long num, long den) { - if (den == 0) den = 1; - long x = value; - long y = num; - - // Logic shamelessly borrowed from Math.multiplyExact() - long r = x * y; - long ax = Math.abs(x); - long ay = Math.abs(y); - if (((ax | ay) >>> 31 != 0)) { - // Some bits greater than 2^31 that might cause overflow - // Check the result using the divide operator - // and check for the special case of Long.MIN_VALUE * -1 - if (((y != 0) && (r / y != x)) || - (x == Long.MIN_VALUE && y == -1)) { - // Use double math to avoid overflowing - return (long) (((double) num / den) * value); - } - } - return r / den; - } - public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) { return getRelevantUids(accessLevel, Binder.getCallingUid()); } @@ -311,11 +283,13 @@ public class NetworkStatsCollection implements FileRotator.Reader { } final long rawBytes = entry.rxBytes + entry.txBytes; - final long rawRxBytes = entry.rxBytes; - final long rawTxBytes = entry.txBytes; + final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes; + final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes; final long targetBytes = augmentPlan.getDataUsageBytes(); - final long targetRxBytes = multiplySafe(targetBytes, rawRxBytes, rawBytes); - final long targetTxBytes = multiplySafe(targetBytes, rawTxBytes, rawBytes); + + final long targetRxBytes = multiplySafeByRational(targetBytes, rawRxBytes, rawBytes); + final long targetTxBytes = multiplySafeByRational(targetBytes, rawTxBytes, rawBytes); + // Scale all matching buckets to reach anchor target final long beforeTotal = combined.getTotalBytes(); @@ -323,8 +297,10 @@ public class NetworkStatsCollection implements FileRotator.Reader { combined.getValues(i, entry); if (entry.bucketStart >= augmentStart && entry.bucketStart + entry.bucketDuration <= augmentEnd) { - entry.rxBytes = multiplySafe(targetRxBytes, entry.rxBytes, rawRxBytes); - entry.txBytes = multiplySafe(targetTxBytes, entry.txBytes, rawTxBytes); + entry.rxBytes = multiplySafeByRational( + targetRxBytes, entry.rxBytes, rawRxBytes); + entry.txBytes = multiplySafeByRational( + targetTxBytes, entry.txBytes, rawTxBytes); // We purposefully clear out packet counters to indicate // that this data has been augmented. entry.rxPackets = 0; From 3dc92d5243b1b5d55e6ccae5a02d96ee8afc573e Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 28 Jul 2020 13:53:09 +0800 Subject: [PATCH 480/881] Update language to comply with Android's inclusive language guidance See https://source.android.com/setup/contribute/respectful-code for reference. Bug: 161896447 Test: m Change-Id: I6c3c03c0c2d1302af6d5245486823c13a3432900 --- .../core/java/com/android/server/net/NetworkStatsFactory.java | 4 ++-- .../java/com/android/server/net/NetworkStatsRecorder.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 86ad0b3086..e9868fde30 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -59,7 +59,7 @@ public class NetworkStatsFactory { private static final String TAG = "NetworkStatsFactory"; private static final boolean USE_NATIVE_PARSING = true; - private static final boolean SANITY_CHECK_NATIVE = false; + private static final boolean VALIDATE_NATIVE_STATS = false; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */ private final File mStatsXtIfaceAll; @@ -347,7 +347,7 @@ public class NetworkStatsFactory { INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) { throw new IOException("Failed to parse network stats"); } - if (SANITY_CHECK_NATIVE) { + if (VALIDATE_NATIVE_STATS) { final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, UID_ALL, INTERFACES_ALL, TAG_ALL); assertEquals(javaStats, stats); diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index a94a2f79ab..66eda1fc2d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -227,7 +227,7 @@ public class NetworkStatsRecorder { for (int i = 0; i < delta.size(); i++) { entry = delta.getValues(i, entry); - // As a last-ditch sanity check, report any negative values and + // As a last-ditch check, report any negative values and // clamp them so recording below doesn't croak. if (entry.isNegative()) { if (mObserver != null) { From 55b277c912300e4dded55ee1dd7982bbdb0020dd Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 29 Jul 2020 12:05:04 +0800 Subject: [PATCH 481/881] Update language to comply with Android's inclusive language guidance See https://source.android.com/setup/contribute/respectful-code for reference. Test: m ; atest TetheringTests Bug: 161896447 Change-Id: Idc58697c72fb00896bee00185fefc50c1a24dd35 --- .../Tethering/src/android/net/util/TetheringMessageBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java index 1b763ce920..29c0a817b6 100644 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java @@ -19,7 +19,7 @@ package android.net.util; * This class defines Message.what base addresses for various state machine. */ public class TetheringMessageBase { - public static final int BASE_MASTER = 0; + public static final int BASE_MAIN_SM = 0; public static final int BASE_IPSERVER = 100; } From c040064a230e82df19c18f771443a9ff3d8c9fef Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 29 Jul 2020 12:05:04 +0800 Subject: [PATCH 482/881] Update language to comply with Android's inclusive language guidance See https://source.android.com/setup/contribute/respectful-code for reference. Test: m ; atest TetheringTests Bug: 161896447 Change-Id: Idc58697c72fb00896bee00185fefc50c1a24dd35 Merged-In: Idc58697c72fb00896bee00185fefc50c1a24dd35 --- .../Tethering/src/android/net/util/TetheringMessageBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java index 1b763ce920..29c0a817b6 100644 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java @@ -19,7 +19,7 @@ package android.net.util; * This class defines Message.what base addresses for various state machine. */ public class TetheringMessageBase { - public static final int BASE_MASTER = 0; + public static final int BASE_MAIN_SM = 0; public static final int BASE_IPSERVER = 100; } From 20452935f96a5463bd32482bf3dea813ca63d98c Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 12 Aug 2020 12:23:59 +0800 Subject: [PATCH 483/881] Update language to comply with Android's inclusive language guidance See https://source.android.com/setup/contribute/respectful-code for reference. Bug: 161896447 Test: m ; atest FrameworkNetTests Change-Id: Ib6b4c9526992c31e05e82be80e2b9b86bc0b57ef --- services/core/java/com/android/server/IpSecService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 6402e07bdd..b2f0c8376d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1477,7 +1477,7 @@ public class IpSecService extends IIpSecService.Stub { } /** - * Checks an IpSecConfig parcel to ensure that the contents are sane and throws an + * Checks an IpSecConfig parcel to ensure that the contents are valid and throws an * IllegalArgumentException if they are not. */ private void checkIpSecConfig(IpSecConfig config) { From a66d7c4361dfed2d1d13564c99be17d436d9b377 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 7 Aug 2020 23:27:08 +0800 Subject: [PATCH 484/881] Add 5G NSA to collapsed RAT types list Currently, getAllCollapsedRatTypes is used to retrieve all RAT types which will be recorded into NetworkStatsService. However, there is a missing part that 5G NSA virtual RAT type is not added into this list. This makes callers such as statsd do not aware of 5G NSA RAT type and missed to collect data usage of it. Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Test: adb shell cmd stats pull-source 10082 Test: ./out/host/linux-x86/bin/statsd_testdrive 10082 Test: atest UidAtomTests#testMobileBytesTransfer \ UidAtomTests#testMobileBytesTransferByFgBg \ UidAtomTests#testDataUsageBytesTransfer Bug: 163021464 Change-Id: I0faeda20f0506a48ac1131b234c5fc40d95dfbe0 --- core/java/android/net/NetworkTemplate.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 7234eb1d81..cd26079a7b 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -503,6 +503,10 @@ public class NetworkTemplate implements Parcelable { for (final int ratType : ratTypes) { collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); } + // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and + // it is not in TelephonyManager#NETWORK_TYPE_* constants. + // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA)); // Ensure that unknown type is returned. collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); return toIntArray(collapsedRatTypes); From fda084bdc96ef0ccd89adcc941644ad17e9d9d91 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 7 Aug 2020 23:27:08 +0800 Subject: [PATCH 485/881] Add 5G NSA to collapsed RAT types list Currently, getAllCollapsedRatTypes is used to retrieve all RAT types which will be recorded into NetworkStatsService. However, there is a missing part that 5G NSA virtual RAT type is not added into this list. This makes callers such as statsd do not aware of 5G NSA RAT type and missed to collect data usage of it. Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Test: adb shell cmd stats pull-source 10082 Test: ./out/host/linux-x86/bin/statsd_testdrive 10082 Test: atest UidAtomTests#testMobileBytesTransfer \ UidAtomTests#testMobileBytesTransferByFgBg \ UidAtomTests#testDataUsageBytesTransfer Bug: 163021464 Change-Id: I0faeda20f0506a48ac1131b234c5fc40d95dfbe0 Merged-In: I0faeda20f0506a48ac1131b234c5fc40d95dfbe0 --- core/java/android/net/NetworkTemplate.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 7234eb1d81..cd26079a7b 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -503,6 +503,10 @@ public class NetworkTemplate implements Parcelable { for (final int ratType : ratTypes) { collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); } + // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and + // it is not in TelephonyManager#NETWORK_TYPE_* constants. + // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA)); // Ensure that unknown type is returned. collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); return toIntArray(collapsedRatTypes); From 064b6915aa2b44ada2e3986674a1e3c5aaed9955 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 11 Feb 2020 14:59:38 +0800 Subject: [PATCH 486/881] Add getAllCollapsedRatTypes to NetworkTemplate This is a partial cherry-pick of ag/10293594 Test: TH Bug: 129082217 Merged-In: I726e74f5c63a6ed456cb13ea259b58c7a33bec76 Change-Id: I726e74f5c63a6ed456cb13ea259b58c7a33bec76 --- core/java/android/net/NetworkTemplate.java | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 4b806e714f..7234eb1d81 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -34,6 +34,7 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.sanitizeSsid; +import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; @@ -52,6 +53,8 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -489,6 +492,32 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Return all supported collapsed RAT types that could be returned by + * {@link #getCollapsedRatType(int)}. + */ + @NonNull + public static final int[] getAllCollapsedRatTypes() { + final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); + final HashSet collapsedRatTypes = new HashSet<>(); + for (final int ratType : ratTypes) { + collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); + } + // Ensure that unknown type is returned. + collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); + return toIntArray(collapsedRatTypes); + } + + @NonNull + private static int[] toIntArray(@NonNull Collection list) { + final int[] array = new int[list.size()]; + int i = 0; + for (final Integer item : list) { + array[i++] = item; + } + return array; + } + /** * Check if matches Wi-Fi network template. */ From 084485bcb94fdd12d9ec23e75e652a9ba60ea3ae Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 7 Aug 2020 23:27:08 +0800 Subject: [PATCH 487/881] Add 5G NSA to collapsed RAT types list Currently, getAllCollapsedRatTypes is used to retrieve all RAT types which will be recorded into NetworkStatsService. However, there is a missing part that 5G NSA virtual RAT type is not added into this list. This makes callers such as statsd do not aware of 5G NSA RAT type and missed to collect data usage of it. Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Test: adb shell cmd stats pull-source 10082 Test: ./out/host/linux-x86/bin/statsd_testdrive 10082 Test: atest UidAtomTests#testMobileBytesTransfer \ UidAtomTests#testMobileBytesTransferByFgBg \ UidAtomTests#testDataUsageBytesTransfer Bug: 163021464 Change-Id: I0faeda20f0506a48ac1131b234c5fc40d95dfbe0 Merged-In: I0faeda20f0506a48ac1131b234c5fc40d95dfbe0 (cherry-picked from ag/12355984) --- core/java/android/net/NetworkTemplate.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 7234eb1d81..cd26079a7b 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -503,6 +503,10 @@ public class NetworkTemplate implements Parcelable { for (final int ratType : ratTypes) { collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); } + // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and + // it is not in TelephonyManager#NETWORK_TYPE_* constants. + // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. + collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA)); // Ensure that unknown type is returned. collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); return toIntArray(collapsedRatTypes); From 58e431877134f33a7e967730c016f1f6663c17ef Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Tue, 11 Aug 2020 08:43:33 -0700 Subject: [PATCH 488/881] WifiP2pManager: Plumb package name to service Will be used for prioritization of different ifaces in HDM. Bug: 162344695 Test: atest com.android.server.wifi Change-Id: Iac1447390f7329768b9c307b08d28ebbd4ea3b90 --- wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl index bfdd45d9f9..fd89d3b048 100644 --- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl +++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl @@ -25,7 +25,7 @@ import android.os.Messenger; */ interface IWifiP2pManager { - Messenger getMessenger(in IBinder binder); + Messenger getMessenger(in IBinder binder, in String packageName); Messenger getP2pStateMachineMessenger(); oneway void close(in IBinder binder); void setMiracastMode(int mode); From 0e7e72fea63efe729ea584ac9ed0391ea35f1667 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 18 Aug 2020 18:50:13 +0800 Subject: [PATCH 489/881] Skip RAT type listener registration if IMSI is not available Currently, if SIM is inserted but IMSI is not available, such as SIM PIN locked state. Information of such SIM will still be available but IMSI is not. Which makes NetworkStatsSubscriptionMonitor failed to store IMSI locally for later RAT type query. Hence, NETWORK_TYPE_UNKNOWN is always returned for such SIM. Skip the registration until the IMSI is available. This is safe since there will be another onSubscriptionsChanged event when that happens. Test: enable SIM PIN and manually test Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdUnavailable Test: ./out/host/linux-x86/bin/statsd_testdrive 10082 Bug: 160941101 Change-Id: I408379b3c432d9e62e0837d6b4f6551cc7838e29 --- .../net/NetworkStatsSubscriptionsMonitor.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 0575ac6315..d202a2a607 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -100,11 +100,16 @@ public class NetworkStatsSubscriptionsMonitor extends if (match != null) continue; // Create listener for every newly added sub. Also store subscriberId into it to - // prevent binder call to telephony when querying RAT. + // prevent binder call to telephony when querying RAT. If the subscriberId is empty + // for any reason, such as SIM PIN locked, skip registration. + // SubscriberId will be unavailable again if 1. modem crashed 2. reboot + // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized + // with active sub list once all subscriberIds are ready. final String subscriberId = mTeleManager.getSubscriberId(subId); if (TextUtils.isEmpty(subscriberId)) { - Log.wtf(NetworkStatsService.TAG, - "Empty subscriberId for newly added sub: " + subId); + Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub " + + subId + ", skip listener registration"); + continue; } final RatTypeListener listener = new RatTypeListener(mExecutor, this, subId, subscriberId); @@ -113,6 +118,7 @@ public class NetworkStatsSubscriptionsMonitor extends // Register listener to the telephony manager that associated with specific sub. mTeleManager.createForSubscriptionId(subId) .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId); } for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { @@ -165,6 +171,7 @@ public class NetworkStatsSubscriptionsMonitor extends private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { mTeleManager.createForSubscriptionId(listener.mSubId) .listen(listener, PhoneStateListener.LISTEN_NONE); + Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId); mRatListeners.remove(listener); // Removal of subscriptions doesn't generate RAT changed event, fire it for every From 11dfa11c890041f93b7e6bd0e2264cd8c61d66bf Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 18 Aug 2020 18:50:13 +0800 Subject: [PATCH 490/881] Skip RAT type listener registration if IMSI is not available Currently, if SIM is inserted but IMSI is not available, such as SIM PIN locked state. Information of such SIM will still be available but IMSI is not. Which makes NetworkStatsSubscriptionMonitor failed to store IMSI locally for later RAT type query. Hence, NETWORK_TYPE_UNKNOWN is always returned for such SIM. Skip the registration until the IMSI is available. This is safe since there will be another onSubscriptionsChanged event when that happens. Test: enable SIM PIN and manually test Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdUnavailable Test: ./out/host/linux-x86/bin/statsd_testdrive 10082 Bug: 160941101 Merged-In: I408379b3c432d9e62e0837d6b4f6551cc7838e29 Change-Id: I408379b3c432d9e62e0837d6b4f6551cc7838e29 (cherry-picked from ag/12400327) --- .../net/NetworkStatsSubscriptionsMonitor.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index cb1c7e4fd0..1c79332e98 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -99,11 +99,16 @@ public class NetworkStatsSubscriptionsMonitor extends if (match != null) continue; // Create listener for every newly added sub. Also store subscriberId into it to - // prevent binder call to telephony when querying RAT. + // prevent binder call to telephony when querying RAT. If the subscriberId is empty + // for any reason, such as SIM PIN locked, skip registration. + // SubscriberId will be unavailable again if 1. modem crashed 2. reboot + // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized + // with active sub list once all subscriberIds are ready. final String subscriberId = mTeleManager.getSubscriberId(subId); if (TextUtils.isEmpty(subscriberId)) { - Log.wtf(NetworkStatsService.TAG, - "Empty subscriberId for newly added sub: " + subId); + Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub " + + subId + ", skip listener registration"); + continue; } final RatTypeListener listener = new RatTypeListener(mExecutor, this, subId, subscriberId); @@ -112,6 +117,7 @@ public class NetworkStatsSubscriptionsMonitor extends // Register listener to the telephony manager that associated with specific sub. mTeleManager.createForSubscriptionId(subId) .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId); } for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { @@ -164,6 +170,7 @@ public class NetworkStatsSubscriptionsMonitor extends private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { mTeleManager.createForSubscriptionId(listener.mSubId) .listen(listener, PhoneStateListener.LISTEN_NONE); + Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId); mRatListeners.remove(listener); // Removal of subscriptions doesn't generate RAT changed event, fire it for every From a13af8b80d9e8ba43e5c0688566b3f763befad4d Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 18 Aug 2020 18:50:13 +0800 Subject: [PATCH 491/881] Skip RAT type listener registration if IMSI is not available Currently, if SIM is inserted but IMSI is not available, such as SIM PIN locked state. Information of such SIM will still be available but IMSI is not. Which makes NetworkStatsSubscriptionMonitor failed to store IMSI locally for later RAT type query. Hence, NETWORK_TYPE_UNKNOWN is always returned for such SIM. Skip the registration until the IMSI is available. This is safe since there will be another onSubscriptionsChanged event when that happens. Test: enable SIM PIN and manually test Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdUnavailable Test: ./out/host/linux-x86/bin/statsd_testdrive 10082 Bug: 160941101 Merged-In: I408379b3c432d9e62e0837d6b4f6551cc7838e29 Change-Id: I408379b3c432d9e62e0837d6b4f6551cc7838e29 (cherry-picked from ag/12400327) --- .../net/NetworkStatsSubscriptionsMonitor.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 0575ac6315..d202a2a607 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -100,11 +100,16 @@ public class NetworkStatsSubscriptionsMonitor extends if (match != null) continue; // Create listener for every newly added sub. Also store subscriberId into it to - // prevent binder call to telephony when querying RAT. + // prevent binder call to telephony when querying RAT. If the subscriberId is empty + // for any reason, such as SIM PIN locked, skip registration. + // SubscriberId will be unavailable again if 1. modem crashed 2. reboot + // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized + // with active sub list once all subscriberIds are ready. final String subscriberId = mTeleManager.getSubscriberId(subId); if (TextUtils.isEmpty(subscriberId)) { - Log.wtf(NetworkStatsService.TAG, - "Empty subscriberId for newly added sub: " + subId); + Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub " + + subId + ", skip listener registration"); + continue; } final RatTypeListener listener = new RatTypeListener(mExecutor, this, subId, subscriberId); @@ -113,6 +118,7 @@ public class NetworkStatsSubscriptionsMonitor extends // Register listener to the telephony manager that associated with specific sub. mTeleManager.createForSubscriptionId(subId) .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId); } for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { @@ -165,6 +171,7 @@ public class NetworkStatsSubscriptionsMonitor extends private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { mTeleManager.createForSubscriptionId(listener.mSubId) .listen(listener, PhoneStateListener.LISTEN_NONE); + Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId); mRatListeners.remove(listener); // Removal of subscriptions doesn't generate RAT changed event, fire it for every From 11385d9d0c3d7cf6038544fd16f6013497d58052 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 19 Aug 2020 16:07:22 +0900 Subject: [PATCH 492/881] Move module utils to the module package. Test: builds Change-Id: If5d1e4a58fb2d6d9544e6d01995dabe445cf1f25 (cherry picked from commit 046bf639eb7728504be35e30e3dd49af3d029728) --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 4a1820a8e5..d907505481 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -25,7 +25,6 @@ import android.net.Uri; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; -import android.net.util.nsd.DnsSdTxtRecord; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; @@ -42,6 +41,7 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.net.module.util.DnsSdTxtRecord; import java.io.FileDescriptor; import java.io.PrintWriter; From e33b576596a8fff01cb03f99318942fb2ff3a0ed Mon Sep 17 00:00:00 2001 From: Hridya Valsaraju Date: Thu, 1 Oct 2020 20:12:46 +0000 Subject: [PATCH 493/881] Revert "Move module utils to the module package." Revert "Move util classes to their destination package" Revert "Move PacketReader and FdEventReader" Revert "Move static utils to a module package" Revert "Move static utils to a module package" Revert submission 12698912-move_packetreader Reason for revert: Broke presubmit on git_master, b/169861635 Reverted Changes: If5d1e4a58:Move module utils to the module package. I44ffaad3d:Move PacketReader and FdEventReader I93e9cfd96:Move util classes to their destination package Ia84d64130:Move static utils to a module package Iaac2810c7:Move static utils to a module package Change-Id: Ibbe59075cd7bc4c38e0707ea6ae3b3703b40986f --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index d907505481..4a1820a8e5 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -25,6 +25,7 @@ import android.net.Uri; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; +import android.net.util.nsd.DnsSdTxtRecord; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; @@ -41,7 +42,6 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; -import com.android.net.module.util.DnsSdTxtRecord; import java.io.FileDescriptor; import java.io.PrintWriter; From 1d34ee5cf79a1480f6fd1af9427c1554a2895203 Mon Sep 17 00:00:00 2001 From: Eran Messeri Date: Fri, 25 Sep 2020 11:35:45 +0100 Subject: [PATCH 494/881] Refactoring: Use explicit methods for checking DO/PO Do not use USES_POLICY_PROFILE_OWNER / USES_POLICY_DEVICE_OWNER. Instead, use explicit methods for checking if the caller is the Device Owner or Profile Owner. USES_POLICY_PROFILE_OWNER is confusing since internally in the DevicePolicyManagerService, it implied a Device Owner is also a Profile Owner, which is not always what the caller expected. This is the first phase of the refactoring, removing external calles' dependency on these constants. The next phase will remove them internally completely in favour of an implementation that accesses mOwners directly. There are no functional changes in this CL. Bug: 163028934 Test: atest FrameworksServicesTests:DevicePolicyManagerTest Change-Id: I57c8465d190a3b4b130d57fd622cc93eaeb9c717 --- .../java/com/android/server/net/NetworkStatsAccess.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 7c1c1c7ce4..5a8fbf3d26 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -24,7 +24,6 @@ import static android.net.TrafficStats.UID_TETHERING; import android.Manifest; import android.annotation.IntDef; import android.app.AppOpsManager; -import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; @@ -111,8 +110,7 @@ public final class NetworkStatsAccess { boolean hasCarrierPrivileges = tm != null && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; - boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, - DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); if (hasCarrierPrivileges || isDeviceOwner || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) { // Carrier-privileged apps and device owners, and the system can access data usage for @@ -126,8 +124,9 @@ public final class NetworkStatsAccess { return NetworkStatsAccess.Level.DEVICESUMMARY; } - boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode. + boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid) + || dpmi.isActiveDeviceOwner(callingUid)); if (isProfileOwner) { // Apps with the AppOps permission, profile owners, and apps with the privileged // permission can access data usage for all apps in this user/profile. From 63fd0c40f091243e78d6ad794190f81a8f8caf56 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 20 Aug 2020 18:23:57 +0800 Subject: [PATCH 495/881] Support dynamically update IMSI Currently, NetworkStatsSubscriptionsMonitor will skip the listener registration until the IMSI is available to deal with SIM PIN locked case. However, this solution can only handle the case that IMSI changes from/to null. And it also relies on the assumption that IMSI never changes for a subId. Thus, support dynamically update IMSI to handle IMSI changes more robustly. This patch also address leftover comments at ag/12400327. Test: enable SIM PIN and manually test Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdUnavailable Test: atest NetworkStatsSubscriptionsMonitorTest#testSubscriberIdChanged Test: ./out/host/linux-x86/bin/statsd_testdrive 10082 Bug: 160941101 Change-Id: I625a5b10ee4806f6fee99c2d9d6c5e7977ff785e --- .../net/NetworkStatsSubscriptionsMonitor.java | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index d202a2a607..5646c752fc 100644 --- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -30,6 +30,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.CollectionUtils; @@ -94,39 +95,41 @@ public class NetworkStatsSubscriptionsMonitor extends // also needed to track CBRS. final List newSubs = getActiveSubIdList(mSubscriptionManager); - for (final int subId : newSubs) { - final RatTypeListener match = CollectionUtils.find(mRatListeners, - it -> it.mSubId == subId); - if (match != null) continue; + // IMSI is needed for every newly added sub. Listener stores subscriberId into it to + // prevent binder call to telephony when querying RAT. Keep listener registration with empty + // IMSI is meaningless since the RAT type changed is ambiguous for multi-SIM if reported + // with empty IMSI. So filter the subs w/o a valid IMSI to prevent such registration. + final List> filteredNewSubs = + CollectionUtils.mapNotNull(newSubs, subId -> { + final String subscriberId = mTeleManager.getSubscriberId(subId); + return TextUtils.isEmpty(subscriberId) ? null : new Pair(subId, subscriberId); + }); - // Create listener for every newly added sub. Also store subscriberId into it to - // prevent binder call to telephony when querying RAT. If the subscriberId is empty - // for any reason, such as SIM PIN locked, skip registration. - // SubscriberId will be unavailable again if 1. modem crashed 2. reboot - // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized - // with active sub list once all subscriberIds are ready. - final String subscriberId = mTeleManager.getSubscriberId(subId); - if (TextUtils.isEmpty(subscriberId)) { - Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub " - + subId + ", skip listener registration"); + for (final Pair sub : filteredNewSubs) { + // Fully match listener with subId and IMSI, since in some rare cases, IMSI might be + // suddenly change regardless of subId, such as switch IMSI feature in modem side. + // If that happens, register new listener with new IMSI and remove old one later. + if (CollectionUtils.find(mRatListeners, + it -> it.equalsKey(sub.first, sub.second)) != null) { continue; } + final RatTypeListener listener = - new RatTypeListener(mExecutor, this, subId, subscriberId); + new RatTypeListener(mExecutor, this, sub.first, sub.second); mRatListeners.add(listener); // Register listener to the telephony manager that associated with specific sub. - mTeleManager.createForSubscriptionId(subId) + mTeleManager.createForSubscriptionId(sub.first) .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); - Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId); + Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first); } for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { - // If the new list contains the subId of the listener, keeps it. - final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId); - if (match != null) continue; - - handleRemoveRatTypeListener(listener); + // If there is no subId and IMSI matched the listener, removes it. + if (CollectionUtils.find(filteredNewSubs, + it -> listener.equalsKey(it.first, it.second)) == null) { + handleRemoveRatTypeListener(listener); + } } } @@ -232,5 +235,9 @@ public class NetworkStatsSubscriptionsMonitor extends public int getSubId() { return mSubId; } + + boolean equalsKey(int subId, @NonNull String subscriberId) { + return mSubId == subId && TextUtils.equals(mSubscriberId, subscriberId); + } } } From 9f6d73c3ccc28aee84e1e9afbdfac8273a3e72a9 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 7 Oct 2020 18:29:20 +0900 Subject: [PATCH 496/881] Allow the network stack to read network stats history Bug: 168984229 Test: testNetworkStatsProvider Change-Id: Ibb6342b0f263c874bb1f7ab4031a639778bad37e --- .../com/android/server/net/NetworkStatsAccess.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 5a8fbf3d26..7cdc4cc747 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -27,6 +27,7 @@ import android.app.AppOpsManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; +import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; @@ -110,11 +111,12 @@ public final class NetworkStatsAccess { boolean hasCarrierPrivileges = tm != null && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; - boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); + final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); + final int appId = UserHandle.getAppId(callingUid); if (hasCarrierPrivileges || isDeviceOwner - || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) { - // Carrier-privileged apps and device owners, and the system can access data usage for - // all apps on the device. + || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { + // Carrier-privileged apps and device owners, and the system (including the + // network stack) can access data usage for all apps on the device. return NetworkStatsAccess.Level.DEVICE; } From 516366088d331f66256457c6181f14f4ac7b1f10 Mon Sep 17 00:00:00 2001 From: Roman Kalukiewicz Date: Wed, 14 Oct 2020 15:59:06 -0700 Subject: [PATCH 497/881] Add @Nullable annotation to the parameter of Object.equals() methods. Those annotations could be inferred by some tools (like Kotlin), but the https://checkerframework.org/ doesn't check inherited annotations complaining about all equals() invocations that get nullable argument. The change was generated by running find . -name \*.java | xargs sed -i 's/public boolean equals(Object /public boolean equals(@Nullable Object /' in the frameworks/base directory and by automatically adding and formatting required imports if needed. No manual edits. Bug: 170883422 Test: Annotation change only. Should have not impact. Exempt-From-Owner-Approval: Mechanical change not specific to any component. Change-Id: I5eedb571c9d78862115dfdc5dae1cf2a35343580 --- core/java/android/net/DataUsageRequest.java | 3 ++- core/java/android/net/IpSecTransform.java | 3 ++- core/java/android/net/NetworkIdentity.java | 3 ++- core/java/android/net/NetworkStats.java | 2 +- core/java/android/net/NetworkTemplate.java | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java index 0ac8f7e794..b06d515b3a 100644 --- a/core/java/android/net/DataUsageRequest.java +++ b/core/java/android/net/DataUsageRequest.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.Nullable; import android.net.NetworkTemplate; import android.os.Parcel; import android.os.Parcelable; @@ -95,7 +96,7 @@ public final class DataUsageRequest implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof DataUsageRequest == false) return false; DataUsageRequest that = (DataUsageRequest) obj; return that.requestId == this.requestId diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 44a0a4f3e1..fa1497dcbc 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -153,7 +154,7 @@ public final class IpSecTransform implements AutoCloseable { /** * Standard equals. */ - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { if (this == other) return true; if (!(other instanceof IpSecTransform)) return false; final IpSecTransform rhs = (IpSecTransform) other; diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 0948a4da1a..9c1038846d 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -20,6 +20,7 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; @@ -69,7 +70,7 @@ public class NetworkIdentity implements Comparable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof NetworkIdentity) { final NetworkIdentity ident = (NetworkIdentity) obj; return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 34e48eb44f..cbee010246 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -411,7 +411,7 @@ public final class NetworkStats implements Parcelable { /** @hide */ @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o instanceof Entry) { final Entry e = (Entry) o; return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cd26079a7b..a95ba12f65 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -327,7 +327,7 @@ public class NetworkTemplate implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof NetworkTemplate) { final NetworkTemplate other = (NetworkTemplate) obj; return mMatchRule == other.mMatchRule From 5c02efcf5b1812201a5079dc2f0daf8ab1655e06 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Wed, 5 Aug 2020 12:16:20 -0700 Subject: [PATCH 498/881] Add new mandatory IPsec algorithms This CL adds new mandatory IPsec algorithms and allows OEM to enable them on old devices using resource overlay Bug: 161716062 Test: FrameworksNetTests:IpSecAlgorithmTest Change-Id: Ib827b05ea27dbe61b14ad236e858f825293ed994 --- core/java/android/net/IpSecAlgorithm.java | 188 +++++++++++++++++++++- 1 file changed, 181 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 38d9883f00..61b2a59f52 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; import android.annotation.StringDef; +import android.content.res.Resources; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -27,6 +28,12 @@ import com.android.internal.util.HexDump; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; /** * This class represents a single algorithm that can be used by an {@link IpSecTransform}. @@ -51,6 +58,29 @@ public final class IpSecAlgorithm implements Parcelable { */ public static final String CRYPT_AES_CBC = "cbc(aes)"; + /** + * AES-CTR Encryption/Ciphering Algorithm. + * + *

Valid lengths for keying material are {160, 224, 288}. + * + *

As per RFC3686 (Section + * 5.1), keying material consists of a 128, 192, or 256 bit AES key followed by a 32-bit + * nonce. RFC compliance requires that the nonce must be unique per security association. + * + *

This algorithm may be available on the device. Caller MUST check if it is supported before + * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is + * included in the returned algorithm set. The returned algorithm set will not change unless the + * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is + * requested on an unsupported device. + * + *

@see {@link #getSupportedAlgorithms()} + * + * @hide + */ + // This algorithm may be available on devices released before Android 12, and is guaranteed + // to be available on devices first shipped with Android 12 or later. + public static final String CRYPT_AES_CTR = "rfc3686(ctr(aes))"; + /** * MD5 HMAC Authentication/Integrity Algorithm. This algorithm is not recommended for use in * new applications and is provided for legacy compatibility with 3gpp infrastructure. @@ -98,6 +128,27 @@ public final class IpSecAlgorithm implements Parcelable { */ public static final String AUTH_HMAC_SHA512 = "hmac(sha512)"; + /** + * AES-XCBC Authentication/Integrity Algorithm. + * + *

Keys for this algorithm must be 128 bits in length. + * + *

The only valid truncation length is 96 bits. + * + *

This algorithm may be available on the device. Caller MUST check if it is supported before + * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is + * included in the returned algorithm set. The returned algorithm set will not change unless the + * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is + * requested on an unsupported device. + * + *

@see {@link #getSupportedAlgorithms()} + * + * @hide + */ + // This algorithm may be available on devices released before Android 12, and is guaranteed + // to be available on devices first shipped with Android 12 or later. + public static final String AUTH_AES_XCBC = "xcbc(aes)"; + /** * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm. * @@ -111,19 +162,69 @@ public final class IpSecAlgorithm implements Parcelable { */ public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))"; + /** + * ChaCha20-Poly1305 Authentication/Integrity + Encryption/Ciphering Algorithm. + * + *

Keys for this algorithm must be 288 bits in length. + * + *

As per RFC7634 (Section 2), + * keying material consists of a 256 bit key followed by a 32-bit salt. The salt is fixed per + * security association. + * + *

The only valid ICV (truncation) length is 128 bits. + * + *

This algorithm may be available on the device. Caller MUST check if it is supported before + * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is + * included in the returned algorithm set. The returned algorithm set will not change unless the + * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is + * requested on an unsupported device. + * + *

@see {@link #getSupportedAlgorithms()} + * + * @hide + */ + // This algorithm may be available on devices released before Android 12, and is guaranteed + // to be available on devices first shipped with Android 12 or later. + public static final String AUTH_CRYPT_CHACHA20_POLY1305 = "rfc7539esp(chacha20,poly1305)"; + /** @hide */ @StringDef({ CRYPT_AES_CBC, + CRYPT_AES_CTR, AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, AUTH_HMAC_SHA384, AUTH_HMAC_SHA512, - AUTH_CRYPT_AES_GCM + AUTH_AES_XCBC, + AUTH_CRYPT_AES_GCM, + AUTH_CRYPT_CHACHA20_POLY1305 }) @Retention(RetentionPolicy.SOURCE) public @interface AlgorithmName {} + /** @hide */ + @VisibleForTesting + public static final Map ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>(); + + static { + ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, Build.VERSION_CODES.P); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P); + + // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined + ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1); + } + + private static final Set ENABLED_ALGOS = + Collections.unmodifiableSet(loadAlgos(Resources.getSystem())); + private final String mName; private final byte[] mKey; private final int mTruncLenBits; @@ -137,6 +238,7 @@ public final class IpSecAlgorithm implements Parcelable { * * @param algorithm name of the algorithm. * @param key key padded to a multiple of 8 bits. + * @throws IllegalArgumentException if algorithm or key length is invalid. */ public IpSecAlgorithm(@NonNull @AlgorithmName String algorithm, @NonNull byte[] key) { this(algorithm, key, 0); @@ -152,6 +254,7 @@ public final class IpSecAlgorithm implements Parcelable { * @param algorithm name of the algorithm. * @param key key padded to a multiple of 8 bits. * @param truncLenBits number of bits of output hash to use. + * @throws IllegalArgumentException if algorithm, key length or truncation length is invalid. */ public IpSecAlgorithm( @NonNull @AlgorithmName String algorithm, @NonNull byte[] key, int truncLenBits) { @@ -206,13 +309,61 @@ public final class IpSecAlgorithm implements Parcelable { } }; - private static void checkValidOrThrow(String name, int keyLen, int truncLen) { - boolean isValidLen = true; - boolean isValidTruncLen = true; + /** + * Returns supported IPsec algorithms for the current device. + * + *

Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is + * supported before using it. + * + * @hide + */ + @NonNull + public static Set getSupportedAlgorithms() { + return ENABLED_ALGOS; + } - switch(name) { + /** @hide */ + @VisibleForTesting + public static Set loadAlgos(Resources systemResources) { + final Set enabledAlgos = new HashSet<>(); + + // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in + // the resource are not allowed. + final String[] resourceAlgos = systemResources.getStringArray( + com.android.internal.R.array.config_optionalIpSecAlgorithms); + for (String str : resourceAlgos) { + if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) { + // This error should be caught by CTS and never be thrown to API callers + throw new IllegalArgumentException("Invalid or repeated algorithm " + str); + } + } + + for (Entry entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) { + if (Build.VERSION.FIRST_SDK_INT >= entry.getValue()) { + enabledAlgos.add(entry.getKey()); + } + } + + return enabledAlgos; + } + + private static void checkValidOrThrow(String name, int keyLen, int truncLen) { + final boolean isValidLen; + final boolean isValidTruncLen; + + if (!getSupportedAlgorithms().contains(name)) { + throw new IllegalArgumentException("Unsupported algorithm: " + name); + } + + switch (name) { case CRYPT_AES_CBC: isValidLen = keyLen == 128 || keyLen == 192 || keyLen == 256; + isValidTruncLen = true; + break; + case CRYPT_AES_CTR: + // The keying material for AES-CTR is a key plus a 32-bit salt + isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32; + isValidTruncLen = true; break; case AUTH_HMAC_MD5: isValidLen = keyLen == 128; @@ -234,12 +385,22 @@ public final class IpSecAlgorithm implements Parcelable { isValidLen = keyLen == 512; isValidTruncLen = truncLen >= 256 && truncLen <= 512; break; + case AUTH_AES_XCBC: + isValidLen = keyLen == 128; + isValidTruncLen = truncLen == 96; + break; case AUTH_CRYPT_AES_GCM: // The keying material for GCM is a key plus a 32-bit salt isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32; isValidTruncLen = truncLen == 64 || truncLen == 96 || truncLen == 128; break; + case AUTH_CRYPT_CHACHA20_POLY1305: + // The keying material for ChaCha20Poly1305 is a key plus a 32-bit salt + isValidLen = keyLen == 256 + 32; + isValidTruncLen = truncLen == 128; + break; default: + // Should never hit here. throw new IllegalArgumentException("Couldn't find an algorithm: " + name); } @@ -260,6 +421,7 @@ public final class IpSecAlgorithm implements Parcelable { case AUTH_HMAC_SHA256: case AUTH_HMAC_SHA384: case AUTH_HMAC_SHA512: + case AUTH_AES_XCBC: return true; default: return false; @@ -268,12 +430,24 @@ public final class IpSecAlgorithm implements Parcelable { /** @hide */ public boolean isEncryption() { - return getName().equals(CRYPT_AES_CBC); + switch (getName()) { + case CRYPT_AES_CBC: // fallthrough + case CRYPT_AES_CTR: + return true; + default: + return false; + } } /** @hide */ public boolean isAead() { - return getName().equals(AUTH_CRYPT_AES_GCM); + switch (getName()) { + case AUTH_CRYPT_AES_GCM: // fallthrough + case AUTH_CRYPT_CHACHA20_POLY1305: + return true; + default: + return false; + } } // Because encryption keys are sensitive and userdebug builds are used by large user pools From a0515bec7677f5752f24ec9ecde93f88b92f741c Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 7 Oct 2020 18:29:20 +0900 Subject: [PATCH 499/881] Allow the network stack to read network stats history Identical to ag/12843161 Bug: 168984229 Test: testNetworkStatsProvider Change-Id: I7ad72c3b2b95f26ceec1371e7e0fdb92fa88920c Merged-In: Ibb6342b0f263c874bb1f7ab4031a639778bad37e --- .../java/com/android/server/net/NetworkStatsAccess.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 7c1c1c7ce4..72559b4825 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -28,6 +28,7 @@ import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; +import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; @@ -113,10 +114,11 @@ public final class NetworkStatsAccess { TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + final int appId = UserHandle.getAppId(callingUid); if (hasCarrierPrivileges || isDeviceOwner - || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) { - // Carrier-privileged apps and device owners, and the system can access data usage for - // all apps on the device. + || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { + // Carrier-privileged apps and device owners, and the system (including the + // network stack) can access data usage for all apps on the device. return NetworkStatsAccess.Level.DEVICE; } From ba07cf027d2ae25b78d0549130bd8dde01958002 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Wed, 12 Aug 2020 13:48:39 -0700 Subject: [PATCH 500/881] Expose new algorithms as public API Bug: 161716062 Test: FrameworksNetTests:IpSecAlgorithmTest Change-Id: I5041c61ad5a4aa58b259e24de80a2c63d6b19dae --- core/java/android/net/IpSecAlgorithm.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 61b2a59f52..a4f7b7454b 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -74,8 +74,6 @@ public final class IpSecAlgorithm implements Parcelable { * requested on an unsupported device. * *

@see {@link #getSupportedAlgorithms()} - * - * @hide */ // This algorithm may be available on devices released before Android 12, and is guaranteed // to be available on devices first shipped with Android 12 or later. @@ -142,8 +140,6 @@ public final class IpSecAlgorithm implements Parcelable { * requested on an unsupported device. * *

@see {@link #getSupportedAlgorithms()} - * - * @hide */ // This algorithm may be available on devices released before Android 12, and is guaranteed // to be available on devices first shipped with Android 12 or later. @@ -180,8 +176,6 @@ public final class IpSecAlgorithm implements Parcelable { * requested on an unsupported device. * *

@see {@link #getSupportedAlgorithms()} - * - * @hide */ // This algorithm may be available on devices released before Android 12, and is guaranteed // to be available on devices first shipped with Android 12 or later. @@ -314,8 +308,6 @@ public final class IpSecAlgorithm implements Parcelable { * *

Some algorithms may not be supported on old devices. Callers MUST check if an algorithm is * supported before using it. - * - * @hide */ @NonNull public static Set getSupportedAlgorithms() { From dce1bf9353b47ea427298fd7f79ac5691f5d074b Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Mon, 19 Oct 2020 16:15:58 +0100 Subject: [PATCH 501/881] Remove @TestApi from @SystemApi symbols I ran these commands: cd frameworks/base grep -rl '@TestApi' --include '*.java' | xargs perl -i -p0e \ 's/\@SystemApi[\s\n]+(\@\w+[\s\n]+)?\@TestApi/\@SystemApi\1/gs' grep -rl '@TestApi' --include '*.java' | xargs perl -i -p0e \ 's/\@TestApi[\s\n]+(\@\w+[\s\n]+)?\@SystemApi/\1\@SystemApi/gs' Bug: 171179806 Test: m checkapi Change-Id: I772790b783b0a8730b8bf680c9e569a886b8d789 Merged-In: I772790b783b0a8730b8bf680c9e569a886b8d789 --- core/java/android/net/EthernetManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index d975017f9c..5860e20ad3 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -37,7 +37,6 @@ import java.util.concurrent.Executor; * @hide */ @SystemApi -@TestApi @SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; From 95a69f8f1b15bc625bbefc895e17e450d9ce767a Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Mon, 19 Oct 2020 18:57:17 +0100 Subject: [PATCH 502/881] Remove @TestApi from @SystemApi symbols I ran these commands: cd frameworks/base grep -rl '@TestApi' --include '*.java' | xargs perl -i -p0e \ 's/\@SystemApi[\s\n]+(\@\w+[\s\n]+)?\@TestApi/\@SystemApi\1/gs' grep -rl '@TestApi' --include '*.java' | xargs perl -i -p0e \ 's/\@TestApi[\s\n]+(\@\w+[\s\n]+)?\@SystemApi/\1\@SystemApi/gs' Bug: 171179806 Test: m checkapi Change-Id: I772790b783b0a8730b8bf680c9e569a886b8d789 Merged-In: I772790b783b0a8730b8bf680c9e569a886b8d789 --- core/java/android/net/EthernetManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index d975017f9c..5860e20ad3 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -37,7 +37,6 @@ import java.util.concurrent.Executor; * @hide */ @SystemApi -@TestApi @SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; From 731713c821d183958bb9b50f1dc988074c19e7c3 Mon Sep 17 00:00:00 2001 From: Anton Hansson Date: Mon, 19 Oct 2020 11:38:00 +0100 Subject: [PATCH 503/881] Remove @TestApi from @SystemApi symbols I ran these commands: cd frameworks/base grep -rl '@TestApi' --include '*.java' | xargs perl -i -p0e \ 's/\@SystemApi[\s\n]+(\@\w+[\s\n]+)?\@TestApi/\@SystemApi\1/gs' grep -rl '@TestApi' --include '*.java' | xargs perl -i -p0e \ 's/\@TestApi[\s\n]+(\@\w+[\s\n]+)?\@SystemApi/\1\@SystemApi/gs' Bug: 171179806 Test: m checkapi Change-Id: I772790b783b0a8730b8bf680c9e569a886b8d789 --- core/java/android/net/EthernetManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index d975017f9c..5860e20ad3 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -37,7 +37,6 @@ import java.util.concurrent.Executor; * @hide */ @SystemApi -@TestApi @SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; From 3b8f510f9ea00e2e8ccaec2038e1f786bf259804 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Tue, 20 Oct 2020 14:49:20 -0700 Subject: [PATCH 504/881] Require devices with first sdk 0 or later to support mandatory algorithms It is safe because these mandatory algorithms are already required before new algorithms are added It is also a quick fix to unblock b/171279612, whose root cause is the device first sdk is wrong Bug: 171279612 Test: atest CtsNetTestCases:IpSecManagerTest Change-Id: I5b9d85b2bc8f13f54467c97160d138a4628265f7 --- core/java/android/net/IpSecAlgorithm.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index a4f7b7454b..e89451e4f4 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -201,14 +201,16 @@ public final class IpSecAlgorithm implements Parcelable { @VisibleForTesting public static final Map ALGO_TO_REQUIRED_FIRST_SDK = new HashMap<>(); + private static final int SDK_VERSION_ZERO = 0; + static { - ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, Build.VERSION_CODES.P); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, Build.VERSION_CODES.P); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, Build.VERSION_CODES.P); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, Build.VERSION_CODES.P); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, Build.VERSION_CODES.P); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, Build.VERSION_CODES.P); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, Build.VERSION_CODES.P); + ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CBC, SDK_VERSION_ZERO); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_MD5, SDK_VERSION_ZERO); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA1, SDK_VERSION_ZERO); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA256, SDK_VERSION_ZERO); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA384, SDK_VERSION_ZERO); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO); // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); From 91ea75cd46e912ed75ed0aec243ce449e5fe5d82 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Sat, 17 Oct 2020 21:20:13 -0600 Subject: [PATCH 505/881] Apply fixes for EfficientStrings. Refactoring to avoid StringBuffer synchronization overhead. Bug: 170978902 Test: none Exempt-From-Owner-Approval: trivial refactoring Change-Id: Ibf843ed780c1202d5d96a11eaca889e592f19263 --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 4a1820a8e5..78bd4cdd4e 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -824,7 +824,7 @@ public class NsdService extends INsdManager.Stub { @Override public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("mChannel ").append(mChannel).append("\n"); sb.append("mMessenger ").append(mMessenger).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); From 18929e62ca16d9227212218d7f098d96af204841 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 27 Oct 2020 11:47:29 +0000 Subject: [PATCH 506/881] Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. Bug: 170729553 Test: Treehugger Change-Id: I4c8fd0006f950de9955242e93968fb0996ceb372 --- .../app/usage/NetworkStatsManager.java | 5 +-- core/java/android/net/EthernetManager.java | 17 +++++----- .../android/net/INetworkStatsService.aidl | 2 +- core/java/android/net/NetworkStats.java | 33 ++++++++++--------- .../java/android/net/NetworkStatsHistory.java | 17 +++++----- core/java/android/net/NetworkTemplate.java | 3 +- core/java/android/net/TrafficStats.java | 4 +-- core/java/android/net/nsd/INsdManager.aidl | 2 +- 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index fc8248e101..1ddfe0d247 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -34,6 +34,7 @@ import android.net.NetworkTemplate; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -129,7 +130,7 @@ public class NetworkStatsManager { /** * {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsManager(Context context) throws ServiceNotFoundException { this(context, INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); @@ -153,7 +154,7 @@ public class NetworkStatsManager { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @TestApi public void setPollForce(boolean pollForce) { if (pollForce) { diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 5860e20ad3..84a8e1c3dc 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -23,6 +23,7 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -76,7 +77,7 @@ public class EthernetManager { * @param isAvailable {@code true} if Ethernet port exists. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void onAvailabilityChanged(String iface, boolean isAvailable); } @@ -97,7 +98,7 @@ public class EthernetManager { * @return the Ethernet Configuration, contained in {@link IpConfiguration}. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public IpConfiguration getConfiguration(String iface) { try { return mService.getConfiguration(iface); @@ -110,7 +111,7 @@ public class EthernetManager { * Set Ethernet configuration. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void setConfiguration(String iface, IpConfiguration config) { try { mService.setConfiguration(iface, config); @@ -123,7 +124,7 @@ public class EthernetManager { * Indicates whether the system currently has one or more Ethernet interfaces. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable() { return getAvailableInterfaces().length > 0; } @@ -134,7 +135,7 @@ public class EthernetManager { * @param iface Ethernet interface name * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable(String iface) { try { return mService.isAvailable(iface); @@ -149,7 +150,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void addListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); @@ -168,7 +169,7 @@ public class EthernetManager { * Returns an array of available Ethernet interface names. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String[] getAvailableInterfaces() { try { return mService.getAvailableInterfaces(); @@ -183,7 +184,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void removeListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 5fa515a143..1a3dc97448 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -42,7 +42,7 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return data layer snapshot of UID network usage. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index cbee010246..d42beae601 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -219,11 +220,11 @@ public final class NetworkStats implements Parcelable { * generated. */ private long elapsedRealtime; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int size; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int capacity; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private String[] iface; @UnsupportedAppUsage private int[] uid; @@ -231,21 +232,21 @@ public final class NetworkStats implements Parcelable { private int[] set; @UnsupportedAppUsage private int[] tag; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] metered; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] roaming; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] defaultNetwork; @UnsupportedAppUsage private long[] rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] rxPackets; @UnsupportedAppUsage private long[] txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] txPackets; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] operations; /** @@ -258,7 +259,7 @@ public final class NetworkStats implements Parcelable { @SystemApi public static class Entry { /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String iface; /** @hide */ @UnsupportedAppUsage @@ -267,7 +268,7 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public int set; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int tag; /** * Note that this is only populated w/ the default value when read from /proc or written @@ -294,20 +295,20 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public long rxBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; /** @hide */ @UnsupportedAppUsage public long txBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long operations; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry() { this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); } @@ -454,7 +455,7 @@ public final class NetworkStats implements Parcelable { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStats(Parcel parcel) { elapsedRealtime = parcel.readLong(); size = parcel.readInt(); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 51f09a0103..fba7561434 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -32,6 +32,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; @@ -91,18 +92,18 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketDuration; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketStart; public long activeTime; @UnsupportedAppUsage public long rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; @UnsupportedAppUsage public long txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; public long operations; } @@ -134,7 +135,7 @@ public class NetworkStatsHistory implements Parcelable { recordEntireHistory(existing); } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); @@ -220,7 +221,7 @@ public class NetworkStatsHistory implements Parcelable { return 0; } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int size() { return bucketCount; } @@ -258,7 +259,7 @@ public class NetworkStatsHistory implements Parcelable { * Return index of bucket that contains or is immediately before the * requested time. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int getIndexBefore(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); if (index < 0) { @@ -286,7 +287,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index a95ba12f65..dc33cc7b61 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; @@ -159,7 +160,7 @@ public class NetworkTemplate implements Parcelable { * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static NetworkTemplate buildTemplateMobileWildcard() { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e7bba69dbb..a985e934ed 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -565,7 +565,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -581,7 +581,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 9484c74bcb..e9e8935a19 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,7 +25,7 @@ import android.os.Messenger; */ interface INsdManager { - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) Messenger getMessenger(); void setEnabled(boolean enable); } From afa0209617d36e058f2f5522f13b759472834f2e Mon Sep 17 00:00:00 2001 From: Hongwei Wang Date: Wed, 28 Oct 2020 19:38:11 +0000 Subject: [PATCH 507/881] Revert "Add maxTargetSdk restriction to unused APIs." This reverts commit 18929e62ca16d9227212218d7f098d96af204841. Reason for revert: Droidcop-triggered revert due to breakage https://android-build.googleplex.com/builds/quarterdeck?testMethod=testAppZygotePreload&testClass=android.app.cts.ServiceTest&atpConfigName=suite%2Ftest-mapping-presubmit-retry_cloud-tf&testModule=CtsAppTestCases&fkbb=6936597&lkbb=6936969&lkgb=6936551&testResults=true&branch=git_master&target=cf_x86_phone-userdebug>, bug b/171886397 Bug: 171886397 Change-Id: Ibe0f0430a3451477c1ee8ef56a596e91ea1e7672 --- .../app/usage/NetworkStatsManager.java | 5 ++- core/java/android/net/EthernetManager.java | 17 +++++----- .../android/net/INetworkStatsService.aidl | 2 +- core/java/android/net/NetworkStats.java | 33 +++++++++---------- .../java/android/net/NetworkStatsHistory.java | 17 +++++----- core/java/android/net/NetworkTemplate.java | 3 +- core/java/android/net/TrafficStats.java | 4 +-- core/java/android/net/nsd/INsdManager.aidl | 2 +- 8 files changed, 39 insertions(+), 44 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 1ddfe0d247..fc8248e101 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -34,7 +34,6 @@ import android.net.NetworkTemplate; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; -import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -130,7 +129,7 @@ public class NetworkStatsManager { /** * {@hide} */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public NetworkStatsManager(Context context) throws ServiceNotFoundException { this(context, INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); @@ -154,7 +153,7 @@ public class NetworkStatsManager { } /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage @TestApi public void setPollForce(boolean pollForce) { if (pollForce) { diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 84a8e1c3dc..5860e20ad3 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -23,7 +23,6 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; -import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -77,7 +76,7 @@ public class EthernetManager { * @param isAvailable {@code true} if Ethernet port exists. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage void onAvailabilityChanged(String iface, boolean isAvailable); } @@ -98,7 +97,7 @@ public class EthernetManager { * @return the Ethernet Configuration, contained in {@link IpConfiguration}. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public IpConfiguration getConfiguration(String iface) { try { return mService.getConfiguration(iface); @@ -111,7 +110,7 @@ public class EthernetManager { * Set Ethernet configuration. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public void setConfiguration(String iface, IpConfiguration config) { try { mService.setConfiguration(iface, config); @@ -124,7 +123,7 @@ public class EthernetManager { * Indicates whether the system currently has one or more Ethernet interfaces. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public boolean isAvailable() { return getAvailableInterfaces().length > 0; } @@ -135,7 +134,7 @@ public class EthernetManager { * @param iface Ethernet interface name * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public boolean isAvailable(String iface) { try { return mService.isAvailable(iface); @@ -150,7 +149,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public void addListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); @@ -169,7 +168,7 @@ public class EthernetManager { * Returns an array of available Ethernet interface names. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public String[] getAvailableInterfaces() { try { return mService.getAvailableInterfaces(); @@ -184,7 +183,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public void removeListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 1a3dc97448..5fa515a143 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -42,7 +42,7 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) + @UnsupportedAppUsage INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return data layer snapshot of UID network usage. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index d42beae601..cbee010246 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,7 +21,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -220,11 +219,11 @@ public final class NetworkStats implements Parcelable { * generated. */ private long elapsedRealtime; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private int size; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private int capacity; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private String[] iface; @UnsupportedAppUsage private int[] uid; @@ -232,21 +231,21 @@ public final class NetworkStats implements Parcelable { private int[] set; @UnsupportedAppUsage private int[] tag; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private int[] metered; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private int[] roaming; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private int[] defaultNetwork; @UnsupportedAppUsage private long[] rxBytes; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private long[] rxPackets; @UnsupportedAppUsage private long[] txBytes; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private long[] txPackets; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage private long[] operations; /** @@ -259,7 +258,7 @@ public final class NetworkStats implements Parcelable { @SystemApi public static class Entry { /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public String iface; /** @hide */ @UnsupportedAppUsage @@ -268,7 +267,7 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public int set; /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public int tag; /** * Note that this is only populated w/ the default value when read from /proc or written @@ -295,20 +294,20 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public long rxBytes; /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public long rxPackets; /** @hide */ @UnsupportedAppUsage public long txBytes; /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public long txPackets; /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public long operations; /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public Entry() { this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); } @@ -455,7 +454,7 @@ public final class NetworkStats implements Parcelable { } /** @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public NetworkStats(Parcel parcel) { elapsedRealtime = parcel.readLong(); size = parcel.readInt(); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index fba7561434..51f09a0103 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -32,7 +32,6 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; @@ -92,18 +91,18 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public long bucketDuration; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public long bucketStart; public long activeTime; @UnsupportedAppUsage public long rxBytes; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public long rxPackets; @UnsupportedAppUsage public long txBytes; - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public long txPackets; public long operations; } @@ -135,7 +134,7 @@ public class NetworkStatsHistory implements Parcelable { recordEntireHistory(existing); } - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); @@ -221,7 +220,7 @@ public class NetworkStatsHistory implements Parcelable { return 0; } - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public int size() { return bucketCount; } @@ -259,7 +258,7 @@ public class NetworkStatsHistory implements Parcelable { * Return index of bucket that contains or is immediately before the * requested time. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public int getIndexBefore(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); if (index < 0) { @@ -287,7 +286,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index dc33cc7b61..a95ba12f65 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,7 +37,6 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; -import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; @@ -160,7 +159,7 @@ public class NetworkTemplate implements Parcelable { * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public static NetworkTemplate buildTemplateMobileWildcard() { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index a985e934ed..e7bba69dbb 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -565,7 +565,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -581,7 +581,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + @UnsupportedAppUsage public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index e9e8935a19..9484c74bcb 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,7 +25,7 @@ import android.os.Messenger; */ interface INsdManager { - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) + @UnsupportedAppUsage Messenger getMessenger(); void setEnabled(boolean enable); } From 06de3de5b496e6cf879dc1aa6ee6a5a64c2ee06d Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Tue, 27 Oct 2020 11:47:29 +0000 Subject: [PATCH 508/881] Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. This is a resubmit of ag/12929664 with some APIs excluded that caused test failures; see bugs 171886397, 171888296, 171864568. APIs excluded: Landroid/bluetooth/le/ScanRecord;->parseFromBytes([B)Landroid/bluetooth/le/ScanRecord; Landroid/os/Process;->myPpid()I Landroid/os/SharedMemory;->getFd()I Landroid/hardware/input/InputManager;->INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH:I Bug: 170729553 Test: Treehugger Change-Id: I8285daa8530260251ecad6f3f38f98e263629ca7 --- .../app/usage/NetworkStatsManager.java | 5 +-- core/java/android/net/EthernetManager.java | 17 +++++----- .../android/net/INetworkStatsService.aidl | 2 +- core/java/android/net/NetworkStats.java | 33 ++++++++++--------- .../java/android/net/NetworkStatsHistory.java | 17 +++++----- core/java/android/net/NetworkTemplate.java | 3 +- core/java/android/net/TrafficStats.java | 4 +-- core/java/android/net/nsd/INsdManager.aidl | 2 +- 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index fc8248e101..1ddfe0d247 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -34,6 +34,7 @@ import android.net.NetworkTemplate; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -129,7 +130,7 @@ public class NetworkStatsManager { /** * {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsManager(Context context) throws ServiceNotFoundException { this(context, INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); @@ -153,7 +154,7 @@ public class NetworkStatsManager { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @TestApi public void setPollForce(boolean pollForce) { if (pollForce) { diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 5860e20ad3..84a8e1c3dc 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -23,6 +23,7 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -76,7 +77,7 @@ public class EthernetManager { * @param isAvailable {@code true} if Ethernet port exists. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void onAvailabilityChanged(String iface, boolean isAvailable); } @@ -97,7 +98,7 @@ public class EthernetManager { * @return the Ethernet Configuration, contained in {@link IpConfiguration}. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public IpConfiguration getConfiguration(String iface) { try { return mService.getConfiguration(iface); @@ -110,7 +111,7 @@ public class EthernetManager { * Set Ethernet configuration. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void setConfiguration(String iface, IpConfiguration config) { try { mService.setConfiguration(iface, config); @@ -123,7 +124,7 @@ public class EthernetManager { * Indicates whether the system currently has one or more Ethernet interfaces. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable() { return getAvailableInterfaces().length > 0; } @@ -134,7 +135,7 @@ public class EthernetManager { * @param iface Ethernet interface name * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable(String iface) { try { return mService.isAvailable(iface); @@ -149,7 +150,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void addListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); @@ -168,7 +169,7 @@ public class EthernetManager { * Returns an array of available Ethernet interface names. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String[] getAvailableInterfaces() { try { return mService.getAvailableInterfaces(); @@ -183,7 +184,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void removeListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 5fa515a143..1a3dc97448 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -42,7 +42,7 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return data layer snapshot of UID network usage. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index cbee010246..d42beae601 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -219,11 +220,11 @@ public final class NetworkStats implements Parcelable { * generated. */ private long elapsedRealtime; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int size; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int capacity; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private String[] iface; @UnsupportedAppUsage private int[] uid; @@ -231,21 +232,21 @@ public final class NetworkStats implements Parcelable { private int[] set; @UnsupportedAppUsage private int[] tag; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] metered; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] roaming; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] defaultNetwork; @UnsupportedAppUsage private long[] rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] rxPackets; @UnsupportedAppUsage private long[] txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] txPackets; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] operations; /** @@ -258,7 +259,7 @@ public final class NetworkStats implements Parcelable { @SystemApi public static class Entry { /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String iface; /** @hide */ @UnsupportedAppUsage @@ -267,7 +268,7 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public int set; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int tag; /** * Note that this is only populated w/ the default value when read from /proc or written @@ -294,20 +295,20 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public long rxBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; /** @hide */ @UnsupportedAppUsage public long txBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long operations; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry() { this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); } @@ -454,7 +455,7 @@ public final class NetworkStats implements Parcelable { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStats(Parcel parcel) { elapsedRealtime = parcel.readLong(); size = parcel.readInt(); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 51f09a0103..fba7561434 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -32,6 +32,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; @@ -91,18 +92,18 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketDuration; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketStart; public long activeTime; @UnsupportedAppUsage public long rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; @UnsupportedAppUsage public long txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; public long operations; } @@ -134,7 +135,7 @@ public class NetworkStatsHistory implements Parcelable { recordEntireHistory(existing); } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); @@ -220,7 +221,7 @@ public class NetworkStatsHistory implements Parcelable { return 0; } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int size() { return bucketCount; } @@ -258,7 +259,7 @@ public class NetworkStatsHistory implements Parcelable { * Return index of bucket that contains or is immediately before the * requested time. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int getIndexBefore(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); if (index < 0) { @@ -286,7 +287,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index a95ba12f65..dc33cc7b61 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; @@ -159,7 +160,7 @@ public class NetworkTemplate implements Parcelable { * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static NetworkTemplate buildTemplateMobileWildcard() { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e7bba69dbb..a985e934ed 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -565,7 +565,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -581,7 +581,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 9484c74bcb..e9e8935a19 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,7 +25,7 @@ import android.os.Messenger; */ interface INsdManager { - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) Messenger getMessenger(); void setEnabled(boolean enable); } From e538030325954aa1ba08ba426d61d88a8b838923 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Thu, 29 Oct 2020 15:21:39 +0000 Subject: [PATCH 509/881] Restructure Module code [ com.android.tethering ] Code Migration from frameworks/base/packages/Tethering -> packages/modules/Connectivity/Tethering BUG: 167962976 Test: TH Change-Id: I2accb96abbdfa665ef34aa79e87af040226bcf32 --- .../net/util/TetheringMessageBase.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 packages/Tethering/src/android/net/util/TetheringMessageBase.java diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java deleted file mode 100644 index 29c0a817b6..0000000000 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -/** - * This class defines Message.what base addresses for various state machine. - */ -public class TetheringMessageBase { - public static final int BASE_MAIN_SM = 0; - public static final int BASE_IPSERVER = 100; - -} From 155b7dea4015b95dc2832da88e3e9a1fa84b7a17 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Thu, 29 Oct 2020 16:31:24 +0000 Subject: [PATCH 510/881] Restructure Module code [ com.android.tethering ] Code Migration from frameworks/base/packages/Tethering -> packages/modules/Connectivity/Tethering BUG: 167962976 Test: TH Merged-In: I2accb96abbdfa665ef34aa79e87af040226bcf32 Change-Id: Ide2ba760c0552e614635b3e402890b587ddc3c4c --- .../net/util/TetheringMessageBase.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 packages/Tethering/src/android/net/util/TetheringMessageBase.java diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java deleted file mode 100644 index 29c0a817b6..0000000000 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -/** - * This class defines Message.what base addresses for various state machine. - */ -public class TetheringMessageBase { - public static final int BASE_MAIN_SM = 0; - public static final int BASE_IPSERVER = 100; - -} From f8c98957b79f2bb915000c105c380d20cd6bb046 Mon Sep 17 00:00:00 2001 From: Ashwini Oruganti Date: Thu, 29 Oct 2020 11:19:36 -0700 Subject: [PATCH 511/881] Apply FLAG_IMMUTABLE to the PendingIntent in NetworkStatService.java Broadcast intents sent by AlarmManager are immutable; the system dispatches them without customization. Fixes: 171815343 Test: TH Change-Id: I35ccfc0f69fd98b5803da74d9eb12902b351acc7 --- .../core/java/com/android/server/net/NetworkStatsService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 71e7c8adc5..12c24d4186 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -552,7 +552,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}. final PendingIntent pollIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); + PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), + PendingIntent.FLAG_IMMUTABLE); final long currentRealtime = SystemClock.elapsedRealtime(); mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, From e1600e7152da3ed78d6ea93075a1bfb3765fc279 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Thu, 29 Oct 2020 16:25:34 +0000 Subject: [PATCH 512/881] Restructure Module code [ com.android.tethering ] Code Migration from frameworks/base/packages/Tethering -> packages/modules/Connectivity/Tethering BUG: 167962976 Test: TH Merged-In: Ide2ba760c0552e614635b3e402890b587ddc3c4c Change-Id: I68cc959b56d5984b038cea4c621c60f34472f34c --- .../net/util/TetheringMessageBase.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 packages/Tethering/src/android/net/util/TetheringMessageBase.java diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java deleted file mode 100644 index 29c0a817b6..0000000000 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -/** - * This class defines Message.what base addresses for various state machine. - */ -public class TetheringMessageBase { - public static final int BASE_MAIN_SM = 0; - public static final int BASE_IPSERVER = 100; - -} From 93c1ce12f3ac5880f0b2ed9764b7a9b9b0233f7f Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Thu, 29 Oct 2020 14:35:17 +0000 Subject: [PATCH 513/881] Restructure Module code [ com.android.tethering ] Code Migration from frameworks/base/packages/Tethering -> packages/modules/Connectivity/Tethering BUG: 167962976 Test: TH Merged-In: I68cc959b56d5984b038cea4c621c60f34472f34c Change-Id: Ia22c69ebff88d2d117a058e6ad22b23fa5d04fda --- .../net/util/TetheringMessageBase.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 packages/Tethering/src/android/net/util/TetheringMessageBase.java diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java deleted file mode 100644 index 29c0a817b6..0000000000 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -/** - * This class defines Message.what base addresses for various state machine. - */ -public class TetheringMessageBase { - public static final int BASE_MAIN_SM = 0; - public static final int BASE_IPSERVER = 100; - -} From 7900906a87c1df326be9c10ecabb0853e799d851 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Thu, 29 Oct 2020 13:10:51 +0000 Subject: [PATCH 514/881] Restructure Module code [ com.android.tethering ] Code Migration from frameworks/base/packages/Tethering -> packages/modules/Connectivity/Tethering BUG: 167962976 Test: m com.android.tethering + TH Merged-In: Ib4a3a7a14d7d0e544aadf1bfb21ad390f1ba76a7 Change-Id: Ifae56d991b43c02f1e3496abbafc87d1869add8a --- .../net/util/TetheringMessageBase.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 packages/Tethering/src/android/net/util/TetheringMessageBase.java diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java deleted file mode 100644 index 29c0a817b6..0000000000 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -/** - * This class defines Message.what base addresses for various state machine. - */ -public class TetheringMessageBase { - public static final int BASE_MAIN_SM = 0; - public static final int BASE_IPSERVER = 100; - -} From 48c46f29725e1522b5daee4241637c7e2d75c87c Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Thu, 29 Oct 2020 17:58:29 +0000 Subject: [PATCH 515/881] Restructure Module code [ com.android.tethering ] Code Migration from frameworks/base/packages/Tethering -> packages/modules/Connectivity/Tethering BUG: 167962976 Test: TH Merged-In: I2accb96abbdfa665ef34aa79e87af040226bcf32 Change-Id: Id7656fe7f6a6fae044dc8defd05e83d81c6b8c11 --- .../net/util/TetheringMessageBase.java | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 packages/Tethering/src/android/net/util/TetheringMessageBase.java diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java deleted file mode 100644 index 29c0a817b6..0000000000 --- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.net.util; - -/** - * This class defines Message.what base addresses for various state machine. - */ -public class TetheringMessageBase { - public static final int BASE_MAIN_SM = 0; - public static final int BASE_IPSERVER = 100; - -} From 6a224d7cfa9564115ecce0d75ef274be0b6f93ad Mon Sep 17 00:00:00 2001 From: Ashwini Oruganti Date: Fri, 30 Oct 2020 10:49:45 -0700 Subject: [PATCH 516/881] Apply FLAG_IMMUTABLE to the PendingIntent in NetworkStatService.java Broadcast intents sent by AlarmManager are immutable; the system dispatches them without customization. Fixes: 171815343 Test: TH Change-Id: I35ccfc0f69fd98b5803da74d9eb12902b351acc7 Merged-In: I35ccfc0f69fd98b5803da74d9eb12902b351acc7 --- .../core/java/com/android/server/net/NetworkStatsService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 71e7c8adc5..12c24d4186 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -552,7 +552,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}. final PendingIntent pollIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); + PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), + PendingIntent.FLAG_IMMUTABLE); final long currentRealtime = SystemClock.elapsedRealtime(); mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, From e34ebe1a097ee676fce0332a85c07de7e6efb335 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 19 Aug 2020 16:07:22 +0900 Subject: [PATCH 517/881] Move module utils to the module package. Test: FrameworksWifiTest FrameworksNetTest Change-Id: I067eeecd458c34b7f2fbfa439072682661ac750c --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 78bd4cdd4e..84f40cb4b8 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -25,7 +25,6 @@ import android.net.Uri; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; -import android.net.util.nsd.DnsSdTxtRecord; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; @@ -42,6 +41,7 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.net.module.util.DnsSdTxtRecord; import java.io.FileDescriptor; import java.io.PrintWriter; From 9627724c3b676500886d94061e6bbfbfccac29b1 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Fri, 16 Oct 2020 04:22:07 +0000 Subject: [PATCH 518/881] Allow the network stack to read network stats history Bug: 168984229 Test: testNetworkStatsProvider Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1450457 Change-Id: Ic9bd2d2d06c790a84e56ec8a6915f1faab16dda0 Merged-In: Ibb6342b0f263c874bb1f7ab4031a639778bad37e (cherry picked from commit 9010baec16faa806c2253f90225d002c4b2efb0c) --- .../java/com/android/server/net/NetworkStatsAccess.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 7c1c1c7ce4..72559b4825 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -28,6 +28,7 @@ import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; +import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; @@ -113,10 +114,11 @@ public final class NetworkStatsAccess { TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + final int appId = UserHandle.getAppId(callingUid); if (hasCarrierPrivileges || isDeviceOwner - || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) { - // Carrier-privileged apps and device owners, and the system can access data usage for - // all apps on the device. + || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { + // Carrier-privileged apps and device owners, and the system (including the + // network stack) can access data usage for all apps on the device. return NetworkStatsAccess.Level.DEVICE; } From 2650c9287d93f31bf57480679d844f194767b8d9 Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Mon, 2 Nov 2020 10:29:35 +0000 Subject: [PATCH 519/881] Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. Bug: 170729553 Test: Treehugger Merged-In: I8285daa8530260251ecad6f3f38f98e263629ca7 Change-Id: I626caf7c1fe46c5ab1f39c2895b42a34319f771a --- .../app/usage/NetworkStatsManager.java | 5 +-- core/java/android/net/EthernetManager.java | 17 +++++----- .../android/net/INetworkStatsService.aidl | 2 +- core/java/android/net/NetworkStats.java | 33 ++++++++++--------- .../java/android/net/NetworkStatsHistory.java | 17 +++++----- core/java/android/net/NetworkTemplate.java | 3 +- core/java/android/net/TrafficStats.java | 4 +-- core/java/android/net/nsd/INsdManager.aidl | 2 +- 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index fc8248e101..1ddfe0d247 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -34,6 +34,7 @@ import android.net.NetworkTemplate; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -129,7 +130,7 @@ public class NetworkStatsManager { /** * {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsManager(Context context) throws ServiceNotFoundException { this(context, INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); @@ -153,7 +154,7 @@ public class NetworkStatsManager { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @TestApi public void setPollForce(boolean pollForce) { if (pollForce) { diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 5860e20ad3..84a8e1c3dc 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -23,6 +23,7 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -76,7 +77,7 @@ public class EthernetManager { * @param isAvailable {@code true} if Ethernet port exists. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void onAvailabilityChanged(String iface, boolean isAvailable); } @@ -97,7 +98,7 @@ public class EthernetManager { * @return the Ethernet Configuration, contained in {@link IpConfiguration}. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public IpConfiguration getConfiguration(String iface) { try { return mService.getConfiguration(iface); @@ -110,7 +111,7 @@ public class EthernetManager { * Set Ethernet configuration. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void setConfiguration(String iface, IpConfiguration config) { try { mService.setConfiguration(iface, config); @@ -123,7 +124,7 @@ public class EthernetManager { * Indicates whether the system currently has one or more Ethernet interfaces. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable() { return getAvailableInterfaces().length > 0; } @@ -134,7 +135,7 @@ public class EthernetManager { * @param iface Ethernet interface name * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable(String iface) { try { return mService.isAvailable(iface); @@ -149,7 +150,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void addListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); @@ -168,7 +169,7 @@ public class EthernetManager { * Returns an array of available Ethernet interface names. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String[] getAvailableInterfaces() { try { return mService.getAvailableInterfaces(); @@ -183,7 +184,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void removeListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 5fa515a143..1a3dc97448 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -42,7 +42,7 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return data layer snapshot of UID network usage. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 34e48eb44f..cf40ce58d4 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -219,11 +220,11 @@ public final class NetworkStats implements Parcelable { * generated. */ private long elapsedRealtime; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int size; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int capacity; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private String[] iface; @UnsupportedAppUsage private int[] uid; @@ -231,21 +232,21 @@ public final class NetworkStats implements Parcelable { private int[] set; @UnsupportedAppUsage private int[] tag; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] metered; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] roaming; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] defaultNetwork; @UnsupportedAppUsage private long[] rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] rxPackets; @UnsupportedAppUsage private long[] txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] txPackets; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] operations; /** @@ -258,7 +259,7 @@ public final class NetworkStats implements Parcelable { @SystemApi public static class Entry { /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String iface; /** @hide */ @UnsupportedAppUsage @@ -267,7 +268,7 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public int set; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int tag; /** * Note that this is only populated w/ the default value when read from /proc or written @@ -294,20 +295,20 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public long rxBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; /** @hide */ @UnsupportedAppUsage public long txBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long operations; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry() { this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); } @@ -454,7 +455,7 @@ public final class NetworkStats implements Parcelable { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStats(Parcel parcel) { elapsedRealtime = parcel.readLong(); size = parcel.readInt(); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 51f09a0103..fba7561434 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -32,6 +32,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; @@ -91,18 +92,18 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketDuration; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketStart; public long activeTime; @UnsupportedAppUsage public long rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; @UnsupportedAppUsage public long txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; public long operations; } @@ -134,7 +135,7 @@ public class NetworkStatsHistory implements Parcelable { recordEntireHistory(existing); } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); @@ -220,7 +221,7 @@ public class NetworkStatsHistory implements Parcelable { return 0; } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int size() { return bucketCount; } @@ -258,7 +259,7 @@ public class NetworkStatsHistory implements Parcelable { * Return index of bucket that contains or is immediately before the * requested time. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int getIndexBefore(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); if (index < 0) { @@ -286,7 +287,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cd26079a7b..72be835a1c 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; @@ -159,7 +160,7 @@ public class NetworkTemplate implements Parcelable { * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static NetworkTemplate buildTemplateMobileWildcard() { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e7bba69dbb..a985e934ed 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -565,7 +565,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -581,7 +581,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 9484c74bcb..e9e8935a19 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,7 +25,7 @@ import android.os.Messenger; */ interface INsdManager { - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) Messenger getMessenger(); void setEnabled(boolean enable); } From 5c74a0f002352a120b38e3b241123dfbdfa27d1f Mon Sep 17 00:00:00 2001 From: Mathew Inwood Date: Wed, 4 Nov 2020 09:29:36 +0000 Subject: [PATCH 520/881] Add maxTargetSdk restriction to unused APIs. These are APIs that have @UnsupportedAppUsage but for which we don't have any evidence of them currently being used, so should be safe to remove from the unsupported list. Bug: 170729553 Test: Treehugger Merged-In: I626caf7c1fe46c5ab1f39c2895b42a34319f771a Change-Id: I54e5ecd11e76ca1de3c5893e3a98b0108e735413 --- .../app/usage/NetworkStatsManager.java | 5 +-- core/java/android/net/EthernetManager.java | 17 +++++----- .../android/net/INetworkStatsService.aidl | 2 +- core/java/android/net/NetworkStats.java | 33 ++++++++++--------- .../java/android/net/NetworkStatsHistory.java | 17 +++++----- core/java/android/net/NetworkTemplate.java | 3 +- core/java/android/net/TrafficStats.java | 4 +-- core/java/android/net/nsd/INsdManager.aidl | 2 +- 8 files changed, 44 insertions(+), 39 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index fc8248e101..1ddfe0d247 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -34,6 +34,7 @@ import android.net.NetworkTemplate; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -129,7 +130,7 @@ public class NetworkStatsManager { /** * {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsManager(Context context) throws ServiceNotFoundException { this(context, INetworkStatsService.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); @@ -153,7 +154,7 @@ public class NetworkStatsManager { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @TestApi public void setPollForce(boolean pollForce) { if (pollForce) { diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 5860e20ad3..84a8e1c3dc 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -23,6 +23,7 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.RemoteException; @@ -76,7 +77,7 @@ public class EthernetManager { * @param isAvailable {@code true} if Ethernet port exists. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void onAvailabilityChanged(String iface, boolean isAvailable); } @@ -97,7 +98,7 @@ public class EthernetManager { * @return the Ethernet Configuration, contained in {@link IpConfiguration}. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public IpConfiguration getConfiguration(String iface) { try { return mService.getConfiguration(iface); @@ -110,7 +111,7 @@ public class EthernetManager { * Set Ethernet configuration. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void setConfiguration(String iface, IpConfiguration config) { try { mService.setConfiguration(iface, config); @@ -123,7 +124,7 @@ public class EthernetManager { * Indicates whether the system currently has one or more Ethernet interfaces. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable() { return getAvailableInterfaces().length > 0; } @@ -134,7 +135,7 @@ public class EthernetManager { * @param iface Ethernet interface name * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isAvailable(String iface) { try { return mService.isAvailable(iface); @@ -149,7 +150,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void addListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); @@ -168,7 +169,7 @@ public class EthernetManager { * Returns an array of available Ethernet interface names. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String[] getAvailableInterfaces() { try { return mService.getAvailableInterfaces(); @@ -183,7 +184,7 @@ public class EthernetManager { * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void removeListener(Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 5fa515a143..1a3dc97448 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -42,7 +42,7 @@ interface INetworkStatsService { * PACKAGE_USAGE_STATS permission is always checked. If PACKAGE_USAGE_STATS is not granted * READ_NETWORK_USAGE_STATS is checked for. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage); /** Return data layer snapshot of UID network usage. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 34e48eb44f..cf40ce58d4 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -219,11 +220,11 @@ public final class NetworkStats implements Parcelable { * generated. */ private long elapsedRealtime; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int size; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int capacity; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private String[] iface; @UnsupportedAppUsage private int[] uid; @@ -231,21 +232,21 @@ public final class NetworkStats implements Parcelable { private int[] set; @UnsupportedAppUsage private int[] tag; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] metered; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] roaming; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private int[] defaultNetwork; @UnsupportedAppUsage private long[] rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] rxPackets; @UnsupportedAppUsage private long[] txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] txPackets; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) private long[] operations; /** @@ -258,7 +259,7 @@ public final class NetworkStats implements Parcelable { @SystemApi public static class Entry { /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public String iface; /** @hide */ @UnsupportedAppUsage @@ -267,7 +268,7 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public int set; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int tag; /** * Note that this is only populated w/ the default value when read from /proc or written @@ -294,20 +295,20 @@ public final class NetworkStats implements Parcelable { @UnsupportedAppUsage public long rxBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; /** @hide */ @UnsupportedAppUsage public long txBytes; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long operations; /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry() { this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L); } @@ -454,7 +455,7 @@ public final class NetworkStats implements Parcelable { } /** @hide */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStats(Parcel parcel) { elapsedRealtime = parcel.readLong(); size = parcel.readInt(); diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 51f09a0103..fba7561434 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -32,6 +32,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; @@ -91,18 +92,18 @@ public class NetworkStatsHistory implements Parcelable { public static class Entry { public static final long UNKNOWN = -1; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketDuration; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketStart; public long activeTime; @UnsupportedAppUsage public long rxBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; @UnsupportedAppUsage public long txBytes; - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; public long operations; } @@ -134,7 +135,7 @@ public class NetworkStatsHistory implements Parcelable { recordEntireHistory(existing); } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); bucketStart = readLongArray(in); @@ -220,7 +221,7 @@ public class NetworkStatsHistory implements Parcelable { return 0; } - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int size() { return bucketCount; } @@ -258,7 +259,7 @@ public class NetworkStatsHistory implements Parcelable { * Return index of bucket that contains or is immediately before the * requested time. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int getIndexBefore(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); if (index < 0) { @@ -286,7 +287,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry getValues(int i, Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.bucketStart = bucketStart[i]; diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index cd26079a7b..72be835a1c 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -37,6 +37,7 @@ import static android.net.wifi.WifiInfo.sanitizeSsid; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; @@ -159,7 +160,7 @@ public class NetworkTemplate implements Parcelable { * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static NetworkTemplate buildTemplateMobileWildcard() { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null); } diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e7bba69dbb..a985e934ed 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -565,7 +565,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpRxPackets() { long total = 0; for (String iface : getMobileIfaces()) { @@ -581,7 +581,7 @@ public class TrafficStats { } /** {@hide} */ - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static long getMobileTcpTxPackets() { long total = 0; for (String iface : getMobileIfaces()) { diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index 9484c74bcb..e9e8935a19 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -25,7 +25,7 @@ import android.os.Messenger; */ interface INsdManager { - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) Messenger getMessenger(); void setEnabled(boolean enable); } From 1dbd5ded7e005e4e884d6e0ccaf3aacb326a6995 Mon Sep 17 00:00:00 2001 From: Eran Messeri Date: Tue, 3 Nov 2020 16:49:30 +0000 Subject: [PATCH 521/881] DO NOT MERGE: Introduce DPMS shim for active DO/PO check Introduce a shim into DevicePolicyManagerInternal & DevicePolicyManagerService so that NetworkStatsAccessTest would not diverge from internal development branches. The DevicePolicyManagerService refactoring on the internal branch removed isActiveAdminWithPolicy in favour of isActiveDeviceOwner and isActiveProfileOwner. These methods are being made available in AOSP for NetworkStatsAccessTest. Bug: 170459325 Test: atest NetworkStatsAccessTest Change-Id: Ic7e0898989fb8222aaba2b35436765c04eb3250c --- .../java/com/android/server/net/NetworkStatsAccess.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 72559b4825..ddc5ef2000 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -24,7 +24,6 @@ import static android.net.TrafficStats.UID_TETHERING; import android.Manifest; import android.annotation.IntDef; import android.app.AppOpsManager; -import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; @@ -112,8 +111,7 @@ public final class NetworkStatsAccess { boolean hasCarrierPrivileges = tm != null && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; - boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, - DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); final int appId = UserHandle.getAppId(callingUid); if (hasCarrierPrivileges || isDeviceOwner || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { @@ -128,8 +126,9 @@ public final class NetworkStatsAccess { return NetworkStatsAccess.Level.DEVICESUMMARY; } - boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, - DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode. + boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid) + || dpmi.isActiveDeviceOwner(callingUid)); if (isProfileOwner) { // Apps with the AppOps permission, profile owners, and apps with the privileged // permission can access data usage for all apps in this user/profile. From 1694538a2059788085f233cc5ba3a49d3bfa7714 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 6 Oct 2020 16:04:31 +0800 Subject: [PATCH 522/881] Remove unused getTetherStats Before Android R, getTetherStats were used to collect tethering iface stats of all clients who extends ITetheringStatsProvider, which typically contains NetdTetheringStatsProvider and OffloadController. However, this always returns 0 since Android R, because: 1. OffloadController implemented NetworkStatsProvider and no longer reports stats through getTetherStats. 2. NetdTetheringStatsProvider always return 0 by design since non-offloaded iface tethering stats are already included in native iface stats. This change is a no-op refactoring to remove unused getTetherStats and update test which is not pratical. Fix for offloaded tethering stats will be in follow-up CLs. Test: atest FrameworksNetTests TetheringTests Bug: 162292214 Change-Id: Icd0717c5c2807ae3bd98626b897e4b148f142815 --- .../server/net/NetworkStatsService.java | 63 +++---------------- 1 file changed, 10 insertions(+), 53 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 12c24d4186..96e3c5163f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1083,13 +1083,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (nativeIfaceStats == -1) { return nativeIfaceStats; } else { - // When tethering offload is in use, nativeIfaceStats does not contain usage from - // offload, add it back here. - // When tethering offload is not in use, nativeIfaceStats contains tethering usage. - // this does not cause double-counting of tethering traffic, because - // NetdTetheringStatsProvider returns zero NetworkStats - // when called with STATS_PER_IFACE. - return nativeIfaceStats + getTetherStats(iface, type); + // TODO: When tethering offload is in use, nativeIfaceStats does not contain usage from + // offload, add it back here. + return nativeIfaceStats; } } @@ -1100,42 +1096,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return nativeTotalStats; } else { // Refer to comment in getIfaceStats - return nativeTotalStats + getTetherStats(IFACE_ALL, type); - } - } - - private long getTetherStats(String iface, int type) { - final NetworkStats tetherSnapshot; - final long token = Binder.clearCallingIdentity(); - try { - tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); - } catch (RemoteException e) { - Slog.w(TAG, "Error get TetherStats: " + e); - return 0; - } finally { - Binder.restoreCallingIdentity(token); - } - HashSet limitIfaces; - if (iface == IFACE_ALL) { - limitIfaces = null; - } else { - limitIfaces = new HashSet(); - limitIfaces.add(iface); - } - NetworkStats.Entry entry = tetherSnapshot.getTotal(null, limitIfaces); - if (LOGD) Slog.d(TAG, "TetherStats: iface=" + iface + " type=" + type + - " entry=" + entry); - switch (type) { - case 0: // TYPE_RX_BYTES - return entry.rxBytes; - case 1: // TYPE_RX_PACKETS - return entry.rxPackets; - case 2: // TYPE_TX_BYTES - return entry.txBytes; - case 3: // TYPE_TX_PACKETS - return entry.txPackets; - default: - return 0; + return nativeTotalStats; } } @@ -1429,14 +1390,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats devSnapshot = readNetworkStatsSummaryDev(); Trace.traceEnd(TRACE_TAG_NETWORK); - // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats - // providers that isn't already counted by dev and XT stats. - Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotTether"); - final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); - Trace.traceEnd(TRACE_TAG_NETWORK); - xtSnapshot.combineAllValues(tetherSnapshot); - devSnapshot.combineAllValues(tetherSnapshot); - // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data // from stats providers that isn't already counted by dev and XT stats. Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider"); @@ -1931,9 +1884,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Return snapshot of current tethering statistics. Will return empty - * {@link NetworkStats} if any problems are encountered. + * Return snapshot of current non-offloaded tethering statistics. Will return empty + * {@link NetworkStats} if any problems are encountered, or queried by {@code STATS_PER_IFACE} + * since it is already included by {@link #nativeGetIfaceStat}. + * See {@code OffloadTetheringStatsProvider} for offloaded tethering stats. */ + // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded + // tethering stats. private NetworkStats getNetworkStatsTethering(int how) throws RemoteException { try { return mNetworkManager.getNetworkStatsTethering(how); From 3841fbeecabca2c7922b41990479c5f5189d0d66 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 6 Oct 2020 11:59:56 +0800 Subject: [PATCH 523/881] Return offloaded traffic when querying from TrafficStats API TrafficStats API are being used for querying realtime network statistics for years. However, on certain devices, some network traffic are produced by hardware components and not be able to seen by kernel counters. Thus, include statistics for those missing network traffic is necessary. Note that the included statistics might be stale since polling newest stats from hardware might impact system health and not suitable for TrafficStats API use cases. Test: atest FrameworksNetTests TetheringTests Bug: 16229221 Change-Id: I6741c41cb5145ca8748f9b083b9c15e7e2735681 --- core/java/android/net/TrafficStats.java | 20 +++-- .../server/net/NetworkStatsService.java | 87 +++++++++++++------ 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index e7bba69dbb..7a79ceb14a 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -976,11 +976,17 @@ public class TrafficStats { } } - // NOTE: keep these in sync with android_net_TrafficStats.cpp - private static final int TYPE_RX_BYTES = 0; - private static final int TYPE_RX_PACKETS = 1; - private static final int TYPE_TX_BYTES = 2; - private static final int TYPE_TX_PACKETS = 3; - private static final int TYPE_TCP_RX_PACKETS = 4; - private static final int TYPE_TCP_TX_PACKETS = 5; + // NOTE: keep these in sync with {@code com_android_server_net_NetworkStatsService.cpp}. + /** {@hide} */ + public static final int TYPE_RX_BYTES = 0; + /** {@hide} */ + public static final int TYPE_RX_PACKETS = 1; + /** {@hide} */ + public static final int TYPE_TX_BYTES = 2; + /** {@hide} */ + public static final int TYPE_TX_PACKETS = 3; + /** {@hide} */ + public static final int TYPE_TCP_RX_PACKETS = 4; + /** {@hide} */ + public static final int TYPE_TCP_TX_PACKETS = 5; } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 96e3c5163f..bfd0211f18 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1083,9 +1083,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (nativeIfaceStats == -1) { return nativeIfaceStats; } else { - // TODO: When tethering offload is in use, nativeIfaceStats does not contain usage from - // offload, add it back here. - return nativeIfaceStats; + // When tethering offload is in use, nativeIfaceStats does not contain usage from + // offload, add it back here. Note that the included statistics might be stale + // since polling newest stats from hardware might impact system health and not + // suitable for TrafficStats API use cases. + return nativeIfaceStats + getProviderIfaceStats(iface, type); } } @@ -1096,7 +1098,31 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return nativeTotalStats; } else { // Refer to comment in getIfaceStats - return nativeTotalStats; + return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type); + } + } + + private long getProviderIfaceStats(@Nullable String iface, int type) { + final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE); + final HashSet limitIfaces; + if (iface == IFACE_ALL) { + limitIfaces = null; + } else { + limitIfaces = new HashSet<>(); + limitIfaces.add(iface); + } + final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces); + switch (type) { + case TrafficStats.TYPE_RX_BYTES: + return entry.rxBytes; + case TrafficStats.TYPE_RX_PACKETS: + return entry.rxPackets; + case TrafficStats.TYPE_TX_BYTES: + return entry.txBytes; + case TrafficStats.TYPE_TX_PACKETS: + return entry.txPackets; + default: + return 0; } } @@ -1464,29 +1490,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0; final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; - // Request asynchronous stats update from all providers for next poll. And wait a bit of - // time to allow providers report-in given that normally binder call should be fast. Note - // that size of list might be changed because addition/removing at the same time. For - // addition, the stats of the missed provider can only be collected in next poll; - // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS - // once that happened. - // TODO: request with a valid token. - Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); - final int registeredCallbackCount = mStatsProviderCbList.size(); - mStatsProviderSem.drainPermits(); - invokeForAllStatsProviderCallbacks( - (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); - try { - mStatsProviderSem.tryAcquire(registeredCallbackCount, - MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - // Strictly speaking it's possible a provider happened to deliver between the timeout - // and the log, and that doesn't matter too much as this is just a debug log. - Log.d(TAG, "requestStatsUpdate - providers responded " - + mStatsProviderSem.availablePermits() - + "/" + registeredCallbackCount + " : " + e); - } - Trace.traceEnd(TRACE_TAG_NETWORK); + performPollFromProvidersLocked(); // TODO: consider marking "untrusted" times in historical stats final long currentTime = mClock.millis(); @@ -1531,6 +1535,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Trace.traceEnd(TRACE_TAG_NETWORK); } + @GuardedBy("mStatsLock") + private void performPollFromProvidersLocked() { + // Request asynchronous stats update from all providers for next poll. And wait a bit of + // time to allow providers report-in given that normally binder call should be fast. Note + // that size of list might be changed because addition/removing at the same time. For + // addition, the stats of the missed provider can only be collected in next poll; + // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS + // once that happened. + // TODO: request with a valid token. + Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); + final int registeredCallbackCount = mStatsProviderCbList.size(); + mStatsProviderSem.drainPermits(); + invokeForAllStatsProviderCallbacks( + (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); + try { + mStatsProviderSem.tryAcquire(registeredCallbackCount, + MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + // Strictly speaking it's possible a provider happened to deliver between the timeout + // and the log, and that doesn't matter too much as this is just a debug log. + Log.d(TAG, "requestStatsUpdate - providers responded " + + mStatsProviderSem.availablePermits() + + "/" + registeredCallbackCount + " : " + e); + } + Trace.traceEnd(TRACE_TAG_NETWORK); + } + /** * Sample recent statistics summary into {@link EventLog}. */ @@ -2183,6 +2214,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + // TODO: Remove unused definitions after removing JNI that fills these variables. + // See {@code com_android_server_net_NetworkStatsService.cpp}. private static int TYPE_RX_BYTES; private static int TYPE_RX_PACKETS; private static int TYPE_TX_BYTES; From bc955da83fc8a054d12f52c2ef4a191cfdc5ca37 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 6 Nov 2020 19:19:31 +0800 Subject: [PATCH 524/881] Remove unused variables From aosp/537809, variables that used to fetch realtime stats are defined in NetworkStatsService. These varialbles are filled by JNI in boot up stage in order to keep definitions sync with native layer. However, there is still a copy in TrafficStats.java, and this copy cannot be filled in boot-up stage since it is in app process. Besides, making a binder call to fetch these constants from service is considered an overkill. Thus, since there is no caller to these variables and callers should use definitions in TrafficStats, remove these variables. Test: atest FrameworksNetTests Bug: 16229221 Change-Id: I6a48d4dbb1b824cfc6c4a47395b2a76aa28cf5c9 --- .../android/server/net/NetworkStatsService.java | 9 --------- ...com_android_server_net_NetworkStatsService.cpp | 15 --------------- 2 files changed, 24 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index bfd0211f18..81a6641de8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -2214,15 +2214,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - // TODO: Remove unused definitions after removing JNI that fills these variables. - // See {@code com_android_server_net_NetworkStatsService.cpp}. - private static int TYPE_RX_BYTES; - private static int TYPE_RX_PACKETS; - private static int TYPE_TX_BYTES; - private static int TYPE_TX_PACKETS; - private static int TYPE_TCP_RX_PACKETS; - private static int TYPE_TCP_TX_PACKETS; - private static native long nativeGetTotalStat(int type, boolean useBpfStats); private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats); private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats); diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 0275f3ea32..10b248a70e 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -215,21 +215,6 @@ static const JNINativeMethod gMethods[] = { }; int register_android_server_net_NetworkStatsService(JNIEnv* env) { - jclass netStatsService = env->FindClass("com/android/server/net/NetworkStatsService"); - jfieldID rxBytesId = env->GetStaticFieldID(netStatsService, "TYPE_RX_BYTES", "I"); - jfieldID rxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_RX_PACKETS", "I"); - jfieldID txBytesId = env->GetStaticFieldID(netStatsService, "TYPE_TX_BYTES", "I"); - jfieldID txPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TX_PACKETS", "I"); - jfieldID tcpRxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_RX_PACKETS", "I"); - jfieldID tcpTxPacketsId = env->GetStaticFieldID(netStatsService, "TYPE_TCP_TX_PACKETS", "I"); - - env->SetStaticIntField(netStatsService, rxBytesId, RX_BYTES); - env->SetStaticIntField(netStatsService, rxPacketsId, RX_PACKETS); - env->SetStaticIntField(netStatsService, txBytesId, TX_BYTES); - env->SetStaticIntField(netStatsService, txPacketsId, TX_PACKETS); - env->SetStaticIntField(netStatsService, tcpRxPacketsId, TCP_RX_PACKETS); - env->SetStaticIntField(netStatsService, tcpTxPacketsId, TCP_TX_PACKETS); - return jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsService", gMethods, NELEM(gMethods)); } From 6b2f5bb979dfff11e56cd38ddb85495f92581db1 Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Thu, 12 Nov 2020 18:26:09 -0800 Subject: [PATCH 525/881] Remove legacy style metalava suppression @SuppressLint("Doclava125") is a legacy way of suppressing RequiresPermission check. Updating to the new style of suppression so metalava no longer has to support the legacy mode. sed -i "s/@SuppressLint(\"Doclava125/@SuppressLint(\"RequiresPermission/" \ core/java/android/app/admin/DevicePolicyManager.java \ core/java/android/hardware/hdmi/HdmiControlManager.java \ core/java/android/hardware/location/ContextHubManager.java \ core/java/android/hardware/usb/UsbDeviceConnection.java \ core/java/android/net/TrafficStats.java \ core/java/android/os/RecoverySystem.java \ core/java/android/os/storage/StorageManager.java \ core/java/android/service/persistentdata/PersistentDataBlockManager.java \ location/java/android/location/LocationManager.java \ media/java/android/media/AudioManager.java \ telecomm/java/android/telecom/TelecomManager.java \ telephony/java/android/telephony/CarrierConfigManager.java \ telephony/java/android/telephony/TelephonyManager.java \ wifi/java/android/net/wifi/RttManager.java \ wifi/java/android/net/wifi/WifiScanner.java Test: make Exempt-From-Owner-Approval: No-op change Change-Id: I6d5df95cfca2950ea86872d2f0afc1ba828841dc --- core/java/android/net/TrafficStats.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 7376830505..4e019cf073 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -301,7 +301,7 @@ public class TrafficStats { * Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. */ - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public static void setThreadStatsUid(int uid) { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); } @@ -339,7 +339,7 @@ public class TrafficStats { * * @see #setThreadStatsUid(int) */ - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public static void clearThreadStatsUid() { NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); } From 0caeaa3ba226793d03b273d3695e0dc0e00eccff Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Thu, 12 Nov 2020 18:29:11 -0800 Subject: [PATCH 526/881] Remove legacy style metalava suppression @SuppressLint("Doclava125") is a legacy way of suppressing RequiresPermission check. Updating to the new style of suppression so metalava no longer has to support the legacy mode. sed -i "s/@SuppressLint(\"Doclava125/@SuppressLint(\"RequiresPermission/" \ core/java/android/app/admin/DevicePolicyManager.java \ core/java/android/hardware/hdmi/HdmiControlManager.java \ core/java/android/hardware/location/ContextHubManager.java \ core/java/android/hardware/usb/UsbDeviceConnection.java \ core/java/android/net/TrafficStats.java \ core/java/android/os/RecoverySystem.java \ core/java/android/os/storage/StorageManager.java \ core/java/android/service/persistentdata/PersistentDataBlockManager.java \ location/java/android/location/LocationManager.java \ media/java/android/media/AudioManager.java \ telecomm/java/android/telecom/TelecomManager.java \ telephony/java/android/telephony/CarrierConfigManager.java \ telephony/java/android/telephony/TelephonyManager.java \ wifi/java/android/net/wifi/RttManager.java \ wifi/java/android/net/wifi/WifiScanner.java Test: make Exempt-From-Owner-Approval: No-op change Merged-In: I6d5df95cfca2950ea86872d2f0afc1ba828841dc Change-Id: I6d5df95cfca2950ea86872d2f0afc1ba828841dc --- core/java/android/net/TrafficStats.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 7376830505..4e019cf073 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -301,7 +301,7 @@ public class TrafficStats { * Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. */ - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public static void setThreadStatsUid(int uid) { NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); } @@ -339,7 +339,7 @@ public class TrafficStats { * * @see #setThreadStatsUid(int) */ - @SuppressLint("Doclava125") + @SuppressLint("RequiresPermission") public static void clearThreadStatsUid() { NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); } From 01f60b234e90e1c0d8e694faa8c08f880228eadc Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 29 Sep 2020 14:19:24 +0800 Subject: [PATCH 527/881] Expose getTx/RxBytes in TrafficStats Test: atest FrameworksNetTests TrafficStatsTest atest android.net.cts android.net.wifi.cts Bug: 164965653 Change-Id: I17b9d0bc2404c5727d4c4530ad941439b7b71a54 --- core/java/android/net/TrafficStats.java | 60 ++++++++++++++++++++----- 1 file changed, 50 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 4e019cf073..fa650617f3 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -597,10 +597,17 @@ public class TrafficStats { } /** - * Return the number of packets transmitted on the specified interface since - * device boot. Statistics are measured at the network layer, so both TCP and + * Return the number of packets transmitted on the specified interface since the interface + * was created. Statistics are measured at the network layer, so both TCP and * UDP usage are included. * + * Note that the returned values are partial statistics that do not count data from several + * sources and do not apply several adjustments that are necessary for correctness, such + * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to + * determine whether traffic is being transferred on the specific interface but are not a + * substitute for the more accurate statistics provided by the {@link NetworkStatsManager} + * APIs. + * * @param iface The name of the interface. * @return The number of transmitted packets. */ @@ -613,10 +620,17 @@ public class TrafficStats { } /** - * Return the number of packets received on the specified interface since - * device boot. Statistics are measured at the network layer, so both TCP + * Return the number of packets received on the specified interface since the interface was + * created. Statistics are measured at the network layer, so both TCP * and UDP usage are included. * + * Note that the returned values are partial statistics that do not count data from several + * sources and do not apply several adjustments that are necessary for correctness, such + * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to + * determine whether traffic is being transferred on the specific interface but are not a + * substitute for the more accurate statistics provided by the {@link NetworkStatsManager} + * APIs. + * * @param iface The name of the interface. * @return The number of received packets. */ @@ -628,9 +642,22 @@ public class TrafficStats { } } - /** {@hide} */ - @UnsupportedAppUsage - public static long getTxBytes(String iface) { + /** + * Return the number of bytes transmitted on the specified interface since the interface + * was created. Statistics are measured at the network layer, so both TCP and + * UDP usage are included. + * + * Note that the returned values are partial statistics that do not count data from several + * sources and do not apply several adjustments that are necessary for correctness, such + * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to + * determine whether traffic is being transferred on the specific interface but are not a + * substitute for the more accurate statistics provided by the {@link NetworkStatsManager} + * APIs. + * + * @param iface The name of the interface. + * @return The number of transmitted bytes. + */ + public static long getTxBytes(@NonNull String iface) { try { return getStatsService().getIfaceStats(iface, TYPE_TX_BYTES); } catch (RemoteException e) { @@ -638,9 +665,22 @@ public class TrafficStats { } } - /** {@hide} */ - @UnsupportedAppUsage - public static long getRxBytes(String iface) { + /** + * Return the number of bytes received on the specified interface since the interface + * was created. Statistics are measured at the network layer, so both TCP + * and UDP usage are included. + * + * Note that the returned values are partial statistics that do not count data from several + * sources and do not apply several adjustments that are necessary for correctness, such + * as adjusting for VPN apps, IPv6-in-IPv4 translation, etc. These values can be used to + * determine whether traffic is being transferred on the specific interface but are not a + * substitute for the more accurate statistics provided by the {@link NetworkStatsManager} + * APIs. + * + * @param iface The name of the interface. + * @return The number of received bytes. + */ + public static long getRxBytes(@NonNull String iface) { try { return getStatsService().getIfaceStats(iface, TYPE_RX_BYTES); } catch (RemoteException e) { From 00cc9a265bc10cb220d451df269f69b04abcf074 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 19 Aug 2020 16:07:22 +0900 Subject: [PATCH 528/881] Move module utils to the module package. Test: FrameworksWifiTest FrameworksNetTest Change-Id: I067eeecd458c34b7f2fbfa439072682661ac750c Merged-In: I067eeecd458c34b7f2fbfa439072682661ac750c --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 4a1820a8e5..d907505481 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -25,7 +25,6 @@ import android.net.Uri; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; -import android.net.util.nsd.DnsSdTxtRecord; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; @@ -42,6 +41,7 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.net.module.util.DnsSdTxtRecord; import java.io.FileDescriptor; import java.io.PrintWriter; From 9768bc681f16d532d884ef9fb60cb14737fb9448 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 30 Nov 2020 16:47:34 +0900 Subject: [PATCH 529/881] Remove NATT keepalive from IpSecTransform The code is unused, and based on ConnectivityManager#startNattKeepalive, which is deprecated. Bug: 174436414 Test: atest FrameworksNetTests Change-Id: I08c6c1baec668a304d971bb6f2328891a5611e6a --- core/java/android/net/IpSecTransform.java | 104 ---------------------- 1 file changed, 104 deletions(-) diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index 44a0a4f3e1..aa7811a3a1 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -17,8 +17,6 @@ package android.net; import static android.net.IpSecManager.INVALID_RESOURCE_ID; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresFeature; @@ -27,7 +25,6 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; -import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -181,7 +178,6 @@ public final class IpSecTransform implements AutoCloseable { try { IIpSecService svc = getIpSecService(); svc.deleteTransform(mResourceId); - stopNattKeepalive(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } catch (Exception e) { @@ -212,36 +208,6 @@ public final class IpSecTransform implements AutoCloseable { private int mResourceId; private final Context mContext; private final CloseGuard mCloseGuard = CloseGuard.get(); - private ConnectivityManager.PacketKeepalive mKeepalive; - private Handler mCallbackHandler; - private final ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback = - new ConnectivityManager.PacketKeepaliveCallback() { - - @Override - public void onStarted() { - synchronized (this) { - mCallbackHandler.post(() -> mUserKeepaliveCallback.onStarted()); - } - } - - @Override - public void onStopped() { - synchronized (this) { - mKeepalive = null; - mCallbackHandler.post(() -> mUserKeepaliveCallback.onStopped()); - } - } - - @Override - public void onError(int error) { - synchronized (this) { - mKeepalive = null; - mCallbackHandler.post(() -> mUserKeepaliveCallback.onError(error)); - } - } - }; - - private NattKeepaliveCallback mUserKeepaliveCallback; /** @hide */ @VisibleForTesting @@ -273,76 +239,6 @@ public final class IpSecTransform implements AutoCloseable { public void onError(int error) {} } - /** - * Start a NAT-T keepalive session for the current transform. - * - * For a transform that is using UDP encapsulated IPv4, NAT-T offloading provides - * a power efficient mechanism of sending NAT-T packets at a specified interval. - * - * @param userCallback a {@link #NattKeepaliveCallback} to receive asynchronous status - * information about the requested NAT-T keepalive session. - * @param intervalSeconds the interval between NAT-T keepalives being sent. The - * the allowed range is between 20 and 3600 seconds. - * @param handler a handler on which to post callbacks when received. - * - * @hide - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, - android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD - }) - public void startNattKeepalive(@NonNull NattKeepaliveCallback userCallback, - int intervalSeconds, @NonNull Handler handler) throws IOException { - checkNotNull(userCallback); - if (intervalSeconds < 20 || intervalSeconds > 3600) { - throw new IllegalArgumentException("Invalid NAT-T keepalive interval"); - } - checkNotNull(handler); - if (mResourceId == INVALID_RESOURCE_ID) { - throw new IllegalStateException( - "Packet keepalive cannot be started for an inactive transform"); - } - - synchronized (mKeepaliveCallback) { - if (mKeepaliveCallback != null) { - throw new IllegalStateException("Keepalive already active"); - } - - mUserKeepaliveCallback = userCallback; - ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - mKeepalive = cm.startNattKeepalive( - mConfig.getNetwork(), intervalSeconds, mKeepaliveCallback, - NetworkUtils.numericToInetAddress(mConfig.getSourceAddress()), - 4500, // FIXME urgently, we need to get the port number from the Encap socket - NetworkUtils.numericToInetAddress(mConfig.getDestinationAddress())); - mCallbackHandler = handler; - } - } - - /** - * Stop an ongoing NAT-T keepalive session. - * - * Calling this API will request that an ongoing NAT-T keepalive session be terminated. - * If this API is not called when a Transform is closed, the underlying NAT-T session will - * be terminated automatically. - * - * @hide - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.MANAGE_IPSEC_TUNNELS, - android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD - }) - public void stopNattKeepalive() { - synchronized (mKeepaliveCallback) { - if (mKeepalive == null) { - Log.e(TAG, "No active keepalive to stop"); - return; - } - mKeepalive.stop(); - } - } - /** This class is used to build {@link IpSecTransform} objects. */ public static class Builder { private Context mContext; From 60dcea8f1e8799c9c17efbf30d2fe219530abed7 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 30 Nov 2020 15:47:53 +0900 Subject: [PATCH 530/881] Remove hidden API usage in metrics toString Remove usage of hidden NetworkType, transport APIs in toString() implementations of metrics and data usage classes. The toString implementations can log the transports or network type as hex or raw indices. While slightly less readable, the metrics classes and network type APIs are deprecated. Bug: 174436414 Test: m Change-Id: I79239a540b66dadd3bbe0a997960530878331358 --- core/java/android/net/NetworkIdentity.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 0948a4da1a..efbfbf93f9 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -17,7 +17,6 @@ package android.net; import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeMobile; import android.content.Context; @@ -84,7 +83,7 @@ public class NetworkIdentity implements Comparable { @Override public String toString() { final StringBuilder builder = new StringBuilder("{"); - builder.append("type=").append(getNetworkTypeName(mType)); + builder.append("type=").append(mType); builder.append(", subType="); if (mSubType == SUBTYPE_COMBINED) { builder.append("COMBINED"); From 8ea7ad3d7b5f20c0e67248ac3477c3b2473723ed Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 30 Nov 2020 15:52:46 +0900 Subject: [PATCH 531/881] Set NetworkIdentity subscriberId on all networks Instead of setting NetworkIdentity.subscriberId only on telephony networks, set it when provided on any network. At the moment only telephony is expected to have a subscriberId in its NetworkState anyway, and while there are plans for other network agents (wifi) to have a subscriberId, it should also be set in that case. This allows NetworkIdentity to stop depending on hidden network type APIs to determine if the network is mobile. Bug: 174436414 Test: atest FrameworksNetTests Change-Id: I4f09987f8737d1801342eb5d6d7c2b9968b466b0 --- core/java/android/net/NetworkIdentity.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index efbfbf93f9..a0dc72d4ad 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -17,7 +17,6 @@ package android.net; import static android.net.ConnectivityManager.TYPE_WIFI; -import static android.net.ConnectivityManager.isNetworkTypeMobile; import android.content.Context; import android.net.wifi.WifiInfo; @@ -25,7 +24,6 @@ import android.net.wifi.WifiManager; import android.os.Build; import android.service.NetworkIdentityProto; import android.telephony.Annotation.NetworkType; -import android.util.Slog; import android.util.proto.ProtoOutputStream; import java.util.Objects; @@ -193,18 +191,9 @@ public class NetworkIdentity implements Comparable { boolean metered = !state.networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - if (isNetworkTypeMobile(type)) { - if (state.subscriberId == null) { - if (state.networkInfo.getState() != NetworkInfo.State.DISCONNECTED && - state.networkInfo.getState() != NetworkInfo.State.UNKNOWN) { - Slog.w(TAG, "Active mobile network without subscriber! ni = " - + state.networkInfo); - } - } + subscriberId = state.subscriberId; - subscriberId = state.subscriberId; - - } else if (type == TYPE_WIFI) { + if (type == TYPE_WIFI) { if (state.networkId != null) { networkId = state.networkId; } else { From 7ff5b025cdac39824932c6940dd1799bf62dcb8a Mon Sep 17 00:00:00 2001 From: Serik Beketayev Date: Sun, 6 Dec 2020 22:31:23 -0800 Subject: [PATCH 532/881] [Mainline Migration] Migrate NetworkUtils Migrating makeStrings(), numericToInetAddress() APIs Bug: 173089079 Test: atest FrameworksNetTests Change-Id: Ie914fd41bc3ce16d07f5d2768b89ce805b9245a9 --- .../java/com/android/server/IpSecService.java | 6 +++--- .../com/android/server/net/IpConfigStore.java | 21 +++++++++++-------- .../android/server/net/IpConfigStoreTest.java | 6 +++--- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index b2f0c8376d..f648c3e146 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -31,6 +31,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IIpSecService; import android.net.INetd; +import android.net.InetAddresses; import android.net.IpSecAlgorithm; import android.net.IpSecConfig; import android.net.IpSecManager; @@ -41,7 +42,6 @@ import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; import android.net.Network; -import android.net.NetworkUtils; import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; @@ -1083,7 +1083,7 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Unspecified address"); } - InetAddress checkAddr = NetworkUtils.numericToInetAddress(inetAddress); + InetAddress checkAddr = InetAddresses.parseNumericAddress(inetAddress); if (checkAddr.isAnyLocalAddress()) { throw new IllegalArgumentException("Inappropriate wildcard address: " + inetAddress); @@ -1467,7 +1467,7 @@ public class IpSecService extends IIpSecService.Stub { private int getFamily(String inetAddress) { int family = AF_UNSPEC; - InetAddress checkAddress = NetworkUtils.numericToInetAddress(inetAddress); + InetAddress checkAddress = InetAddresses.parseNumericAddress(inetAddress); if (checkAddress instanceof Inet4Address) { family = AF_INET; } else if (checkAddress instanceof Inet6Address) { diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index f0bf5c0975..9c5abd4706 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -16,11 +16,11 @@ package com.android.server.net; +import android.net.InetAddresses; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; -import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.StaticIpConfiguration; @@ -284,8 +284,10 @@ public class IpConfigStore { } else if (key.equals(IP_ASSIGNMENT_KEY)) { ipAssignment = IpAssignment.valueOf(in.readUTF()); } else if (key.equals(LINK_ADDRESS_KEY)) { - LinkAddress linkAddr = new LinkAddress( - NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt()); + LinkAddress linkAddr = + new LinkAddress( + InetAddresses.parseNumericAddress(in.readUTF()), + in.readInt()); if (linkAddr.getAddress() instanceof Inet4Address && staticIpConfiguration.ipAddress == null) { staticIpConfiguration.ipAddress = linkAddr; @@ -297,7 +299,7 @@ public class IpConfigStore { InetAddress gateway = null; if (version == 1) { // only supported default gateways - leave the dest/prefix empty - gateway = NetworkUtils.numericToInetAddress(in.readUTF()); + gateway = InetAddresses.parseNumericAddress(in.readUTF()); if (staticIpConfiguration.gateway == null) { staticIpConfiguration.gateway = gateway; } else { @@ -305,12 +307,13 @@ public class IpConfigStore { } } else { if (in.readInt() == 1) { - dest = new LinkAddress( - NetworkUtils.numericToInetAddress(in.readUTF()), - in.readInt()); + dest = + new LinkAddress( + InetAddresses.parseNumericAddress(in.readUTF()), + in.readInt()); } if (in.readInt() == 1) { - gateway = NetworkUtils.numericToInetAddress(in.readUTF()); + gateway = InetAddresses.parseNumericAddress(in.readUTF()); } RouteInfo route = new RouteInfo(dest, gateway); if (route.isIPv4Default() && @@ -322,7 +325,7 @@ public class IpConfigStore { } } else if (key.equals(DNS_KEY)) { staticIpConfiguration.dnsServers.add( - NetworkUtils.numericToInetAddress(in.readUTF())); + InetAddresses.parseNumericAddress(in.readUTF())); } else if (key.equals(PROXY_SETTINGS_KEY)) { proxySettings = ProxySettings.valueOf(in.readUTF()); } else if (key.equals(PROXY_HOST_KEY)) { diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java index 7767a2810a..9d300a6113 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -20,11 +20,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import android.net.InetAddresses; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; -import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; import android.util.ArrayMap; @@ -79,8 +79,8 @@ public class IpConfigStoreTest { StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1); - staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_1)); - staticIpConfiguration.dnsServers.add(NetworkUtils.numericToInetAddress(DNS_IP_ADDR_2)); + staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); + staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2"); From 6f31ece763d4fda9b3b15651f3d3cf8ede1c3f4e Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 2 Dec 2020 12:50:18 +0900 Subject: [PATCH 533/881] Split NetworkUtils and NetworkUtilsInternal NetworkUtils is planned to move to a dedicated JAR for connectivity classes, while NetworkUtilsInternal would stay in the frameworks-minus-apex JAR, in the com.android.internal.net package. Bug: 171540887 Test: m, boots, wifi working atest FrameworksNetTests Change-Id: I3d38d72ad23a4bf84af823c7baeb6fed25c0665f --- core/java/android/net/NetworkStatsHistory.java | 2 +- .../java/com/android/server/net/NetworkStatsCollection.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index fba7561434..bf25602041 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -26,9 +26,9 @@ import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray; import static android.net.NetworkStatsHistory.Entry.UNKNOWN; import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; -import static android.net.NetworkUtils.multiplySafeByRational; import static android.text.format.DateUtils.SECOND_IN_MILLIS; +import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; import static com.android.internal.util.ArrayUtils.total; import android.compat.annotation.UnsupportedAppUsage; diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 342a11b87a..c4beddd42e 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -28,9 +28,9 @@ import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; -import static android.net.NetworkUtils.multiplySafeByRational; import static android.text.format.DateUtils.WEEK_IN_MILLIS; +import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; import static com.android.server.net.NetworkStatsService.TAG; import android.net.NetworkIdentity; From d436634a35924807d2ef6f21948941bdcd8b57ec Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 3 Dec 2020 17:58:49 +0900 Subject: [PATCH 534/881] Register ethernet listeners on specific Executors Have users of EthernetManager#addListener specify an Executor instead of running callbacks on ConnectivityThread. For existing clients, run callbacks on the common BackgroundThread. This change in behavior is fine because addListener is not an API, the threading model in Q was to run callbacks on the looper of the thread that first created EthernetManager (so there is already no guarantee on which thread is used), and the only users are in Settings. ConnectivityThread is moving to a connectivity-specific JAR, so it should not be used by external classes. Bug: 174436414 Test: Ethernet client / tethering working atest TetheringIntegrationTests Change-Id: Ic9a959f89915329f79eeeaa0a210ad50811d1291 --- core/java/android/net/EthernetManager.java | 93 ++++++++++++++-------- 1 file changed, 58 insertions(+), 35 deletions(-) diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java index 84a8e1c3dc..7cd63ef9cc 100644 --- a/core/java/android/net/EthernetManager.java +++ b/core/java/android/net/EthernetManager.java @@ -24,10 +24,11 @@ import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; -import android.os.Handler; -import android.os.Message; import android.os.RemoteException; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.os.BackgroundThread; + import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; @@ -41,31 +42,35 @@ import java.util.concurrent.Executor; @SystemService(Context.ETHERNET_SERVICE) public class EthernetManager { private static final String TAG = "EthernetManager"; - private static final int MSG_AVAILABILITY_CHANGED = 1000; - private final Context mContext; private final IEthernetManager mService; - private final Handler mHandler = new Handler(ConnectivityThread.getInstanceLooper()) { - @Override - public void handleMessage(Message msg) { - if (msg.what == MSG_AVAILABILITY_CHANGED) { - boolean isAvailable = (msg.arg1 == 1); - for (Listener listener : mListeners) { - listener.onAvailabilityChanged((String) msg.obj, isAvailable); - } - } - } - }; - private final ArrayList mListeners = new ArrayList<>(); + @GuardedBy("mListeners") + private final ArrayList mListeners = new ArrayList<>(); private final IEthernetServiceListener.Stub mServiceListener = new IEthernetServiceListener.Stub() { @Override public void onAvailabilityChanged(String iface, boolean isAvailable) { - mHandler.obtainMessage( - MSG_AVAILABILITY_CHANGED, isAvailable ? 1 : 0, 0, iface).sendToTarget(); + synchronized (mListeners) { + for (ListenerInfo li : mListeners) { + li.executor.execute(() -> + li.listener.onAvailabilityChanged(iface, isAvailable)); + } + } } }; + private static class ListenerInfo { + @NonNull + public final Executor executor; + @NonNull + public final Listener listener; + + private ListenerInfo(@NonNull Executor executor, @NonNull Listener listener) { + this.executor = executor; + this.listener = listener; + } + } + /** * A listener interface to receive notification on changes in Ethernet. * @hide @@ -89,7 +94,6 @@ public class EthernetManager { * @hide */ public EthernetManager(Context context, IEthernetManager service) { - mContext = context; mService = service; } @@ -146,21 +150,38 @@ public class EthernetManager { /** * Adds a listener. + * + * Consider using {@link #addListener(Listener, Executor)} instead: this method uses a default + * executor that may have higher latency than a provided executor. * @param listener A {@link Listener} to add. * @throws IllegalArgumentException If the listener is null. * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void addListener(Listener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); + public void addListener(@NonNull Listener listener) { + addListener(listener, BackgroundThread.getExecutor()); + } + + /** + * Adds a listener. + * @param listener A {@link Listener} to add. + * @param executor Executor to run callbacks on. + * @throws IllegalArgumentException If the listener or executor is null. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public void addListener(@NonNull Listener listener, @NonNull Executor executor) { + if (listener == null || executor == null) { + throw new NullPointerException("listener and executor must not be null"); } - mListeners.add(listener); - if (mListeners.size() == 1) { - try { - mService.addListener(mServiceListener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + synchronized (mListeners) { + mListeners.add(new ListenerInfo(executor, listener)); + if (mListeners.size() == 1) { + try { + mService.addListener(mServiceListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } } } @@ -185,16 +206,18 @@ public class EthernetManager { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void removeListener(Listener listener) { + public void removeListener(@NonNull Listener listener) { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } - mListeners.remove(listener); - if (mListeners.isEmpty()) { - try { - mService.removeListener(mServiceListener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + synchronized (mListeners) { + mListeners.removeIf(l -> l.listener == listener); + if (mListeners.isEmpty()) { + try { + mService.removeListener(mServiceListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } } } From 1b161bcebcbe0c72c6a0c45728a2f62adac492a3 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 19 Aug 2020 16:07:22 +0900 Subject: [PATCH 535/881] Move module utils to the module package. Test: FrameworksWifiTest FrameworksNetTest Change-Id: If5d1e4a58fb2d6d9544e6d01995dabe445cf1f25 Merged-In: I067eeecd458c34b7f2fbfa439072682661ac750c --- services/core/java/com/android/server/NsdService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 4a1820a8e5..d907505481 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -25,7 +25,6 @@ import android.net.Uri; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; -import android.net.util.nsd.DnsSdTxtRecord; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; @@ -42,6 +41,7 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; +import com.android.net.module.util.DnsSdTxtRecord; import java.io.FileDescriptor; import java.io.PrintWriter; From 38a17a772684b89e1616ee7180aeb898d2d2af79 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Wed, 23 Dec 2020 22:42:10 +0000 Subject: [PATCH 536/881] Migrate frameworks/base/wifi & frameworks/base/packages/OsuLogin Migrate to packages/modules/Wifi. This CL will be presubmit tested once migration is complete. This CL drops the code from frameworks/base/wifi and migrated to packages/modules/Wifi. Also adjusts visibility rules in frameworks/base/Android.bp Bug: 137323948 Test: TH Change-Id: Id02e28648e922a30d6a81cf92b39eff4ca3cc002 --- .../android/net/wifi/p2p/IWifiP2pManager.aidl | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl deleted file mode 100644 index fd89d3b048..0000000000 --- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi.p2p; - -import android.os.Messenger; - -/** - * Interface that WifiP2pService implements - * - * {@hide} - */ -interface IWifiP2pManager -{ - Messenger getMessenger(in IBinder binder, in String packageName); - Messenger getP2pStateMachineMessenger(); - oneway void close(in IBinder binder); - void setMiracastMode(int mode); - void checkConfigureWifiDisplayPermission(); -} - From a94c867fba73f470696156fa1ef81429904e8bff Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Wed, 23 Dec 2020 22:53:04 +0000 Subject: [PATCH 537/881] Migrate frameworks/base/wifi & frameworks/base/packages/OsuLogin Migrate to packages/modules/Wifi. This CL will be presubmit tested once migration is complete. This CL drops the code from frameworks/base/wifi and migrated to packages/modules/Wifi. Also adjusts visibility rules in frameworks/base/Android.bp Bug: 137323948 Test: TH Merged-In: I9031a37c84e17c2cf5c0552d1b33e8fd59216b92 Change-Id: I4ad80b1584f9f80dffed7786739b80f3aaf88cdc --- .../android/net/wifi/p2p/IWifiP2pManager.aidl | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl deleted file mode 100644 index bfdd45d9f9..0000000000 --- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi.p2p; - -import android.os.Messenger; - -/** - * Interface that WifiP2pService implements - * - * {@hide} - */ -interface IWifiP2pManager -{ - Messenger getMessenger(in IBinder binder); - Messenger getP2pStateMachineMessenger(); - oneway void close(in IBinder binder); - void setMiracastMode(int mode); - void checkConfigureWifiDisplayPermission(); -} - From bbbc041523437626ed6ec076534be0b1bc97f147 Mon Sep 17 00:00:00 2001 From: Baligh Uddin Date: Wed, 23 Dec 2020 23:18:44 +0000 Subject: [PATCH 538/881] Migrate frameworks/base/wifi & frameworks/base/packages/OsuLogin Migrate to packages/modules/Wifi. This CL will be presubmit tested once migration is complete. This CL drops the code from frameworks/base/wifi and migrated to packages/modules/Wifi. Also adjusts visibility rules in frameworks/base/Android.bp Bug: 137323948 Test: TH Merged-In: Id02e28648e922a30d6a81cf92b39eff4ca3cc002 Change-Id: I28e35cea55001c2333374c2342f496a0340f2f32 --- .../android/net/wifi/p2p/IWifiP2pManager.aidl | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl deleted file mode 100644 index bfdd45d9f9..0000000000 --- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2008, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net.wifi.p2p; - -import android.os.Messenger; - -/** - * Interface that WifiP2pService implements - * - * {@hide} - */ -interface IWifiP2pManager -{ - Messenger getMessenger(in IBinder binder); - Messenger getP2pStateMachineMessenger(); - oneway void close(in IBinder binder); - void setMiracastMode(int mode); - void checkConfigureWifiDisplayPermission(); -} - From b71ce2a04f1d315f07e128fd79a5868602961ebe Mon Sep 17 00:00:00 2001 From: Serik Beketayev Date: Sun, 6 Dec 2020 23:08:08 -0800 Subject: [PATCH 539/881] [Mainline] Migrate ProxyInfo Bug: 173455434 Test: atest FrameworksNetTests Change-Id: I924aed710b62a0c91b888a9e04ac2c90cdfd88d0 --- .../java/com/android/server/net/IpConfigStore.java | 11 +++++++---- .../src/com/android/server/net/IpConfigStoreTest.java | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index 9c5abd4706..cc3a002adc 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -30,6 +30,7 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.ProxyUtils; import java.io.BufferedInputStream; import java.io.DataInputStream; @@ -123,7 +124,8 @@ public class IpConfigStore { switch (config.proxySettings) { case STATIC: ProxyInfo proxyProperties = config.httpProxy; - String exclusionList = proxyProperties.getExclusionListAsString(); + String exclusionList = ProxyUtils.exclusionListAsString( + proxyProperties.getExclusionList()); out.writeUTF(PROXY_SETTINGS_KEY); out.writeUTF(config.proxySettings.toString()); out.writeUTF(PROXY_HOST_KEY); @@ -370,13 +372,14 @@ public class IpConfigStore { switch (proxySettings) { case STATIC: - ProxyInfo proxyInfo = - new ProxyInfo(proxyHost, proxyPort, exclusionList); + ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy(proxyHost, proxyPort, + ProxyUtils.exclusionStringAsList(exclusionList)); config.proxySettings = proxySettings; config.httpProxy = proxyInfo; break; case PAC: - ProxyInfo proxyPacProperties = new ProxyInfo(Uri.parse(pacFileUrl)); + ProxyInfo proxyPacProperties = + ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl)); config.proxySettings = proxySettings; config.httpProxy = proxyPacProperties; break; diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java index 9d300a6113..401d6e30df 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -39,6 +39,7 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; /** * Unit tests for {@link IpConfigStore} @@ -82,7 +83,8 @@ public class IpConfigStoreTest { staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); - ProxyInfo proxyInfo = new ProxyInfo("10.10.10.10", 88, "host1,host2"); + ProxyInfo proxyInfo = + ProxyInfo.buildDirectProxy("10.10.10.10", 88, Arrays.asList("host1", "host2")); IpConfiguration expectedConfig1 = new IpConfiguration(IpAssignment.STATIC, ProxySettings.STATIC, staticIpConfiguration, proxyInfo); From 5520d9d6017e800e286af03dd93728977b862ff0 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Mon, 4 Jan 2021 22:35:57 -0700 Subject: [PATCH 540/881] Pivot network statistics to use DataInput/Output. Using these generalized interfaces is more flexible, since it enables us to pivot the implementation being used internally. In particular, an upcoming CL will pivot them to use a more efficient alternative. This is a no-op refactoring. Bug: 176777285 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: Ibd4717174cf1f136e9d5d80172ecb6e493265306 --- .../java/android/net/NetworkStatsHistory.java | 18 +++++++++--------- .../server/net/NetworkIdentitySet.java | 12 ++++++------ .../server/net/NetworkStatsCollection.java | 19 +++++++++++++------ .../server/net/NetworkStatsRecorder.java | 5 ++--- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index bf25602041..f41306301d 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -45,8 +45,8 @@ import com.android.internal.util.IndentingPrintWriter; import libcore.util.EmptyArray; import java.io.CharArrayWriter; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.io.PrintWriter; import java.net.ProtocolException; @@ -162,7 +162,7 @@ public class NetworkStatsHistory implements Parcelable { out.writeLong(totalBytes); } - public NetworkStatsHistory(DataInputStream in) throws IOException { + public NetworkStatsHistory(DataInput in) throws IOException { final int version = in.readInt(); switch (version) { case VERSION_INIT: { @@ -204,7 +204,7 @@ public class NetworkStatsHistory implements Parcelable { } } - public void writeToStream(DataOutputStream out) throws IOException { + public void writeToStream(DataOutput out) throws IOException { out.writeInt(VERSION_ADD_ACTIVE); out.writeLong(bucketDuration); writeVarLongArray(out, bucketStart, bucketCount); @@ -768,7 +768,7 @@ public class NetworkStatsHistory implements Parcelable { */ public static class DataStreamUtils { @Deprecated - public static long[] readFullLongArray(DataInputStream in) throws IOException { + public static long[] readFullLongArray(DataInput in) throws IOException { final int size = in.readInt(); if (size < 0) throw new ProtocolException("negative array size"); final long[] values = new long[size]; @@ -781,7 +781,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Read variable-length {@link Long} using protobuf-style approach. */ - public static long readVarLong(DataInputStream in) throws IOException { + public static long readVarLong(DataInput in) throws IOException { int shift = 0; long result = 0; while (shift < 64) { @@ -797,7 +797,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Write variable-length {@link Long} using protobuf-style approach. */ - public static void writeVarLong(DataOutputStream out, long value) throws IOException { + public static void writeVarLong(DataOutput out, long value) throws IOException { while (true) { if ((value & ~0x7FL) == 0) { out.writeByte((int) value); @@ -809,7 +809,7 @@ public class NetworkStatsHistory implements Parcelable { } } - public static long[] readVarLongArray(DataInputStream in) throws IOException { + public static long[] readVarLongArray(DataInput in) throws IOException { final int size = in.readInt(); if (size == -1) return null; if (size < 0) throw new ProtocolException("negative array size"); @@ -820,7 +820,7 @@ public class NetworkStatsHistory implements Parcelable { return values; } - public static void writeVarLongArray(DataOutputStream out, long[] values, int size) + public static void writeVarLongArray(DataOutput out, long[] values, int size) throws IOException { if (values == null) { out.writeInt(-1); diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index 2326ad39fd..bce80696f7 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -20,8 +20,8 @@ import android.net.NetworkIdentity; import android.service.NetworkIdentitySetProto; import android.util.proto.ProtoOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; +import java.io.DataInput; +import java.io.DataOutput; import java.io.IOException; import java.util.HashSet; @@ -44,7 +44,7 @@ public class NetworkIdentitySet extends HashSet implements public NetworkIdentitySet() { } - public NetworkIdentitySet(DataInputStream in) throws IOException { + public NetworkIdentitySet(DataInput in) throws IOException { final int version = in.readInt(); final int size = in.readInt(); for (int i = 0; i < size; i++) { @@ -89,7 +89,7 @@ public class NetworkIdentitySet extends HashSet implements } } - public void writeToStream(DataOutputStream out) throws IOException { + public void writeToStream(DataOutput out) throws IOException { out.writeInt(VERSION_ADD_DEFAULT_NETWORK); out.writeInt(size()); for (NetworkIdentity ident : this) { @@ -143,7 +143,7 @@ public class NetworkIdentitySet extends HashSet implements return true; } - private static void writeOptionalString(DataOutputStream out, String value) throws IOException { + private static void writeOptionalString(DataOutput out, String value) throws IOException { if (value != null) { out.writeByte(1); out.writeUTF(value); @@ -152,7 +152,7 @@ public class NetworkIdentitySet extends HashSet implements } } - private static String readOptionalString(DataInputStream in) throws IOException { + private static String readOptionalString(DataInput in) throws IOException { if (in.readByte() != 0) { return in.readUTF(); } else { diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index c4beddd42e..6aefe41891 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -63,12 +63,15 @@ import com.google.android.collect.Lists; import com.google.android.collect.Maps; import java.io.BufferedInputStream; +import java.io.DataInput; import java.io.DataInputStream; +import java.io.DataOutput; import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.io.PrintWriter; import java.net.ProtocolException; import java.time.ZonedDateTime; @@ -82,7 +85,7 @@ import java.util.Objects; * Collection of {@link NetworkStatsHistory}, stored based on combined key of * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. */ -public class NetworkStatsCollection implements FileRotator.Reader { +public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer { /** File header magic number: "ANET" */ private static final int FILE_MAGIC = 0x414E4554; @@ -431,10 +434,10 @@ public class NetworkStatsCollection implements FileRotator.Reader { @Override public void read(InputStream in) throws IOException { - read(new DataInputStream(in)); + read((DataInput) new DataInputStream(in)); } - public void read(DataInputStream in) throws IOException { + private void read(DataInput in) throws IOException { // verify file magic header intact final int magic = in.readInt(); if (magic != FILE_MAGIC) { @@ -468,7 +471,13 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } - public void write(DataOutputStream out) throws IOException { + @Override + public void write(OutputStream out) throws IOException { + write((DataOutput) new DataOutputStream(out)); + out.flush(); + } + + private void write(DataOutput out) throws IOException { // cluster key lists grouped by ident final HashMap> keysByIdent = Maps.newHashMap(); for (Key key : mStats.keySet()) { @@ -497,8 +506,6 @@ public class NetworkStatsCollection implements FileRotator.Reader { history.writeToStream(out); } } - - out.flush(); } @Deprecated diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index ce741693cb..978ae87d39 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -42,7 +42,6 @@ import com.google.android.collect.Sets; import libcore.io.IoUtils; import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -375,7 +374,7 @@ public class NetworkStatsRecorder { @Override public void write(OutputStream out) throws IOException { - mCollection.write(new DataOutputStream(out)); + mCollection.write(out); mCollection.reset(); } } @@ -412,7 +411,7 @@ public class NetworkStatsRecorder { @Override public void write(OutputStream out) throws IOException { - mTemp.write(new DataOutputStream(out)); + mTemp.write(out); } } From aa005e47cae9c270533f4e42bf1ef7fec8b1639e Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 12 Jan 2021 16:22:32 +0900 Subject: [PATCH 541/881] [NS01.eth] Remove a useless argument Test: FrameworksNetTests Change-Id: Ib262871e4909ae65b5e6b2e52d2f25bf5a653f34 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 793b284676..3c67927baa 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -87,20 +87,20 @@ public class EthernetNetworkFactory extends NetworkFactory { } @Override - public boolean acceptRequest(NetworkRequest request, int score) { + public boolean acceptRequest(NetworkRequest request) { if (request.type == NetworkRequest.Type.TRACK_DEFAULT) { return false; } if (DBG) { - Log.d(TAG, "acceptRequest, request: " + request + ", score: " + score); + Log.d(TAG, "acceptRequest, request: " + request); } return networkForRequest(request) != null; } @Override - protected void needNetworkFor(NetworkRequest networkRequest, int score) { + protected void needNetworkFor(NetworkRequest networkRequest) { NetworkInterfaceState network = networkForRequest(networkRequest); if (network == null) { From 4715a5c3820451e4f4adb604d8929aa66873c53f Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Thu, 3 Dec 2020 17:08:29 -0800 Subject: [PATCH 542/881] Expose IPsec tunnel APIs from @SystemApi to public APIs Since IKE APIs to negotiate IPsec tunnel migration (MOBIKE) are public, all IPsec tunnel APIs should also be public so that public callers are able to create, manage and migrate IPsec tunnels Bug: 174606949 Test: atest IpSecManagerTunnelTest Change-Id: I86aec334cfc937953f9c2b411cc55862032aae4d --- core/java/android/net/IpSecManager.java | 93 +++++++++++++++++-------- 1 file changed, 65 insertions(+), 28 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index d83715c692..b6ae7ecfdb 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -705,7 +705,7 @@ public final class IpSecManager { } /** - * This class represents an IpSecTunnelInterface + * This class represents an IpSecTunnelInterface. * *

IpSecTunnelInterface objects track tunnel interfaces that serve as * local endpoints for IPsec tunnels. @@ -714,9 +714,7 @@ public final class IpSecManager { * applied to provide IPsec security to packets sent through the tunnel. While a tunnel * cannot be used in standalone mode within Android, the higher layers may use the tunnel * to create Network objects which are accessible to the Android system. - * @hide */ - @SystemApi public static final class IpSecTunnelInterface implements AutoCloseable { private final String mOpPackageName; private final IIpSecService mService; @@ -727,23 +725,26 @@ public final class IpSecManager { private String mInterfaceName; private int mResourceId = INVALID_RESOURCE_ID; - /** Get the underlying SPI held by this object. */ + /** + * Get the underlying SPI held by this object. + * + * @hide + */ + @SystemApi @NonNull public String getInterfaceName() { return mInterfaceName; } /** - * Add an address to the IpSecTunnelInterface + * Add an address to the IpSecTunnelInterface. * *

Add an address which may be used as the local inner address for * tunneled traffic. * * @param address the local address for traffic inside the tunnel * @param prefixLen length of the InetAddress prefix - * @hide */ - @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { @@ -758,15 +759,13 @@ public final class IpSecManager { } /** - * Remove an address from the IpSecTunnelInterface + * Remove an address from the IpSecTunnelInterface. * - *

Remove an address which was previously added to the IpSecTunnelInterface + *

Remove an address which was previously added to the IpSecTunnelInterface. * * @param address to be removed * @param prefixLen length of the InetAddress prefix - * @hide */ - @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { @@ -817,7 +816,7 @@ public final class IpSecManager { } /** - * Delete an IpSecTunnelInterface + * Delete an IpSecTunnelInterface. * *

Calling close will deallocate the IpSecTunnelInterface and all of its system * resources. Any packets bound for this interface either inbound or outbound will @@ -839,7 +838,12 @@ public final class IpSecManager { } } - /** Check that the Interface was closed properly. */ + + /** + * Check that the Interface was closed properly. + * + * @hide + */ @Override protected void finalize() throws Throwable { if (mCloseGuard != null) { @@ -871,17 +875,52 @@ public final class IpSecManager { * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. * *

An application that creates tunnels is responsible for cleaning up the tunnel when the - * underlying network goes away, and the onLost() callback is received. + * underlying network disconnects, and the {@link + * ConnectivityManager.NetworkCallback#onLost(Network)} callback is received. * - * @param localAddress The local addres of the tunnel - * @param remoteAddress The local addres of the tunnel - * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. - * This network should almost certainly be a network such as WiFi with an L2 address. - * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties - * @throws IOException indicating that the socket could not be opened or bound - * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open - * @hide + * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. Packets + * that go through the tunnel will need a underlying network to transit to the IPsec peer. + * This network should almost certainly be a physical network such as WiFi. + * @return a new {@link IpSecTunnelInterface} with the specified properties + * @throws IOException indicating that the tunnel could not be created due to a lower-layer + * error + * @throws ResourceUnavailableException indicating that the number of opening tunnels has + * reached the limit. */ + @NonNull + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) + public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull Network underlyingNetwork) + throws ResourceUnavailableException, IOException { + + // TODO: Remove the need for adding two unused addresses with IPsec tunnels when {@link + // #createIpSecTunnelInterface(localAddress, remoteAddress, underlyingNetwork)} can be + // safely removed. + final InetAddress address = InetAddress.getLocalHost(); + return createIpSecTunnelInterface(address, address, underlyingNetwork); + } + + /** + * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. + * + *

An application that creates tunnels is responsible for cleaning up the tunnel when the + * underlying network disconnects, and the {@link + * ConnectivityManager.NetworkCallback#onLost(Network)} callback is received. + * + * @param localAddress The local address of the tunnel + * @param remoteAddress The local address of the tunnel + * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. Packets + * that go through the tunnel will need a underlying network to transit to the IPsec peer. + * This network should almost certainly be a physical network such as WiFi. + * @return a new {@link IpSecTunnelInterface} with the specified properties + * @throws IOException indicating that the tunnel could not be created due to a lower-layer + * error + * @throws ResourceUnavailableException indicating that the number of opening tunnels has + * reached the limit. + * @hide + * @deprecated Callers should use {@link #createIpSecTunnelInterface(Network)} + */ + @Deprecated @SystemApi @NonNull @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @@ -905,16 +944,14 @@ public final class IpSecManager { *

Applications should probably not use this API directly. * * - * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied + * @param tunnel The {@link IpSecTunnelInterface} that will use the supplied * transform. - * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which + * @param direction the direction, {@link #DIRECTION_OUT} or {@link #DIRECTION_IN} in which * the transform will be used. * @param transform an {@link IpSecTransform} created in tunnel mode - * @throws IOException indicating that the transform could not be applied due to a lower - * layer failure. - * @hide + * @throws IOException indicating that the transform could not be applied due to a lower-layer + * error */ - @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, From e42fc5ff7624e666dbe8d067eb7b0be11161aaa6 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 8 Jan 2021 20:22:27 +0800 Subject: [PATCH 543/881] [FUI14] Get SSID from NetworkCapabilities This allows subsequent patches to remove the need of exposing SSID in NetworkState. Test: atest NetworkStatsServiceTest Bug: 174123988 Change-Id: Ib9ab07c9610954c9a5de035a3aefbf6d0bb0b53b --- core/java/android/net/NetworkIdentity.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index a0dc72d4ad..b644ed56ad 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -194,13 +194,15 @@ public class NetworkIdentity implements Comparable { subscriberId = state.subscriberId; if (type == TYPE_WIFI) { - if (state.networkId != null) { - networkId = state.networkId; - } else { - final WifiManager wifi = (WifiManager) context.getSystemService( - Context.WIFI_SERVICE); - final WifiInfo info = wifi.getConnectionInfo(); - networkId = info != null ? info.getSSID() : null; + if (state.networkCapabilities.getSsid() != null) { + networkId = state.networkCapabilities.getSsid(); + if (networkId == null) { + // TODO: Figure out if this code path never runs. If so, remove them. + final WifiManager wifi = (WifiManager) context.getSystemService( + Context.WIFI_SERVICE); + final WifiInfo info = wifi.getConnectionInfo(); + networkId = info != null ? info.getSSID() : null; + } } } From 33bcecba89a945aec63969d4ec757aca2caab2d2 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Wed, 20 Jan 2021 18:00:52 +0800 Subject: [PATCH 544/881] Fix EthernetTrackerTest#createNetworkCapabilities aosp/1307433 added NET_CAPABILITY_NOT_ROAMING, NET_CAPABILITY_NOT_CONGESTED and NET_CAPABILITY_NOT_SUSPENDED for ethernet but forgot to run and modify EthernetTrackerTest. Follow aosp/1307433 to add NET_CAPABILITY_NOT_ROAMING, NET_CAPABILITY_NOT_CONGESTED and NET_CAPABILITY_NOT_SUSPENDED for ethernet in test when verifying the network capabilities of ethernet. Bug: 177782157 Test: atest EthernetServiceTests Change-Id: I32c596b1b7726c47818460ea646bf5e346825887 --- .../server/ethernet/EthernetTrackerTest.java | 60 ++++++++++--------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 67740b666a..12187889ac 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -133,6 +133,15 @@ public class EthernetTrackerTest { } } + private NetworkCapabilitiesBuilder makeEthernetCapabilitiesBuilder(boolean clearAll) { + final NetworkCapabilitiesBuilder result = + clearAll ? new NetworkCapabilitiesBuilder().clearAll() + : new NetworkCapabilitiesBuilder(); + return result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); + } + /** * Test: Attempt to create a capabilties with various valid sets of capabilities/transports */ @@ -140,23 +149,23 @@ public class EthernetTrackerTest { public void createNetworkCapabilities() { // Particularly common expected results - NetworkCapabilities defaultEthernetCleared = new NetworkCapabilitiesBuilder() - .clearAll() - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) - .build(); + NetworkCapabilities defaultEthernetCleared = + makeEthernetCapabilitiesBuilder(true /* clearAll */) + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .build(); - NetworkCapabilities ethernetClearedWithCommonCaps = new NetworkCapabilitiesBuilder() - .clearAll() - .setLinkUpstreamBandwidthKbps(100000) - .setLinkDownstreamBandwidthKbps(100000) - .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) - .addCapability(12) - .addCapability(13) - .addCapability(14) - .addCapability(15) - .build(); + NetworkCapabilities ethernetClearedWithCommonCaps = + makeEthernetCapabilitiesBuilder(true /* clearAll */) + .setLinkUpstreamBandwidthKbps(100000) + .setLinkDownstreamBandwidthKbps(100000) + .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .addCapability(12) + .addCapability(13) + .addCapability(14) + .addCapability(15) + .build(); // Empty capabilities and transports lists with a "please clear defaults" should // yield an empty capabilities set with TRANPORT_ETHERNET @@ -165,7 +174,7 @@ public class EthernetTrackerTest { // Empty capabilities and transports without the clear defaults flag should return the // default capabilities set with TRANSPORT_ETHERNET assertParsedNetworkCapabilities( - new NetworkCapabilitiesBuilder() + makeEthernetCapabilitiesBuilder(false /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) @@ -175,7 +184,7 @@ public class EthernetTrackerTest { // A list of capabilities without the clear defaults flag should return the default // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET assertParsedNetworkCapabilities( - new NetworkCapabilitiesBuilder() + makeEthernetCapabilitiesBuilder(false /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) @@ -195,32 +204,28 @@ public class EthernetTrackerTest { // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport // and apply only the override to the capabiltities object assertParsedNetworkCapabilities( - new NetworkCapabilitiesBuilder() - .clearAll() + makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) .addTransport(0) .build(), true, "", "0"); assertParsedNetworkCapabilities( - new NetworkCapabilitiesBuilder() - .clearAll() + makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) .addTransport(1) .build(), true, "", "1"); assertParsedNetworkCapabilities( - new NetworkCapabilitiesBuilder() - .clearAll() + makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) .addTransport(2) .build(), true, "", "2"); assertParsedNetworkCapabilities( - new NetworkCapabilitiesBuilder() - .clearAll() + makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) .addTransport(3) @@ -244,8 +249,7 @@ public class EthernetTrackerTest { // Ensure the adding of both capabilities and transports work assertParsedNetworkCapabilities( - new NetworkCapabilitiesBuilder() - .clearAll() + makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) .addCapability(12) From 2b482af9587bdf6d191189a2b2be94c5289af7bc Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 21 Jan 2021 12:20:00 +0800 Subject: [PATCH 545/881] Replace the usage of NetworkManagementService with NetdUtils Since NetdUtils has the same method(setInterfaceUp) as NetworkManagementService, replace the usage of NMS with NetdUtils. Bug: 170598012 Test: atest EthernetServiceTests Change-Id: Id0f8e17e9d6237fa8ab157c96dd982c47007a453 --- .../com/android/server/ethernet/EthernetTracker.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index d7fd408b69..80c3b97359 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -21,6 +21,7 @@ import static android.net.TestNetworkManager.TEST_TAP_PREFIX; import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; +import android.net.INetd; import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfiguration; import android.net.IpConfiguration; @@ -28,6 +29,7 @@ import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; import android.net.NetworkCapabilities; +import android.net.NetworkStack; import android.net.StaticIpConfiguration; import android.os.Handler; import android.os.IBinder; @@ -38,14 +40,17 @@ import android.os.ServiceManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; +import android.net.util.NetdService; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; +import com.android.net.module.util.NetdUtils; import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; import java.net.InetAddress; import java.util.ArrayList; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; /** @@ -87,6 +92,7 @@ final class EthernetTracker { private final Context mContext; private final INetworkManagementService mNMService; + private final INetd mNetd; private final Handler mHandler; private final EthernetNetworkFactory mFactory; private final EthernetConfigStore mConfigStore; @@ -117,6 +123,7 @@ final class EthernetTracker { // The services we use. IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); mNMService = INetworkManagementService.Stub.asInterface(b); + mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance"); // Interface match regex. updateIfaceMatchRegexp(); @@ -280,7 +287,8 @@ final class EthernetTracker { InterfaceConfiguration config = null; // Bring up the interface so we get link status indications. try { - mNMService.setInterfaceUp(iface); + NetworkStack.checkNetworkStackPermission(mContext); + NetdUtils.setInterfaceUp(mNetd, iface); config = mNMService.getInterfaceConfig(iface); } catch (RemoteException | IllegalStateException e) { // Either the system is crashing or the interface has disappeared. Just ignore the From 2fe9a7247542f7d4ab8f2d09beaf69af261dcab2 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 12 Jan 2021 18:48:13 +0800 Subject: [PATCH 546/881] Expose UdpEncapsulationSocket.getResourceId() ConnectivityManager.createSocketKeepalive() will need to get the socket resource ID as a parameter for creating a new NattSocketKeepalive. ConnectivityManager is a part of incoming ConnectivityService mainline, so expose getResourceId() as an API since the hidden APIs are not accessible for a mainline module. This API should not be exposed to apps, so make it a MODULE_LIBRARIES system API. Bug: 172183305 Test: make update-api Change-Id: Ic0722352ea186fcb18a2d91cc3969f771fde9e86 --- core/java/android/net/IpSecManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index b6ae7ecfdb..60923f5ea8 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -15,6 +15,8 @@ */ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -628,7 +630,7 @@ public final class IpSecManager { } /** @hide */ - @VisibleForTesting + @SystemApi(client = MODULE_LIBRARIES) public int getResourceId() { return mResourceId; } From c9983ee71c5071d6bdbff5ba893298924e0a5bae Mon Sep 17 00:00:00 2001 From: junyulai Date: Sat, 23 Jan 2021 01:09:11 +0800 Subject: [PATCH 547/881] [FUI03] No-op refactoring of VpnInfo As a preparation of exposing system API. This patch does some harmless refactoring, which includes: 1. Move VpnInfo to android.net 2. Add nullability annotations 3. Make members final Bug: 174123988 Test: TH Change-Id: I1530bb45d0e84c28c6deac33596bc686058afc0d --- core/java/android/net/INetworkStatsService.aidl | 2 +- core/java/{com/android/internal => android}/net/VpnInfo.aidl | 2 +- .../core/java/com/android/server/net/NetworkStatsFactory.java | 2 +- .../core/java/com/android/server/net/NetworkStatsService.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename core/java/{com/android/internal => android}/net/VpnInfo.aidl (94%) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 1a3dc97448..d5aede7101 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -23,11 +23,11 @@ import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; +import android.net.VpnInfo; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.os.IBinder; import android.os.Messenger; -import com.android.internal.net.VpnInfo; /** {@hide} */ interface INetworkStatsService { diff --git a/core/java/com/android/internal/net/VpnInfo.aidl b/core/java/android/net/VpnInfo.aidl similarity index 94% rename from core/java/com/android/internal/net/VpnInfo.aidl rename to core/java/android/net/VpnInfo.aidl index 6fc97be409..8bcaa81f39 100644 --- a/core/java/com/android/internal/net/VpnInfo.aidl +++ b/core/java/android/net/VpnInfo.aidl @@ -14,6 +14,6 @@ * limitations under the License. */ -package com.android.internal.net; +package android.net; parcelable VpnInfo; diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index e9868fde30..4faa7903c6 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -27,6 +27,7 @@ import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.annotation.Nullable; import android.net.INetd; import android.net.NetworkStats; +import android.net.VpnInfo; import android.net.util.NetdService; import android.os.RemoteException; import android.os.StrictMode; @@ -34,7 +35,6 @@ import android.os.SystemClock; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 81a6641de8..4be7b483af 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -105,6 +105,7 @@ import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; import android.net.Uri; +import android.net.VpnInfo; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; @@ -143,7 +144,6 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.net.VpnInfo; import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; From 40bac65ec7fd951d66cdcfcd82f088409e17c177 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 28 Jan 2021 14:42:52 +0800 Subject: [PATCH 548/881] [VCN07.4] Add NOT_VCN_MANAGED for NetworkAgent implementations Follow-up from aosp/1549897, the capability will not be in default capabilities, but will be in most of the NetworkRequests which requires internet. Thus, add the capabilities into all NetworkAgent implementations by default to provide backward compatibility. Test: TH Bug: 175662146 Change-Id: Ib6e203571946e3094e4ce534b108f796cc3b8fb7 --- service-t/src/com/android/server/ethernet/EthernetTracker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index d7fd408b69..72245afdf8 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -467,6 +467,7 @@ final class EthernetTracker { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); + nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); if (isTestIface) { nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST); From 6a1f216c0efe24f17c087ee9f6c51ec400294ed9 Mon Sep 17 00:00:00 2001 From: junyulai Date: Sat, 23 Jan 2021 09:46:34 +0800 Subject: [PATCH 549/881] [FUI04] Refactor VpnInfo As a preparation of exposing system API. This patch does some harmless refactoring, which includes: 1. Change raw arrays into lists according to API guidelines. 2. Write test. 3. Rename class to UnderlyingNetworkInfo. 4. Rename vpnIface to iface. 5. Make underlyingIfaces @NonNull in order to adapt new unparceling code. 6. implement equals and hashCode for testing. Test: atest android.net.UnderlyingNetworkInfoTest Bug: 174123988 Change-Id: I405c21e57c4af8a12a9dd0a1749b9e6690f87045 --- .../android/net/INetworkStatsService.aidl | 4 +- ...pnInfo.aidl => UnderlyingNetworkInfo.aidl} | 2 +- .../android/net/UnderlyingNetworkInfo.java | 110 ++++++++++++++++++ .../server/net/NetworkStatsFactory.java | 19 +-- .../server/net/NetworkStatsService.java | 6 +- 5 files changed, 126 insertions(+), 15 deletions(-) rename core/java/android/net/{VpnInfo.aidl => UnderlyingNetworkInfo.aidl} (94%) create mode 100644 core/java/android/net/UnderlyingNetworkInfo.java diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index d5aede7101..0baf11e850 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -23,7 +23,7 @@ import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; -import android.net.VpnInfo; +import android.net.UnderlyingNetworkInfo; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.os.IBinder; @@ -70,7 +70,7 @@ interface INetworkStatsService { in Network[] defaultNetworks, in NetworkState[] networkStates, in String activeIface, - in VpnInfo[] vpnInfos); + in UnderlyingNetworkInfo[] underlyingNetworkInfos); /** Force update of statistics. */ @UnsupportedAppUsage void forceUpdate(); diff --git a/core/java/android/net/VpnInfo.aidl b/core/java/android/net/UnderlyingNetworkInfo.aidl similarity index 94% rename from core/java/android/net/VpnInfo.aidl rename to core/java/android/net/UnderlyingNetworkInfo.aidl index 8bcaa81f39..a56f2f4058 100644 --- a/core/java/android/net/VpnInfo.aidl +++ b/core/java/android/net/UnderlyingNetworkInfo.aidl @@ -16,4 +16,4 @@ package android.net; -parcelable VpnInfo; +parcelable UnderlyingNetworkInfo; diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java new file mode 100644 index 0000000000..8fb4832e06 --- /dev/null +++ b/core/java/android/net/UnderlyingNetworkInfo.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * A lightweight container used to carry information on the networks that underly a given + * virtual network. + * + * @hide + */ +public final class UnderlyingNetworkInfo implements Parcelable { + /** The owner of this network. */ + public final int ownerUid; + /** The interface name of this network. */ + @NonNull + public final String iface; + /** The names of the interfaces underlying this network. */ + @NonNull + public final List underlyingIfaces; + + public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface, + @NonNull List underlyingIfaces) { + Objects.requireNonNull(iface); + Objects.requireNonNull(underlyingIfaces); + this.ownerUid = ownerUid; + this.iface = iface; + this.underlyingIfaces = underlyingIfaces; + } + + private UnderlyingNetworkInfo(@NonNull Parcel in) { + this.ownerUid = in.readInt(); + this.iface = in.readString(); + this.underlyingIfaces = new ArrayList<>(); + in.readList(this.underlyingIfaces, null /*classLoader*/); + } + + @Override + public String toString() { + return "UnderlyingNetworkInfo{" + + "ownerUid=" + ownerUid + + ", iface='" + iface + '\'' + + ", underlyingIfaces='" + underlyingIfaces.toString() + '\'' + + '}'; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(ownerUid); + dest.writeString(iface); + dest.writeList(underlyingIfaces); + } + + @NonNull + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @NonNull + @Override + public UnderlyingNetworkInfo createFromParcel(@NonNull Parcel in) { + return new UnderlyingNetworkInfo(in); + } + + @NonNull + @Override + public UnderlyingNetworkInfo[] newArray(int size) { + return new UnderlyingNetworkInfo[size]; + } + }; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof UnderlyingNetworkInfo)) return false; + final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o; + return ownerUid == that.ownerUid + && Objects.equals(iface, that.iface) + && Objects.equals(underlyingIfaces, that.underlyingIfaces); + } + + @Override + public int hashCode() { + return Objects.hash(ownerUid, iface, underlyingIfaces); + } +} diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 4faa7903c6..d042b882fe 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -27,7 +27,7 @@ import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.annotation.Nullable; import android.net.INetd; import android.net.NetworkStats; -import android.net.VpnInfo; +import android.net.UnderlyingNetworkInfo; import android.net.util.NetdService; import android.os.RemoteException; import android.os.StrictMode; @@ -81,7 +81,7 @@ public class NetworkStatsFactory { private final Object mPersistentDataLock = new Object(); /** Set containing info about active VPNs and their underlying networks. */ - private volatile VpnInfo[] mVpnInfos = new VpnInfo[0]; + private volatile UnderlyingNetworkInfo[] mUnderlyingNetworkInfos = new UnderlyingNetworkInfo[0]; // A persistent snapshot of cumulative stats since device start @GuardedBy("mPersistentDataLock") @@ -116,8 +116,8 @@ public class NetworkStatsFactory { * * @param vpnArray The snapshot of the currently-running VPNs. */ - public void updateVpnInfos(VpnInfo[] vpnArray) { - mVpnInfos = vpnArray.clone(); + public void updateUnderlyingNetworkInfos(UnderlyingNetworkInfo[] vpnArray) { + mUnderlyingNetworkInfos = vpnArray.clone(); } /** @@ -319,7 +319,7 @@ public class NetworkStatsFactory { // code that will acquire other locks within the system server. See b/134244752. synchronized (mPersistentDataLock) { // Take a reference. If this gets swapped out, we still have the old reference. - final VpnInfo[] vpnArray = mVpnInfos; + final UnderlyingNetworkInfo[] vpnArray = mUnderlyingNetworkInfos; // Take a defensive copy. mPersistSnapshot is mutated in some cases below final NetworkStats prev = mPersistSnapshot.clone(); @@ -369,8 +369,8 @@ public class NetworkStatsFactory { } @GuardedBy("mPersistentDataLock") - private NetworkStats adjustForTunAnd464Xlat( - NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) { + private NetworkStats adjustForTunAnd464Xlat(NetworkStats uidDetailStats, + NetworkStats previousStats, UnderlyingNetworkInfo[] vpnArray) { // Calculate delta from last snapshot final NetworkStats delta = uidDetailStats.subtract(previousStats); @@ -381,8 +381,9 @@ public class NetworkStatsFactory { delta.apply464xlatAdjustments(mStackedIfaces); // Migrate data usage over a VPN to the TUN network. - for (VpnInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces); + for (UnderlyingNetworkInfo info : vpnArray) { + delta.migrateTun(info.ownerUid, info.iface, + info.underlyingIfaces.toArray(new String[0])); // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4be7b483af..0ab35a9110 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -104,8 +104,8 @@ import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; +import android.net.UnderlyingNetworkInfo; import android.net.Uri; -import android.net.VpnInfo; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; @@ -973,7 +973,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Network[] defaultNetworks, NetworkState[] networkStates, String activeIface, - VpnInfo[] vpnInfos) { + UnderlyingNetworkInfo[] underlyingNetworkInfos) { checkNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); @@ -986,7 +986,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Update the VPN underlying interfaces only after the poll is made and tun data has been // migrated. Otherwise the migration would use the new interfaces instead of the ones that // were current when the polled data was transferred. - mStatsFactory.updateVpnInfos(vpnInfos); + mStatsFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); } @Override From a60efcc095d51dfe5c7be87c9b0894c445828d96 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 15 Jan 2021 18:08:24 +0900 Subject: [PATCH 550/881] Move module sources to packages/Connectivity Files that are planned to be part of the connectivity module are grouped in packages/Connectivity, so they can be built separately and moved in one operation with their history into packages/modules/Connectivity. This places the files in the existing framework-connectivity-sources filegroup instead of the current framework-core-sources filegroup. Both are used the same way in framework-non-updatable-sources. Bug: 171540887 Test: m Change-Id: I62d9d91574ace6f5c4624035d190260c3126b91e --- core/java/android/net/UidRange.aidl | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 core/java/android/net/UidRange.aidl diff --git a/core/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl deleted file mode 100644 index f70fc8e2fe..0000000000 --- a/core/java/android/net/UidRange.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** - * An inclusive range of UIDs. - * - * {@hide} - */ -parcelable UidRange; \ No newline at end of file From c35b88591b6c1d430c280d5b4efe3d10730c6952 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 1 Feb 2021 08:12:34 +0000 Subject: [PATCH 551/881] Revert "Expose IPsec tunnel APIs from @SystemApi to public APIs" This reverts commit 4715a5c3820451e4f4adb604d8929aa66873c53f. Reason for revert: not necessary, since VCN already has access to system APIs Bug: 174606949 Test: revert with no conflicts Change-Id: Ife2d0fc08c540265d52cdf930d0b6df005990ac8 --- core/java/android/net/IpSecManager.java | 91 ++++++++----------------- 1 file changed, 27 insertions(+), 64 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index b6ae7ecfdb..d83715c692 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -705,7 +705,7 @@ public final class IpSecManager { } /** - * This class represents an IpSecTunnelInterface. + * This class represents an IpSecTunnelInterface * *

IpSecTunnelInterface objects track tunnel interfaces that serve as * local endpoints for IPsec tunnels. @@ -714,7 +714,9 @@ public final class IpSecManager { * applied to provide IPsec security to packets sent through the tunnel. While a tunnel * cannot be used in standalone mode within Android, the higher layers may use the tunnel * to create Network objects which are accessible to the Android system. + * @hide */ + @SystemApi public static final class IpSecTunnelInterface implements AutoCloseable { private final String mOpPackageName; private final IIpSecService mService; @@ -725,26 +727,23 @@ public final class IpSecManager { private String mInterfaceName; private int mResourceId = INVALID_RESOURCE_ID; - /** - * Get the underlying SPI held by this object. - * - * @hide - */ - @SystemApi + /** Get the underlying SPI held by this object. */ @NonNull public String getInterfaceName() { return mInterfaceName; } /** - * Add an address to the IpSecTunnelInterface. + * Add an address to the IpSecTunnelInterface * *

Add an address which may be used as the local inner address for * tunneled traffic. * * @param address the local address for traffic inside the tunnel * @param prefixLen length of the InetAddress prefix + * @hide */ + @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void addAddress(@NonNull InetAddress address, int prefixLen) throws IOException { @@ -759,13 +758,15 @@ public final class IpSecManager { } /** - * Remove an address from the IpSecTunnelInterface. + * Remove an address from the IpSecTunnelInterface * - *

Remove an address which was previously added to the IpSecTunnelInterface. + *

Remove an address which was previously added to the IpSecTunnelInterface * * @param address to be removed * @param prefixLen length of the InetAddress prefix + * @hide */ + @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void removeAddress(@NonNull InetAddress address, int prefixLen) throws IOException { @@ -816,7 +817,7 @@ public final class IpSecManager { } /** - * Delete an IpSecTunnelInterface. + * Delete an IpSecTunnelInterface * *

Calling close will deallocate the IpSecTunnelInterface and all of its system * resources. Any packets bound for this interface either inbound or outbound will @@ -838,12 +839,7 @@ public final class IpSecManager { } } - - /** - * Check that the Interface was closed properly. - * - * @hide - */ + /** Check that the Interface was closed properly. */ @Override protected void finalize() throws Throwable { if (mCloseGuard != null) { @@ -875,52 +871,17 @@ public final class IpSecManager { * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. * *

An application that creates tunnels is responsible for cleaning up the tunnel when the - * underlying network disconnects, and the {@link - * ConnectivityManager.NetworkCallback#onLost(Network)} callback is received. + * underlying network goes away, and the onLost() callback is received. * - * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. Packets - * that go through the tunnel will need a underlying network to transit to the IPsec peer. - * This network should almost certainly be a physical network such as WiFi. - * @return a new {@link IpSecTunnelInterface} with the specified properties - * @throws IOException indicating that the tunnel could not be created due to a lower-layer - * error - * @throws ResourceUnavailableException indicating that the number of opening tunnels has - * reached the limit. - */ - @NonNull - @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) - @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) - public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull Network underlyingNetwork) - throws ResourceUnavailableException, IOException { - - // TODO: Remove the need for adding two unused addresses with IPsec tunnels when {@link - // #createIpSecTunnelInterface(localAddress, remoteAddress, underlyingNetwork)} can be - // safely removed. - final InetAddress address = InetAddress.getLocalHost(); - return createIpSecTunnelInterface(address, address, underlyingNetwork); - } - - /** - * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic. - * - *

An application that creates tunnels is responsible for cleaning up the tunnel when the - * underlying network disconnects, and the {@link - * ConnectivityManager.NetworkCallback#onLost(Network)} callback is received. - * - * @param localAddress The local address of the tunnel - * @param remoteAddress The local address of the tunnel - * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. Packets - * that go through the tunnel will need a underlying network to transit to the IPsec peer. - * This network should almost certainly be a physical network such as WiFi. - * @return a new {@link IpSecTunnelInterface} with the specified properties - * @throws IOException indicating that the tunnel could not be created due to a lower-layer - * error - * @throws ResourceUnavailableException indicating that the number of opening tunnels has - * reached the limit. + * @param localAddress The local addres of the tunnel + * @param remoteAddress The local addres of the tunnel + * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel. + * This network should almost certainly be a network such as WiFi with an L2 address. + * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties + * @throws IOException indicating that the socket could not be opened or bound + * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open * @hide - * @deprecated Callers should use {@link #createIpSecTunnelInterface(Network)} */ - @Deprecated @SystemApi @NonNull @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @@ -944,14 +905,16 @@ public final class IpSecManager { *

Applications should probably not use this API directly. * * - * @param tunnel The {@link IpSecTunnelInterface} that will use the supplied + * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied * transform. - * @param direction the direction, {@link #DIRECTION_OUT} or {@link #DIRECTION_IN} in which + * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which * the transform will be used. * @param transform an {@link IpSecTransform} created in tunnel mode - * @throws IOException indicating that the transform could not be applied due to a lower-layer - * error + * @throws IOException indicating that the transform could not be applied due to a lower + * layer failure. + * @hide */ + @SystemApi @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull IpSecTunnelInterface tunnel, From 614515339cfa515881d047d69f47ef36dcd647d1 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 28 Jan 2021 21:19:32 +0800 Subject: [PATCH 552/881] [FUI20] Expose UnderlyingNetworkInfo as system Api Test: atest android.net.UnderlyingNetworkInfoTest Bug: 174123988 Change-Id: Id602fbe744669f472d27fb466d00dcc601bd8f17 --- core/java/android/net/UnderlyingNetworkInfo.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java index 8fb4832e06..7bf9231239 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.java +++ b/core/java/android/net/UnderlyingNetworkInfo.java @@ -16,11 +16,15 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Objects; @@ -30,6 +34,7 @@ import java.util.Objects; * * @hide */ +@SystemApi(client = MODULE_LIBRARIES) public final class UnderlyingNetworkInfo implements Parcelable { /** The owner of this network. */ public final int ownerUid; @@ -46,7 +51,7 @@ public final class UnderlyingNetworkInfo implements Parcelable { Objects.requireNonNull(underlyingIfaces); this.ownerUid = ownerUid; this.iface = iface; - this.underlyingIfaces = underlyingIfaces; + this.underlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces)); } private UnderlyingNetworkInfo(@NonNull Parcel in) { From 00a5b7f75255ba88e479429c99e362b87e734662 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 29 Jan 2021 20:20:15 +0800 Subject: [PATCH 553/881] [FUI21] Move scrubSubscriberId to utils class This patch also removes the functionality of returning original subscriberId in eng build since it is not really useful. Test: atest NetworkIdentityUtilsTest Bug: 174123988 Change-Id: I721457e571aa9403a2200b3e4261b4895e4f7a3e --- .../app/usage/NetworkStatsManager.java | 4 +-- core/java/android/net/NetworkIdentity.java | 35 ++++--------------- core/java/android/net/NetworkTemplate.java | 5 +-- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 1ddfe0d247..1d5dc1d5df 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -28,7 +28,6 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.DataUsageRequest; import android.net.INetworkStatsService; -import android.net.NetworkIdentity; import android.net.NetworkStack; import android.net.NetworkTemplate; import android.net.netstats.provider.INetworkStatsProviderCallback; @@ -47,6 +46,7 @@ import android.util.DataUnit; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.NetworkIdentityUtils; import java.util.Objects; @@ -628,7 +628,7 @@ public class NetworkStatsManager { default: throw new IllegalArgumentException("Cannot create template for network type " + networkType + ", subscriberId '" - + NetworkIdentity.scrubSubscriberId(subscriberId) + "'."); + + NetworkIdentityUtils.scrubSubscriberId(subscriberId) + "'."); } return template; } diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index b644ed56ad..521ed9b194 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -21,11 +21,12 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import android.os.Build; import android.service.NetworkIdentityProto; import android.telephony.Annotation.NetworkType; import android.util.proto.ProtoOutputStream; +import com.android.net.module.util.NetworkIdentityUtils; + import java.util.Objects; /** @@ -89,7 +90,8 @@ public class NetworkIdentity implements Comparable { builder.append(mSubType); } if (mSubscriberId != null) { - builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId)); + builder.append(", subscriberId=") + .append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId)); } if (mNetworkId != null) { builder.append(", networkId=").append(mNetworkId); @@ -110,7 +112,8 @@ public class NetworkIdentity implements Comparable { // Not dumping mSubType, subtypes are no longer supported. if (mSubscriberId != null) { - proto.write(NetworkIdentityProto.SUBSCRIBER_ID, scrubSubscriberId(mSubscriberId)); + proto.write(NetworkIdentityProto.SUBSCRIBER_ID, + NetworkIdentityUtils.scrubSubscriberId(mSubscriberId)); } proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId); proto.write(NetworkIdentityProto.ROAMING, mRoaming); @@ -148,32 +151,6 @@ public class NetworkIdentity implements Comparable { return mDefaultNetwork; } - /** - * Scrub given IMSI on production builds. - */ - public static String scrubSubscriberId(String subscriberId) { - if (Build.IS_ENG) { - return subscriberId; - } else if (subscriberId != null) { - // TODO: parse this as MCC+MNC instead of hard-coding - return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "..."; - } else { - return "null"; - } - } - - /** - * Scrub given IMSI on production builds. - */ - public static String[] scrubSubscriberId(String[] subscriberId) { - if (subscriberId == null) return null; - final String[] res = new String[subscriberId.length]; - for (int i = 0; i < res.length; i++) { - res[i] = NetworkIdentity.scrubSubscriberId(subscriberId[i]); - } - return res; - } - /** * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType}, * assuming that any mobile networks are using the current IMSI. The subType if applicable, diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 72be835a1c..2322048708 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -48,6 +48,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; +import com.android.net.module.util.NetworkIdentityUtils; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -296,11 +297,11 @@ public class NetworkTemplate implements Parcelable { builder.append("matchRule=").append(getMatchRuleName(mMatchRule)); if (mSubscriberId != null) { builder.append(", subscriberId=").append( - NetworkIdentity.scrubSubscriberId(mSubscriberId)); + NetworkIdentityUtils.scrubSubscriberId(mSubscriberId)); } if (mMatchSubscriberIds != null) { builder.append(", matchSubscriberIds=").append( - Arrays.toString(NetworkIdentity.scrubSubscriberId(mMatchSubscriberIds))); + Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds))); } if (mNetworkId != null) { builder.append(", networkId=").append(mNetworkId); From 3088c8fab8d3e73901eaa172ad5941323c5daf7e Mon Sep 17 00:00:00 2001 From: Roman Kalukiewicz Date: Wed, 14 Oct 2020 15:59:06 -0700 Subject: [PATCH 554/881] Add @Nullable to Object#equals() This is a partial cherry-pick of change: I5eedb571c9d78862115dfdc5dae1cf2a35343580 for connectivity classes. Bug: 170883422 Test: m Merged-In: I5eedb571c9d78862115dfdc5dae1cf2a35343580 Change-Id: I7dc661863b73f4198ddb4f3a1566583d0f07db3c --- core/java/android/net/DataUsageRequest.java | 3 ++- core/java/android/net/IpSecTransform.java | 3 ++- core/java/android/net/NetworkIdentity.java | 3 ++- core/java/android/net/NetworkStats.java | 2 +- core/java/android/net/NetworkTemplate.java | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/DataUsageRequest.java b/core/java/android/net/DataUsageRequest.java index 0ac8f7e794..b06d515b3a 100644 --- a/core/java/android/net/DataUsageRequest.java +++ b/core/java/android/net/DataUsageRequest.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.Nullable; import android.net.NetworkTemplate; import android.os.Parcel; import android.os.Parcelable; @@ -95,7 +96,7 @@ public final class DataUsageRequest implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof DataUsageRequest == false) return false; DataUsageRequest that = (DataUsageRequest) obj; return that.requestId == this.requestId diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index aa7811a3a1..b48c1fdaf1 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -19,6 +19,7 @@ import static android.net.IpSecManager.INVALID_RESOURCE_ID; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; @@ -150,7 +151,7 @@ public final class IpSecTransform implements AutoCloseable { /** * Standard equals. */ - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { if (this == other) return true; if (!(other instanceof IpSecTransform)) return false; final IpSecTransform rhs = (IpSecTransform) other; diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 521ed9b194..5d8122b6ce 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -18,6 +18,7 @@ package android.net; import static android.net.ConnectivityManager.TYPE_WIFI; +import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; @@ -67,7 +68,7 @@ public class NetworkIdentity implements Comparable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof NetworkIdentity) { final NetworkIdentity ident = (NetworkIdentity) obj; return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index cf40ce58d4..d42beae601 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -412,7 +412,7 @@ public final class NetworkStats implements Parcelable { /** @hide */ @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (o instanceof Entry) { final Entry e = (Entry) o; return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 2322048708..aa61e03b28 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -329,7 +329,7 @@ public class NetworkTemplate implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof NetworkTemplate) { final NetworkTemplate other = (NetworkTemplate) obj; return mMatchRule == other.mMatchRule From 0fc5576b55133003597006766b2a722e2b03c384 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Wed, 3 Feb 2021 23:59:45 +0800 Subject: [PATCH 555/881] Use NetdUtils instead of NetworkManagementService in IpSecService NetdUtils has the same method(e.g. setInterfaceUp) as NetworkManagementService so using the one inside NetdUtils instead and try to remove NetworkManagementService from IpSecService in the following commit. Bug: 170598012 Test: atest FrameworksNetTests Change-Id: I0ed8b0c678b067a655b51b938b6b40eadd985321 --- services/core/java/com/android/server/IpSecService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index f648c3e146..b35091b5f2 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -62,6 +62,7 @@ import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import com.android.net.module.util.NetdUtils; import libcore.io.IoUtils; @@ -1317,7 +1318,7 @@ public class IpSecService extends IIpSecService.Stub { netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); Binder.withCleanCallingIdentity(() -> { - mNetworkManager.setInterfaceUp(intfName); + NetdUtils.setInterfaceUp(netd, intfName); }); for (int selAddrFamily : ADDRESS_FAMILIES) { From 2af9ad4065450641b8825d1c505bd3cde6879b4c Mon Sep 17 00:00:00 2001 From: lucaslin Date: Mon, 18 Jan 2021 13:06:39 +0800 Subject: [PATCH 556/881] Remove unused INetworkManagementService from IpSecService IpSecService is no longer using any methods of INetworkManagementService, so remove it from IpSecService and related files. Bug: 170598012 Test: atest FrameworksNetTests Change-Id: I852e3a534e0ffd26b4b22420754f3ec8a6f153ad --- .../java/com/android/server/IpSecService.java | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index b35091b5f2..2789f5f26d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -46,7 +46,6 @@ import android.net.TrafficStats; import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -116,9 +115,6 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; - /* NetworkManager instance */ - private final INetworkManagementService mNetworkManager; - /** * The next non-repeating global ID for tracking resources between users, this service, and * kernel data structures. Accessing this variable is not thread safe, so it is only read or @@ -997,13 +993,13 @@ public class IpSecService extends IIpSecService.Stub { * * @param context Binder context for this service */ - private IpSecService(Context context, INetworkManagementService networkManager) { - this(context, networkManager, IpSecServiceConfiguration.GETSRVINSTANCE); + private IpSecService(Context context) { + this(context, IpSecServiceConfiguration.GETSRVINSTANCE); } - static IpSecService create(Context context, INetworkManagementService networkManager) + static IpSecService create(Context context) throws InterruptedException { - final IpSecService service = new IpSecService(context, networkManager); + final IpSecService service = new IpSecService(context); service.connectNativeNetdService(); return service; } @@ -1017,11 +1013,9 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, INetworkManagementService networkManager, - IpSecServiceConfiguration config) { + public IpSecService(Context context, IpSecServiceConfiguration config) { this( context, - networkManager, config, (fd, uid) -> { try { @@ -1035,10 +1029,9 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, INetworkManagementService networkManager, - IpSecServiceConfiguration config, UidFdTagger uidFdTagger) { + public IpSecService(Context context, IpSecServiceConfiguration config, + UidFdTagger uidFdTagger) { mContext = context; - mNetworkManager = Objects.requireNonNull(networkManager); mSrvConfig = config; mUidFdTagger = uidFdTagger; } From 22d74f2833b9ad0a451eb4d09a3a4828710a3b99 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 29 Dec 2020 19:17:01 +0800 Subject: [PATCH 557/881] [FUI06] Stop using NetworkInfo in NetworkState from external callers This is achieved by: 1. Use legacy network type inside NetworkState to replace the needs of referencing NetworkInfo.getType(). 2. Let getAllNetworkState only return networks with isConnected() equals true. This allows callers such as NPMS or NSS does not have to reference to NetworkInfo.isConnected(). Test: atest FrameworksNetTests NetworkPolicyManagerServiceTest Bug: 174123988 Change-Id: I1c4eb08d18ca973eb8f41d06258872eabc0006b8 --- core/java/android/net/NetworkIdentity.java | 8 +- .../server/net/NetworkStatsService.java | 143 +++++++++--------- 2 files changed, 74 insertions(+), 77 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 521ed9b194..b4aed6f963 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -31,7 +31,7 @@ import java.util.Objects; /** * Network definition that includes strong identity. Analogous to combining - * {@link NetworkInfo} and an IMSI. + * {@link NetworkCapabilities} and an IMSI. * * @hide */ @@ -159,7 +159,7 @@ public class NetworkIdentity implements Comparable { */ public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, boolean defaultNetwork, @NetworkType int subType) { - final int type = state.networkInfo.getType(); + final int legacyType = state.legacyNetworkType; String subscriberId = null; String networkId = null; @@ -170,7 +170,7 @@ public class NetworkIdentity implements Comparable { subscriberId = state.subscriberId; - if (type == TYPE_WIFI) { + if (legacyType == TYPE_WIFI) { if (state.networkCapabilities.getSsid() != null) { networkId = state.networkCapabilities.getSsid(); if (networkId == null) { @@ -183,7 +183,7 @@ public class NetworkIdentity implements Comparable { } } - return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, + return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered, defaultNetwork); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 0ab35a9110..9706bcece9 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -96,7 +96,6 @@ import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; -import android.net.NetworkInfo; import android.net.NetworkStack; import android.net.NetworkState; import android.net.NetworkStats; @@ -1264,7 +1263,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * Inspect all current {@link NetworkState} to derive mapping from {@code iface} to {@link - * NetworkStatsHistory}. When multiple {@link NetworkInfo} are active on a single {@code iface}, + * NetworkStatsHistory}. When multiple networks are active on a single {@code iface}, * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") @@ -1294,84 +1293,82 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { - if (state.networkInfo.isConnected()) { - final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); - final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); - final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED - : getSubTypeForState(state); - final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, - isDefault, subType); + final boolean isMobile = isNetworkTypeMobile(state.legacyNetworkType); + final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); + final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED + : getSubTypeForState(state); + final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, + isDefault, subType); - // Traffic occurring on the base interface is always counted for - // both total usage and UID details. - final String baseIface = state.linkProperties.getInterfaceName(); - if (baseIface != null) { - findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident); - findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident); + // Traffic occurring on the base interface is always counted for + // both total usage and UID details. + final String baseIface = state.linkProperties.getInterfaceName(); + if (baseIface != null) { + findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident); + findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident); - // Build a separate virtual interface for VT (Video Telephony) data usage. - // Only do this when IMS is not metered, but VT is metered. - // If IMS is metered, then the IMS network usage has already included VT usage. - // VT is considered always metered in framework's layer. If VT is not metered - // per carrier's policy, modem will report 0 usage for VT calls. - if (state.networkCapabilities.hasCapability( - NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) { + // Build a separate virtual interface for VT (Video Telephony) data usage. + // Only do this when IMS is not metered, but VT is metered. + // If IMS is metered, then the IMS network usage has already included VT usage. + // VT is considered always metered in framework's layer. If VT is not metered + // per carrier's policy, modem will report 0 usage for VT calls. + if (state.networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) { - // Copy the identify from IMS one but mark it as metered. - NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), - ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), - ident.getRoaming(), true /* metered */, - true /* onDefaultNetwork */); - findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent); - findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent); - } - - if (isMobile) { - mobileIfaces.add(baseIface); - } + // Copy the identify from IMS one but mark it as metered. + NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), + ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), + ident.getRoaming(), true /* metered */, + true /* onDefaultNetwork */); + findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent); + findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent); } - // Traffic occurring on stacked interfaces is usually clatd. - // - // UID stats are always counted on the stacked interface and never on the base - // interface, because the packets on the base interface do not actually match - // application sockets (they're not IPv4) and thus the app uid is not known. - // For receive this is obvious: packets must be translated from IPv6 to IPv4 - // before the application socket can be found. - // For transmit: either they go through the clat daemon which by virtue of going - // through userspace strips the original socket association during the IPv4 to - // IPv6 translation process, or they are offloaded by eBPF, which doesn't: - // However, on an ebpf device the accounting is done in cgroup ebpf hooks, - // which don't trigger again post ebpf translation. - // (as such stats accounted to the clat uid are ignored) - // - // Interface stats are more complicated. - // - // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus - // *all* statistics are collected by iptables on the stacked v4-* interface. - // - // Additionally for ingress all packets bound for the clat IPv6 address are dropped - // in ip6tables raw prerouting and thus even non-offloaded packets are only - // accounted for on the stacked interface. - // - // For egress, packets subject to eBPF offload never appear on the base interface - // and only appear on the stacked interface. Thus to ensure packets increment - // interface stats, we must collate data from stacked interfaces. For xt_qtaguid - // (or non eBPF offloaded) TX they would appear on both, however egress interface - // accounting is explicitly bypassed for traffic from the clat uid. - // - final List stackedLinks = state.linkProperties.getStackedLinks(); - for (LinkProperties stackedLink : stackedLinks) { - final String stackedIface = stackedLink.getInterfaceName(); - if (stackedIface != null) { - findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); - findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); - if (isMobile) { - mobileIfaces.add(stackedIface); - } + if (isMobile) { + mobileIfaces.add(baseIface); + } + } - mStatsFactory.noteStackedIface(stackedIface, baseIface); + // Traffic occurring on stacked interfaces is usually clatd. + // + // UID stats are always counted on the stacked interface and never on the base + // interface, because the packets on the base interface do not actually match + // application sockets (they're not IPv4) and thus the app uid is not known. + // For receive this is obvious: packets must be translated from IPv6 to IPv4 + // before the application socket can be found. + // For transmit: either they go through the clat daemon which by virtue of going + // through userspace strips the original socket association during the IPv4 to + // IPv6 translation process, or they are offloaded by eBPF, which doesn't: + // However, on an ebpf device the accounting is done in cgroup ebpf hooks, + // which don't trigger again post ebpf translation. + // (as such stats accounted to the clat uid are ignored) + // + // Interface stats are more complicated. + // + // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus + // *all* statistics are collected by iptables on the stacked v4-* interface. + // + // Additionally for ingress all packets bound for the clat IPv6 address are dropped + // in ip6tables raw prerouting and thus even non-offloaded packets are only + // accounted for on the stacked interface. + // + // For egress, packets subject to eBPF offload never appear on the base interface + // and only appear on the stacked interface. Thus to ensure packets increment + // interface stats, we must collate data from stacked interfaces. For xt_qtaguid + // (or non eBPF offloaded) TX they would appear on both, however egress interface + // accounting is explicitly bypassed for traffic from the clat uid. + // + final List stackedLinks = state.linkProperties.getStackedLinks(); + for (LinkProperties stackedLink : stackedLinks) { + final String stackedIface = stackedLink.getInterfaceName(); + if (stackedIface != null) { + findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); + findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); + if (isMobile) { + mobileIfaces.add(stackedIface); } + + mStatsFactory.noteStackedIface(stackedIface, baseIface); } } } From d67df4036cdf1d2f92d96887c18a3158162905dd Mon Sep 17 00:00:00 2001 From: lifr Date: Thu, 28 Jan 2021 19:11:04 +0800 Subject: [PATCH 558/881] [CS02]Remove hidden API usage of NetworkCapabilities The connection service will become the mainline module. The mutable NetworkCapabilities is deprecated, and the NetworkCapabilities should be built through their Builder instead. Bug: 170598012 Test: atest EthernetServiceTests Change-Id: I31f12a39a924302beca980b8d920e3c5c18816d4 --- .../ethernet/EthernetNetworkFactory.java | 12 ++++++++-- .../server/ethernet/EthernetTracker.java | 22 +++++++++---------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 3c67927baa..b9ebf8974e 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -161,12 +161,20 @@ public class EthernetNetworkFactory extends NetworkFactory { updateCapabilityFilter(); } + private static NetworkCapabilities mixInCapabilities(NetworkCapabilities nc, + NetworkCapabilities addedNc) { + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(nc); + for (int transport : addedNc.getTransportTypes()) builder.addTransportType(transport); + for (int capability : addedNc.getCapabilities()) builder.addCapability(capability); + return builder.build(); + } + private void updateCapabilityFilter() { NetworkCapabilities capabilitiesFilter = new NetworkCapabilities(); capabilitiesFilter.clearAll(); for (NetworkInterfaceState iface: mTrackingInterfaces.values()) { - capabilitiesFilter.combineCapabilities(iface.mCapabilities); + capabilitiesFilter = mixInCapabilities(capabilitiesFilter, iface.mCapabilities); } if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter); @@ -210,7 +218,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private NetworkInterfaceState networkForRequest(NetworkRequest request) { String requestedIface = null; - NetworkSpecifier specifier = request.networkCapabilities.getNetworkSpecifier(); + NetworkSpecifier specifier = request.getNetworkSpecifier(); if (specifier instanceof StringNetworkSpecifier) { requestedIface = ((StringNetworkSpecifier) specifier).specifier; } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 381f96163d..05b2782216 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -506,9 +506,9 @@ final class EthernetTracker { boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities, @Nullable String overrideTransport) { - NetworkCapabilities nc = new NetworkCapabilities(); + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); if (clearDefaultCapabilities) { - nc.clearAll(); // Remove default capabilities and transports + builder.clearAll(); // Remove default capabilities and transports } // Determine the transport type. If someone has tried to define an override transport then @@ -536,21 +536,21 @@ final class EthernetTracker { // Apply the transport. If the user supplied a valid number that is not a valid transport // then adding will throw an exception. Default back to TRANSPORT_ETHERNET if that happens try { - nc.addTransportType(transport); + builder.addTransportType(transport); } catch (IllegalArgumentException iae) { Log.e(TAG, transport + " is not a valid NetworkCapability.TRANSPORT_* value. " + "Defaulting to TRANSPORT_ETHERNET"); - nc.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); + builder.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET); } - nc.setLinkUpstreamBandwidthKbps(100 * 1000); - nc.setLinkDownstreamBandwidthKbps(100 * 1000); + builder.setLinkUpstreamBandwidthKbps(100 * 1000); + builder.setLinkDownstreamBandwidthKbps(100 * 1000); if (!TextUtils.isEmpty(commaSeparatedCapabilities)) { for (String strNetworkCapability : commaSeparatedCapabilities.split(",")) { if (!TextUtils.isEmpty(strNetworkCapability)) { try { - nc.addCapability(Integer.valueOf(strNetworkCapability)); + builder.addCapability(Integer.valueOf(strNetworkCapability)); } catch (NumberFormatException nfe) { Log.e(TAG, "Capability '" + strNetworkCapability + "' could not be parsed"); } catch (IllegalArgumentException iae) { @@ -562,11 +562,11 @@ final class EthernetTracker { } // Ethernet networks have no way to update the following capabilities, so they always // have them. - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); - return nc; + return builder.build(); } /** From 0f904190427da3203f51eb6503d35813ac927d4a Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Tue, 29 Sep 2020 23:38:00 -0700 Subject: [PATCH 559/881] Update underlying network of IpSecTunnelInterface Bug: 169855650 Test: atest IpSecManagerTunnelTest Change-Id: I6d1b8d0e49f89c67ddc2caf4ba63fb0b1eb062c0 --- core/java/android/net/IIpSecService.aidl | 3 ++ core/java/android/net/IpSecManager.java | 37 +++++++++++++ .../java/com/android/server/IpSecService.java | 54 +++++++++++++++++-- 3 files changed, 90 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/IIpSecService.aidl b/core/java/android/net/IIpSecService.aidl index d6774d47b4..933256a3b4 100644 --- a/core/java/android/net/IIpSecService.aidl +++ b/core/java/android/net/IIpSecService.aidl @@ -58,6 +58,9 @@ interface IIpSecService in LinkAddress localAddr, in String callingPackage); + void setNetworkForTunnelInterface( + int tunnelResourceId, in Network underlyingNetwork, in String callingPackage); + void deleteTunnelInterface(int resourceId, in String callingPackage); IpSecTransformResponse createTransform( diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 70bca30198..55fdafcea6 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -782,6 +782,43 @@ public final class IpSecManager { } } + /** + * Update the underlying network for this IpSecTunnelInterface. + * + *

This new underlying network will be used for all transforms applied AFTER this call is + * complete. Before new {@link IpSecTransform}(s) with matching addresses are applied to + * this tunnel interface, traffic will still use the old SA, and be routed on the old + * underlying network. + * + *

To migrate IPsec tunnel mode traffic, a caller should: + * + *

    + *
  1. Update the IpSecTunnelInterface’s underlying network. + *
  2. Apply {@link IpSecTransform}(s) with matching addresses to this + * IpSecTunnelInterface. + *
+ * + * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel. + * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise + * this method will throw an {@link IllegalArgumentException}. + * @hide + */ + // TODO: b/169171001 Update the documentation when transform migration is supported. + // The purpose of making updating network and applying transforms separate is to leave open + // the possibility to support lossless migration procedures. To do that, Android platform + // will need to support multiple inbound tunnel mode transforms, just like it can support + // multiple transport mode transforms. + @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS) + @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) + public void setUnderlyingNetwork(@NonNull Network underlyingNetwork) throws IOException { + try { + mService.setNetworkForTunnelInterface( + mResourceId, underlyingNetwork, mOpPackageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private IpSecTunnelInterface(@NonNull Context ctx, @NonNull IIpSecService service, @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index f648c3e146..b48bc900aa 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -29,6 +29,7 @@ import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; +import android.net.ConnectivityManager; import android.net.IIpSecService; import android.net.INetd; import android.net.InetAddresses; @@ -41,6 +42,7 @@ import android.net.IpSecTransformResponse; import android.net.IpSecTunnelInterfaceResponse; import android.net.IpSecUdpEncapResponse; import android.net.LinkAddress; +import android.net.LinkProperties; import android.net.Network; import android.net.TrafficStats; import android.net.util.NetdService; @@ -797,9 +799,15 @@ public class IpSecService extends IIpSecService.Stub { } } - private final class TunnelInterfaceRecord extends OwnedResourceRecord { + /** + * Tracks an tunnel interface, and manages cleanup paths. + * + *

This class is not thread-safe, and expects that that users of this class will ensure + * synchronization and thread safety by holding the IpSecService.this instance lock + */ + @VisibleForTesting + final class TunnelInterfaceRecord extends OwnedResourceRecord { private final String mInterfaceName; - private final Network mUnderlyingNetwork; // outer addresses private final String mLocalAddress; @@ -810,6 +818,8 @@ public class IpSecService extends IIpSecService.Stub { private final int mIfId; + private Network mUnderlyingNetwork; + TunnelInterfaceRecord( int resourceId, String interfaceName, @@ -870,14 +880,22 @@ public class IpSecService extends IIpSecService.Stub { releaseNetId(mOkey); } - public String getInterfaceName() { - return mInterfaceName; + @GuardedBy("IpSecService.this") + public void setUnderlyingNetwork(Network underlyingNetwork) { + // When #applyTunnelModeTransform is called, this new underlying network will be used to + // update the output mark of the input transform. + mUnderlyingNetwork = underlyingNetwork; } + @GuardedBy("IpSecService.this") public Network getUnderlyingNetwork() { return mUnderlyingNetwork; } + public String getInterfaceName() { + return mInterfaceName; + } + /** Returns the local, outer address for the tunnelInterface */ public String getLocalAddress() { return mLocalAddress; @@ -1429,6 +1447,34 @@ public class IpSecService extends IIpSecService.Stub { } } + /** Set TunnelInterface to use a specific underlying network. */ + @Override + public synchronized void setNetworkForTunnelInterface( + int tunnelResourceId, Network underlyingNetwork, String callingPackage) { + enforceTunnelFeatureAndPermissions(callingPackage); + Objects.requireNonNull(underlyingNetwork, "No underlying network was specified"); + + final UserRecord userRecord = mUserResourceTracker.getUserRecord(Binder.getCallingUid()); + + // Get tunnelInterface record; if no such interface is found, will throw + // IllegalArgumentException. userRecord.mTunnelInterfaceRecords is never null + final TunnelInterfaceRecord tunnelInterfaceInfo = + userRecord.mTunnelInterfaceRecords.getResourceOrThrow(tunnelResourceId); + + final ConnectivityManager connectivityManager = + mContext.getSystemService(ConnectivityManager.class); + final LinkProperties lp = connectivityManager.getLinkProperties(underlyingNetwork); + if (tunnelInterfaceInfo.getInterfaceName().equals(lp.getInterfaceName())) { + throw new IllegalArgumentException( + "Underlying network cannot be the network being exposed by this tunnel"); + } + + // It is meaningless to check if the network exists or is valid because the network might + // disconnect at any time after it passes the check. + + tunnelInterfaceInfo.setUnderlyingNetwork(underlyingNetwork); + } + /** * Delete a TunnelInterface that has been been allocated by and registered with the system * server From b7d45ba3c6ccd9c3642d72fc9e1f5a2f971a1e9b Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Wed, 7 Oct 2020 18:48:57 -0700 Subject: [PATCH 560/881] [API] Expose IpSecTunnelInterface#setUnderlyingNetwork This API is required to perform MOBIKE. This API allows an IPsec peer to change the underlying network of its established IPsec tunnel without re-establishing the tunnel. Bug: 169855650 Test: atest IpSecManagerTunnelTest (new tests added) Change-Id: Ifc8ad902cbfbe4ad07e715f2fef0faa1bf9d68f3 --- core/java/android/net/IpSecManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 55fdafcea6..98acd98cc4 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -801,7 +801,6 @@ public final class IpSecManager { * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel. * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise * this method will throw an {@link IllegalArgumentException}. - * @hide */ // TODO: b/169171001 Update the documentation when transform migration is supported. // The purpose of making updating network and applying transforms separate is to leave open From 331c2896d16ec9c7ffc7c2b3d889f35d8b2c33df Mon Sep 17 00:00:00 2001 From: Bob Badour Date: Fri, 12 Feb 2021 16:14:35 -0800 Subject: [PATCH 561/881] [LSC] Add LOCAL_LICENSE_KINDS to frameworks/opt/net/ethernet Added SPDX-license-identifier-Apache-2.0 to: Android.bp tests/Android.bp Bug: 68860345 Bug: 151177513 Bug: 151953481 Test: m all Exempt-From-Owner-Approval: janitorial work Change-Id: I9e5f4513d6a737c8e31639babd7a4e6342968214 --- tests/ethernet/Android.bp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp index 9c776e604f..4b2d270769 100644 --- a/tests/ethernet/Android.bp +++ b/tests/ethernet/Android.bp @@ -13,6 +13,10 @@ // limitations under the License. // +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + android_test { name: "EthernetServiceTests", From 6b1f3eaf12e762c5d3dee469bb19fe75c51ceda1 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Tue, 16 Feb 2021 11:48:55 -0800 Subject: [PATCH 562/881] Improve documentation of IpSecTunnelInterface#setUnderlyingNetwork Clarify the consequence of adding IpSecTunnelInterface to the underlying network. Bug: 169855650 Test: builds Change-Id: I2e3c4fe735b3374b2ff6d23850970e36c0aafda5 --- core/java/android/net/IpSecManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 98acd98cc4..f554dd5ab0 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -800,7 +800,9 @@ public final class IpSecManager { * * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel. * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise - * this method will throw an {@link IllegalArgumentException}. + * this method will throw an {@link IllegalArgumentException}. If the + * IpSecTunnelInterface is later added to this network, all outbound traffic will be + * blackholed. */ // TODO: b/169171001 Update the documentation when transform migration is supported. // The purpose of making updating network and applying transforms separate is to leave open From ce6537c9b739a311b109e726e76c89c6058be52f Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Feb 2021 20:16:28 +0900 Subject: [PATCH 563/881] Split parcelable .aidl files to aidl-export The one-line "parcelable X" files need to be imported by targets that do not build against SDK (the SDK has prebuilt definitions), so prepare a dedicated directory for them. This avoids having users of the classes include the whole src/ directory, which could contain definitions for classes that are not part of the public API, so should not be imported. Also move back to frameworks/base/core some .aidl definitions that were separated from their associated class. Bug: 171540887 Test: m Change-Id: I7432fe4c87cd3cab04dcb6185c9a4f3f84376549 --- core/java/android/net/UidRange.aidl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 core/java/android/net/UidRange.aidl diff --git a/core/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl new file mode 100644 index 0000000000..f70fc8e2fe --- /dev/null +++ b/core/java/android/net/UidRange.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * An inclusive range of UIDs. + * + * {@hide} + */ +parcelable UidRange; \ No newline at end of file From 695378c7b210c1942fe66a0e017d4da8f559e7c8 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 15 Feb 2021 20:16:28 +0900 Subject: [PATCH 564/881] Split parcelable .aidl files to aidl-export The one-line "parcelable X" files need to be imported by targets that do not build against SDK (the SDK has prebuilt definitions), so prepare a dedicated directory for them. This avoids having users of the classes include the whole src/ directory, which could contain definitions for classes that are not part of the public API, so should not be imported. Also move back to frameworks/base/core some .aidl definitions that were separated from their associated class. Bug: 171540887 Test: m Merged-In: I7432fe4c87cd3cab04dcb6185c9a4f3f84376549 Change-Id: I7432fe4c87cd3cab04dcb6185c9a4f3f84376549 --- core/java/android/net/UidRange.aidl | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 core/java/android/net/UidRange.aidl diff --git a/core/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl new file mode 100644 index 0000000000..f70fc8e2fe --- /dev/null +++ b/core/java/android/net/UidRange.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +/** + * An inclusive range of UIDs. + * + * {@hide} + */ +parcelable UidRange; \ No newline at end of file From 76649dfa94bd05ec6b229659c99fbd79fc04ce48 Mon Sep 17 00:00:00 2001 From: Chris Weir Date: Wed, 2 Dec 2020 17:58:54 -0800 Subject: [PATCH 565/881] Add support for tracking PANS data usage Adds support for tracking oemManagedNetwork types (OEM_PAID and OEM_PRIVATE). Bug: 174485293 Test: atest NetworkTemplateTest NetworkStatsCollectionTest NetworkStatsObserversTest NetworkStatsServiceTest NetworkIdentityTest Test: verify that the bytes go up in PansTest app only when `ping -I eth2 8.8.8.8` is run as root. Change-Id: I78660a835f16265ba8e44bb84332c6633dd72b84 --- core/java/android/net/NetworkIdentity.java | 57 +++++++++++++++++-- core/java/android/net/NetworkTemplate.java | 48 ++++++++++++++-- .../server/net/NetworkIdentitySet.java | 13 ++++- .../server/net/NetworkStatsService.java | 2 +- 4 files changed, 107 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 32b19a4622..303a40755d 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -18,6 +18,7 @@ package android.net; import static android.net.ConnectivityManager.TYPE_WIFI; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; @@ -41,6 +42,22 @@ public class NetworkIdentity implements Comparable { public static final int SUBTYPE_COMBINED = -1; + /** + * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}. + * @hide + */ + public static final int OEM_NONE = 0x0; + /** + * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}. + * @hide + */ + public static final int OEM_PAID = 0x1; + /** + * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}. + * @hide + */ + public static final int OEM_PRIVATE = 0x2; + final int mType; final int mSubType; final String mSubscriberId; @@ -48,10 +65,11 @@ public class NetworkIdentity implements Comparable { final boolean mRoaming; final boolean mMetered; final boolean mDefaultNetwork; + final int mOemManaged; public NetworkIdentity( int type, int subType, String subscriberId, String networkId, boolean roaming, - boolean metered, boolean defaultNetwork) { + boolean metered, boolean defaultNetwork, int oemManaged) { mType = type; mSubType = subType; mSubscriberId = subscriberId; @@ -59,12 +77,13 @@ public class NetworkIdentity implements Comparable { mRoaming = roaming; mMetered = metered; mDefaultNetwork = defaultNetwork; + mOemManaged = oemManaged; } @Override public int hashCode() { return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered, - mDefaultNetwork); + mDefaultNetwork, mOemManaged); } @Override @@ -75,7 +94,8 @@ public class NetworkIdentity implements Comparable { && Objects.equals(mSubscriberId, ident.mSubscriberId) && Objects.equals(mNetworkId, ident.mNetworkId) && mMetered == ident.mMetered - && mDefaultNetwork == ident.mDefaultNetwork; + && mDefaultNetwork == ident.mDefaultNetwork + && mOemManaged == ident.mOemManaged; } return false; } @@ -102,6 +122,8 @@ public class NetworkIdentity implements Comparable { } builder.append(", metered=").append(mMetered); builder.append(", defaultNetwork=").append(mDefaultNetwork); + // TODO(180557699): Print a human readable string for OEM managed state. + builder.append(", oemManaged=").append(mOemManaged); return builder.append("}").toString(); } @@ -120,6 +142,7 @@ public class NetworkIdentity implements Comparable { proto.write(NetworkIdentityProto.ROAMING, mRoaming); proto.write(NetworkIdentityProto.METERED, mMetered); proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork); + proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged); proto.end(start); } @@ -152,6 +175,10 @@ public class NetworkIdentity implements Comparable { return mDefaultNetwork; } + public int getOemManaged() { + return mOemManaged; + } + /** * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType}, * assuming that any mobile networks are using the current IMSI. The subType if applicable, @@ -171,6 +198,8 @@ public class NetworkIdentity implements Comparable { subscriberId = state.subscriberId; + final int oemManaged = getOemBitfield(state.networkCapabilities); + if (legacyType == TYPE_WIFI) { if (state.networkCapabilities.getSsid() != null) { networkId = state.networkCapabilities.getSsid(); @@ -185,7 +214,24 @@ public class NetworkIdentity implements Comparable { } return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered, - defaultNetwork); + defaultNetwork, oemManaged); + } + + /** + * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}. + * @hide + */ + public static int getOemBitfield(NetworkCapabilities nc) { + int oemManaged = OEM_NONE; + + if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) { + oemManaged |= OEM_PAID; + } + if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE)) { + oemManaged |= OEM_PRIVATE; + } + + return oemManaged; } @Override @@ -209,6 +255,9 @@ public class NetworkIdentity implements Comparable { if (res == 0) { res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork); } + if (res == 0) { + res = Integer.compare(mOemManaged, another.mOemManaged); + } return res; } } diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index aa61e03b28..c83dd99c2a 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -23,6 +23,7 @@ import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIMAX; +import static android.net.NetworkIdentity.OEM_NONE; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; @@ -99,6 +100,22 @@ public class NetworkTemplate implements Parcelable { */ public static final int NETWORK_TYPE_5G_NSA = -2; + /** + * Value to match both OEM managed and unmanaged networks (all networks). + * @hide + */ + public static final int OEM_MANAGED_ALL = -1; + /** + * Value to match networks which are not OEM managed. + * @hide + */ + public static final int OEM_MANAGED_NO = OEM_NONE; + /** + * Value to match any OEM managed network. + * @hide + */ + public static final int OEM_MANAGED_YES = -2; + private static boolean isKnownMatchRule(final int rule) { switch (rule) { case MATCH_MOBILE: @@ -151,10 +168,10 @@ public class NetworkTemplate implements Parcelable { @NetworkType int ratType) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL); } return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType); + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL); } /** @@ -235,6 +252,9 @@ public class NetworkTemplate implements Parcelable { private final int mDefaultNetwork; private final int mSubType; + // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}. + private final int mOemManaged; + @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); @@ -243,11 +263,12 @@ public class NetworkTemplate implements Parcelable { public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL); + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL); } public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String networkId, int metered, int roaming, int defaultNetwork, int subType) { + String networkId, int metered, int roaming, int defaultNetwork, int subType, + int oemManaged) { mMatchRule = matchRule; mSubscriberId = subscriberId; mMatchSubscriberIds = matchSubscriberIds; @@ -256,6 +277,7 @@ public class NetworkTemplate implements Parcelable { mRoaming = roaming; mDefaultNetwork = defaultNetwork; mSubType = subType; + mOemManaged = oemManaged; if (!isKnownMatchRule(matchRule)) { Log.e(TAG, "Unknown network template rule " + matchRule @@ -272,6 +294,7 @@ public class NetworkTemplate implements Parcelable { mRoaming = in.readInt(); mDefaultNetwork = in.readInt(); mSubType = in.readInt(); + mOemManaged = in.readInt(); } @Override @@ -284,6 +307,7 @@ public class NetworkTemplate implements Parcelable { dest.writeInt(mRoaming); dest.writeInt(mDefaultNetwork); dest.writeInt(mSubType); + dest.writeInt(mOemManaged); } @Override @@ -319,13 +343,16 @@ public class NetworkTemplate implements Parcelable { if (mSubType != NETWORK_TYPE_ALL) { builder.append(", subType=").append(mSubType); } + if (mOemManaged != OEM_MANAGED_ALL) { + builder.append(", oemManaged=").append(mOemManaged); + } return builder.toString(); } @Override public int hashCode() { return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, - mDefaultNetwork, mSubType); + mDefaultNetwork, mSubType, mOemManaged); } @Override @@ -338,7 +365,8 @@ public class NetworkTemplate implements Parcelable { && mMetered == other.mMetered && mRoaming == other.mRoaming && mDefaultNetwork == other.mDefaultNetwork - && mSubType == other.mSubType; + && mSubType == other.mSubType + && mOemManaged == other.mOemManaged; } return false; } @@ -384,6 +412,7 @@ public class NetworkTemplate implements Parcelable { if (!matchesMetered(ident)) return false; if (!matchesRoaming(ident)) return false; if (!matchesDefaultNetwork(ident)) return false; + if (!matchesOemNetwork(ident)) return false; switch (mMatchRule) { case MATCH_MOBILE: @@ -425,6 +454,13 @@ public class NetworkTemplate implements Parcelable { || (mDefaultNetwork == DEFAULT_NETWORK_NO && !ident.mDefaultNetwork); } + private boolean matchesOemNetwork(NetworkIdentity ident) { + return (mOemManaged == OEM_MANAGED_ALL) + || (mOemManaged == OEM_MANAGED_YES + && ident.mOemManaged != OEM_NONE) + || (mOemManaged == ident.mOemManaged); + } + private boolean matchesCollapsedRatType(NetworkIdentity ident) { return mSubType == NETWORK_TYPE_ALL || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType); diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index bce80696f7..22ed781da9 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -40,6 +40,7 @@ public class NetworkIdentitySet extends HashSet implements private static final int VERSION_ADD_NETWORK_ID = 3; private static final int VERSION_ADD_METERED = 4; private static final int VERSION_ADD_DEFAULT_NETWORK = 5; + private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6; public NetworkIdentitySet() { } @@ -84,13 +85,20 @@ public class NetworkIdentitySet extends HashSet implements defaultNetwork = true; } + final int oemNetCapabilities; + if (version >= VERSION_ADD_OEM_MANAGED_NETWORK) { + oemNetCapabilities = in.readInt(); + } else { + oemNetCapabilities = NetworkIdentity.OEM_NONE; + } + add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, - defaultNetwork)); + defaultNetwork, oemNetCapabilities)); } } public void writeToStream(DataOutput out) throws IOException { - out.writeInt(VERSION_ADD_DEFAULT_NETWORK); + out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK); out.writeInt(size()); for (NetworkIdentity ident : this) { out.writeInt(ident.getType()); @@ -100,6 +108,7 @@ public class NetworkIdentitySet extends HashSet implements out.writeBoolean(ident.getRoaming()); out.writeBoolean(ident.getMetered()); out.writeBoolean(ident.getDefaultNetwork()); + out.writeInt(ident.getOemManaged()); } } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 9706bcece9..5b9a11bc5a 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1319,7 +1319,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), ident.getRoaming(), true /* metered */, - true /* onDefaultNetwork */); + true /* onDefaultNetwork */, ident.getOemManaged()); findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent); findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent); } From 1b4f0a409db397bcf877f36edcf15ed16e801d96 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Tue, 19 Jan 2021 10:47:55 -0700 Subject: [PATCH 566/881] Pivot network statistics to use DataInput/Output. The majority of this refactoring has already landed in AOSP, and this small CL is the remaining piece needed to begin using the new optimized classes which only exist in the internal tree. This is a no-op refactoring. Bug: 176777285 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: Ifd7ac95c6cd6761e7d03cbf381dcc9e32b6406aa --- .../android/server/net/NetworkStatsCollection.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 6aefe41891..557fa89444 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -54,6 +54,8 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.FastDataInput; +import com.android.internal.util.FastDataOutput; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; @@ -89,6 +91,9 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** File header magic number: "ANET" */ private static final int FILE_MAGIC = 0x414E4554; + /** Default buffer size from BufferedInputStream */ + private static final int BUFFER_SIZE = 8192; + private static final int VERSION_NETWORK_INIT = 1; private static final int VERSION_UID_INIT = 1; @@ -434,7 +439,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W @Override public void read(InputStream in) throws IOException { - read((DataInput) new DataInputStream(in)); + final FastDataInput dataIn = new FastDataInput(in, BUFFER_SIZE); + read(dataIn); } private void read(DataInput in) throws IOException { @@ -473,8 +479,9 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W @Override public void write(OutputStream out) throws IOException { - write((DataOutput) new DataOutputStream(out)); - out.flush(); + final FastDataOutput dataOut = new FastDataOutput(out, BUFFER_SIZE); + write(dataOut); + dataOut.flush(); } private void write(DataOutput out) throws IOException { From 60fe5aa059f4caa2c521bbee4841a4c9cfe59470 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Mon, 8 Feb 2021 18:23:44 -0800 Subject: [PATCH 567/881] Support new IpSecAlgorithm AUTH_AES_CMAC Bug: 161716062 Test: IpSecAlgorithmTest, verified with CTS Change-Id: Ideaf4225bd851fad8c8072505c6ad99d85ba616e --- core/java/android/net/IpSecAlgorithm.java | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index e89451e4f4..8f1e2defd2 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -145,6 +145,25 @@ public final class IpSecAlgorithm implements Parcelable { // to be available on devices first shipped with Android 12 or later. public static final String AUTH_AES_XCBC = "xcbc(aes)"; + /** + * AES-CMAC Authentication/Integrity Algorithm. + * + *

Keys for this algorithm must be 128 bits in length. + * + *

The only valid truncation length is 96 bits. + * + *

This algorithm may be available on the device. Caller MUST check if it is supported before + * using it by calling {@link #getSupportedAlgorithms()} and checking if this algorithm is + * included in the returned algorithm set. The returned algorithm set will not change unless the + * device is rebooted. {@link IllegalArgumentException} will be thrown if this algorithm is + * requested on an unsupported device. + * + *

@see {@link #getSupportedAlgorithms()} + */ + // This algorithm may be available on devices released before Android 12, and is guaranteed + // to be available on devices first shipped with Android 12 or later. + public static final String AUTH_AES_CMAC = "cmac(aes)"; + /** * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm. * @@ -191,6 +210,7 @@ public final class IpSecAlgorithm implements Parcelable { AUTH_HMAC_SHA384, AUTH_HMAC_SHA512, AUTH_AES_XCBC, + AUTH_AES_CMAC, AUTH_CRYPT_AES_GCM, AUTH_CRYPT_CHACHA20_POLY1305 }) @@ -215,6 +235,7 @@ public final class IpSecAlgorithm implements Parcelable { // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1); ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1); } @@ -383,6 +404,10 @@ public final class IpSecAlgorithm implements Parcelable { isValidLen = keyLen == 128; isValidTruncLen = truncLen == 96; break; + case AUTH_AES_CMAC: + isValidLen = keyLen == 128; + isValidTruncLen = truncLen == 96; + break; case AUTH_CRYPT_AES_GCM: // The keying material for GCM is a key plus a 32-bit salt isValidLen = keyLen == 128 + 32 || keyLen == 192 + 32 || keyLen == 256 + 32; @@ -416,6 +441,7 @@ public final class IpSecAlgorithm implements Parcelable { case AUTH_HMAC_SHA384: case AUTH_HMAC_SHA512: case AUTH_AES_XCBC: + case AUTH_AES_CMAC: return true; default: return false; From 1745f3a7592fae9f572027f46df6441e61dc2bf5 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Thu, 25 Feb 2021 10:40:24 -0800 Subject: [PATCH 568/881] Use VERSION_CODES.S instead of VERSION_CODES.R + 1 Bug: 170424293 Test: IpSecAlgorithmTest Change-Id: I4662b0d43c476b744536a41000d578e8b69286ef --- core/java/android/net/IpSecAlgorithm.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 8f1e2defd2..268002f1dd 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -232,11 +232,10 @@ public final class IpSecAlgorithm implements Parcelable { ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO); ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO); - // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined - ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.S); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.S); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.S); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S); } private static final Set ENABLED_ALGOS = From 51fa8bd6d099fa478071f341df5696d4b5438e42 Mon Sep 17 00:00:00 2001 From: paulhu Date: Fri, 26 Feb 2021 11:19:41 +0800 Subject: [PATCH 569/881] Replace ConnectivityManager hidden symbols on framework Connectivity is becoming a mainline module in S, so ConnectivityManager hidden symbols can not be used for outside components. Besides, most Tethering relevant methods or variables on CM are migrated to TetheringManager. So replace all these methods or variables from ConnectivityManager to TetheringManager on Telephony on framework. Bug: 180693313 Test: atest FrameworksNetTests Change-Id: I14e032ad6f278a36e8756aa7045d73a403f8f059 --- .../core/java/com/android/server/net/NetworkStatsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 9706bcece9..870768c186 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -24,7 +24,6 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; @@ -45,6 +44,7 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; +import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.TrafficStats.UNSUPPORTED; From e553899c44c4a38eac2614ea92997cca5bd2133f Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 22 Jan 2021 20:59:50 +0800 Subject: [PATCH 570/881] [FUI08] Create NeworkStateSnapshot Since NetworkState has UnsupportedAppUsage APIs that cannot be changed, create another class for follow-up patches to expose as system API. Test: NetworkStateSnapshotTest Bug: 174123988 Change-Id: I54ef872847f34166aa34a79f6178c90ac12b6c72 --- .../android/net/NetworkStateSnapshot.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 core/java/android/net/NetworkStateSnapshot.java diff --git a/core/java/android/net/NetworkStateSnapshot.java b/core/java/android/net/NetworkStateSnapshot.java new file mode 100644 index 0000000000..881b373fa2 --- /dev/null +++ b/core/java/android/net/NetworkStateSnapshot.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Snapshot of network state. + * + * @hide + */ +public final class NetworkStateSnapshot implements Parcelable { + @NonNull + public final LinkProperties linkProperties; + @NonNull + public final NetworkCapabilities networkCapabilities; + @NonNull + public final Network network; + @Nullable + public final String subscriberId; + public final int legacyType; + + public NetworkStateSnapshot(@NonNull LinkProperties linkProperties, + @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, + @Nullable String subscriberId, int legacyType) { + this.linkProperties = Objects.requireNonNull(linkProperties); + this.networkCapabilities = Objects.requireNonNull(networkCapabilities); + this.network = Objects.requireNonNull(network); + this.subscriberId = subscriberId; + this.legacyType = legacyType; + } + + public NetworkStateSnapshot(@NonNull Parcel in) { + linkProperties = in.readParcelable(null); + networkCapabilities = in.readParcelable(null); + network = in.readParcelable(null); + subscriberId = in.readString(); + legacyType = in.readInt(); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeParcelable(linkProperties, flags); + out.writeParcelable(networkCapabilities, flags); + out.writeParcelable(network, flags); + out.writeString(subscriberId); + out.writeInt(legacyType); + } + + @NonNull + public static final Creator CREATOR = + new Creator() { + @NonNull + @Override + public NetworkStateSnapshot createFromParcel(@NonNull Parcel in) { + return new NetworkStateSnapshot(in); + } + + @NonNull + @Override + public NetworkStateSnapshot[] newArray(int size) { + return new NetworkStateSnapshot[size]; + } + }; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof NetworkStateSnapshot)) return false; + NetworkStateSnapshot that = (NetworkStateSnapshot) o; + return legacyType == that.legacyType + && Objects.equals(linkProperties, that.linkProperties) + && Objects.equals(networkCapabilities, that.networkCapabilities) + && Objects.equals(network, that.network) + && Objects.equals(subscriberId, that.subscriberId); + } + + @Override + public int hashCode() { + return Objects.hash(linkProperties, networkCapabilities, network, subscriberId, legacyType); + } +} From dd7831ded4f49af31a83be24b8a530917f344b41 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 2 Mar 2021 12:12:49 +0900 Subject: [PATCH 571/881] Move UidRange to connectivity UidRange is a data class that is an implementation detail of Connectivity. Move it to the connectivity boundary. Remaining usages of UidRange outside of Connectivity (in VPN) should be migrated to other classes, like Range or UidRangeParcel. Bug: 181512874 Test: m Change-Id: I6f2e3685ad1c07171dd90480d1e546329de8732d --- core/java/android/net/UidRange.aidl | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 core/java/android/net/UidRange.aidl diff --git a/core/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl deleted file mode 100644 index f70fc8e2fe..0000000000 --- a/core/java/android/net/UidRange.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.net; - -/** - * An inclusive range of UIDs. - * - * {@hide} - */ -parcelable UidRange; \ No newline at end of file From 73d79037dd94cf629f95ea111bf7dfd20db617bc Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 22 Jan 2021 22:46:01 +0800 Subject: [PATCH 572/881] [FUI17] Migrate NetworkStatsService to use NetworkStateSnapshot This change migrates NetworkStatsService and related code to use NetworkStateSnapshot which is used for replacing the NetworkState. This patch also changes some formating which is suggested by the linter. Test: FrameworksNetTests NetworkPolicyManagerServiceTest Bug: 174123988 Change-Id: I547da8f411cb45bdadc376ac3cadf3f3c55bb282 --- .../android/net/INetworkStatsService.aidl | 4 +- core/java/android/net/NetworkIdentity.java | 44 ++++++++++++------- .../server/net/NetworkStatsService.java | 41 +++++++++-------- 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 0baf11e850..dc3b88a7c3 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -19,7 +19,7 @@ package android.net; import android.net.DataUsageRequest; import android.net.INetworkStatsSession; import android.net.Network; -import android.net.NetworkState; +import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; @@ -68,7 +68,7 @@ interface INetworkStatsService { /** Force update of ifaces. */ void forceUpdateIfaces( in Network[] defaultNetworks, - in NetworkState[] networkStates, + in NetworkStateSnapshot[] snapshots, in String activeIface, in UnderlyingNetworkInfo[] underlyingNetworkInfos); /** Force update of statistics. */ diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 303a40755d..927db11ecd 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -18,7 +18,6 @@ package android.net; import static android.net.ConnectivityManager.TYPE_WIFI; -import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; @@ -180,29 +179,42 @@ public class NetworkIdentity implements Comparable { } /** - * Build a {@link NetworkIdentity} from the given {@link NetworkState} and {@code subType}, - * assuming that any mobile networks are using the current IMSI. The subType if applicable, - * should be set as one of the TelephonyManager.NETWORK_TYPE_* constants, or - * {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. + * Build a {@link NetworkIdentity} from the given {@link NetworkState} and + * {@code subType}, assuming that any mobile networks are using the current IMSI. + * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_* + * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. */ - public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, - boolean defaultNetwork, @NetworkType int subType) { - final int legacyType = state.legacyNetworkType; + // TODO: Delete this function after NetworkPolicyManagerService finishes the migration. + public static NetworkIdentity buildNetworkIdentity(Context context, + NetworkState state, boolean defaultNetwork, @NetworkType int subType) { + final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.linkProperties, + state.networkCapabilities, state.network, state.subscriberId, + state.legacyNetworkType); + return buildNetworkIdentity(context, snapshot, defaultNetwork, subType); + } - String subscriberId = null; + /** + * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and + * {@code subType}, assuming that any mobile networks are using the current IMSI. + * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_* + * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. + */ + public static NetworkIdentity buildNetworkIdentity(Context context, + NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) { + final int legacyType = snapshot.legacyType; + + final String subscriberId = snapshot.subscriberId; String networkId = null; - boolean roaming = !state.networkCapabilities.hasCapability( + boolean roaming = !snapshot.networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - boolean metered = !state.networkCapabilities.hasCapability( + boolean metered = !snapshot.networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - subscriberId = state.subscriberId; - - final int oemManaged = getOemBitfield(state.networkCapabilities); + final int oemManaged = getOemBitfield(snapshot.networkCapabilities); if (legacyType == TYPE_WIFI) { - if (state.networkCapabilities.getSsid() != null) { - networkId = state.networkCapabilities.getSsid(); + if (snapshot.networkCapabilities.getSsid() != null) { + networkId = snapshot.networkCapabilities.getSsid(); if (networkId == null) { // TODO: Figure out if this code path never runs. If so, remove them. final WifiManager wifi = (WifiManager) context.getSystemService( diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 5b9a11bc5a..3a5e10ed95 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -97,7 +97,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkStack; -import android.net.NetworkState; +import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; @@ -296,7 +296,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Last states of all networks sent from ConnectivityService. */ @GuardedBy("mStatsLock") @Nullable - private NetworkState[] mLastNetworkStates = null; + private NetworkStateSnapshot[] mLastNetworkStateSnapshots = null; private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -378,8 +378,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } case MSG_UPDATE_IFACES: { // If no cached states, ignore. - if (mLastNetworkStates == null) break; - updateIfaces(mDefaultNetworks, mLastNetworkStates, mActiveIface); + if (mLastNetworkStateSnapshots == null) break; + updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); break; } case MSG_PERFORM_POLL_REGISTER_ALERT: { @@ -967,10 +967,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - @Override public void forceUpdateIfaces( Network[] defaultNetworks, - NetworkState[] networkStates, + NetworkStateSnapshot[] networkStates, String activeIface, UnderlyingNetworkInfo[] underlyingNetworkInfos) { checkNetworkStackPermission(mContext); @@ -1248,13 +1247,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void updateIfaces( Network[] defaultNetworks, - NetworkState[] networkStates, + NetworkStateSnapshot[] snapshots, String activeIface) { synchronized (mStatsLock) { mWakeLock.acquire(); try { mActiveIface = activeIface; - updateIfacesLocked(defaultNetworks, networkStates); + updateIfacesLocked(defaultNetworks, snapshots); } finally { mWakeLock.release(); } @@ -1262,13 +1261,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Inspect all current {@link NetworkState} to derive mapping from {@code iface} to {@link - * NetworkStatsHistory}. When multiple networks are active on a single {@code iface}, + * Inspect all current {@link NetworkStateSnapshot}s to derive mapping from {@code iface} to + * {@link NetworkStatsHistory}. When multiple networks are active on a single {@code iface}, * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") private void updateIfacesLocked(@Nullable Network[] defaultNetworks, - @NonNull NetworkState[] states) { + @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1288,21 +1287,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mDefaultNetworks = defaultNetworks; } - mLastNetworkStates = states; + mLastNetworkStateSnapshots = snapshots; final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); - for (NetworkState state : states) { - final boolean isMobile = isNetworkTypeMobile(state.legacyNetworkType); - final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); + for (NetworkStateSnapshot snapshot : snapshots) { + final boolean isMobile = isNetworkTypeMobile(snapshot.legacyType); + final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.network); final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED - : getSubTypeForState(state); - final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, + : getSubTypeForStateSnapshot(snapshot); + final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot, isDefault, subType); // Traffic occurring on the base interface is always counted for // both total usage and UID details. - final String baseIface = state.linkProperties.getInterfaceName(); + final String baseIface = snapshot.linkProperties.getInterfaceName(); if (baseIface != null) { findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident); findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident); @@ -1312,7 +1311,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // If IMS is metered, then the IMS network usage has already included VT usage. // VT is considered always metered in framework's layer. If VT is not metered // per carrier's policy, modem will report 0 usage for VT calls. - if (state.networkCapabilities.hasCapability( + if (snapshot.networkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) { // Copy the identify from IMS one but mark it as metered. @@ -1358,7 +1357,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // (or non eBPF offloaded) TX they would appear on both, however egress interface // accounting is explicitly bypassed for traffic from the clat uid. // - final List stackedLinks = state.linkProperties.getStackedLinks(); + final List stackedLinks = snapshot.linkProperties.getStackedLinks(); for (LinkProperties stackedLink : stackedLinks) { final String stackedIface = stackedLink.getInterfaceName(); if (stackedIface != null) { @@ -1381,7 +1380,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different * transport types do not actually fill this value. */ - private int getSubTypeForState(@NonNull NetworkState state) { + private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) { if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return 0; } From 51392affe6a7473f6ece942a83d377410f2a3fee Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 30 Dec 2020 19:03:32 +0800 Subject: [PATCH 573/881] [FUI09] Expose NetworkStateSnapshot as system API This is needed by NetworkStatsService and NetworkPolicyManagerService to utilize the snapshots of information of networks that grabbed from ConnectivityService. Test: atest FrameworksNetTests NetworkPolicyManagerServiceTest Bug: 174123988 Change-Id: I7e974ef7b23ba9ba6ee775eed9899b0c0e2eca55 --- core/java/android/net/NetworkIdentity.java | 4 +- .../android/net/NetworkStateSnapshot.java | 51 +++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 927db11ecd..a5ece7b713 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -187,8 +187,8 @@ public class NetworkIdentity implements Comparable { // TODO: Delete this function after NetworkPolicyManagerService finishes the migration. public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, boolean defaultNetwork, @NetworkType int subType) { - final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.linkProperties, - state.networkCapabilities, state.network, state.subscriberId, + final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.network, + state.networkCapabilities, state.linkProperties, state.subscriberId, state.legacyNetworkType); return buildNetworkIdentity(context, snapshot, defaultNetwork, subType); } diff --git a/core/java/android/net/NetworkStateSnapshot.java b/core/java/android/net/NetworkStateSnapshot.java index 881b373fa2..b3d8d4e614 100644 --- a/core/java/android/net/NetworkStateSnapshot.java +++ b/core/java/android/net/NetworkStateSnapshot.java @@ -16,8 +16,11 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -28,31 +31,49 @@ import java.util.Objects; * * @hide */ +@SystemApi(client = MODULE_LIBRARIES) public final class NetworkStateSnapshot implements Parcelable { - @NonNull - public final LinkProperties linkProperties; - @NonNull - public final NetworkCapabilities networkCapabilities; + /** The network associated with this snapshot. */ @NonNull public final Network network; + + /** The {@link NetworkCapabilities} of the network associated with this snapshot. */ + @NonNull + public final NetworkCapabilities networkCapabilities; + + /** The {@link LinkProperties} of the network associated with this snapshot. */ + @NonNull + public final LinkProperties linkProperties; + + /** + * The Subscriber Id of the network associated with this snapshot. See + * {@link android.telephony.TelephonyManager#getSubscriberId()}. + */ @Nullable public final String subscriberId; + + /** + * The legacy type of the network associated with this snapshot. See + * {@code ConnectivityManager#TYPE_*}. + */ public final int legacyType; - public NetworkStateSnapshot(@NonNull LinkProperties linkProperties, - @NonNull NetworkCapabilities networkCapabilities, @NonNull Network network, + public NetworkStateSnapshot(@NonNull Network network, + @NonNull NetworkCapabilities networkCapabilities, + @NonNull LinkProperties linkProperties, @Nullable String subscriberId, int legacyType) { - this.linkProperties = Objects.requireNonNull(linkProperties); - this.networkCapabilities = Objects.requireNonNull(networkCapabilities); this.network = Objects.requireNonNull(network); + this.networkCapabilities = Objects.requireNonNull(networkCapabilities); + this.linkProperties = Objects.requireNonNull(linkProperties); this.subscriberId = subscriberId; this.legacyType = legacyType; } + /** @hide */ public NetworkStateSnapshot(@NonNull Parcel in) { - linkProperties = in.readParcelable(null); - networkCapabilities = in.readParcelable(null); network = in.readParcelable(null); + networkCapabilities = in.readParcelable(null); + linkProperties = in.readParcelable(null); subscriberId = in.readString(); legacyType = in.readInt(); } @@ -64,9 +85,9 @@ public final class NetworkStateSnapshot implements Parcelable { @Override public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeParcelable(linkProperties, flags); - out.writeParcelable(networkCapabilities, flags); out.writeParcelable(network, flags); + out.writeParcelable(networkCapabilities, flags); + out.writeParcelable(linkProperties, flags); out.writeString(subscriberId); out.writeInt(legacyType); } @@ -93,14 +114,14 @@ public final class NetworkStateSnapshot implements Parcelable { if (!(o instanceof NetworkStateSnapshot)) return false; NetworkStateSnapshot that = (NetworkStateSnapshot) o; return legacyType == that.legacyType - && Objects.equals(linkProperties, that.linkProperties) - && Objects.equals(networkCapabilities, that.networkCapabilities) && Objects.equals(network, that.network) + && Objects.equals(networkCapabilities, that.networkCapabilities) + && Objects.equals(linkProperties, that.linkProperties) && Objects.equals(subscriberId, that.subscriberId); } @Override public int hashCode() { - return Objects.hash(linkProperties, networkCapabilities, network, subscriberId, legacyType); + return Objects.hash(network, networkCapabilities, linkProperties, subscriberId, legacyType); } } From 124e136954fc9bfea1f804b1079f4cc062cca2c9 Mon Sep 17 00:00:00 2001 From: junyulai Date: Sat, 23 Jan 2021 11:00:10 +0800 Subject: [PATCH 574/881] [FUI18] Expose notifyNetworkStatus as system API Test: m -j doc-comment-check-docs Bug: 174123988 Change-Id: I11d4c9ab24de87fb2ad120e3787b78b73133e874 --- .../app/usage/NetworkStatsManager.java | 50 +++++++++++++++++++ .../server/net/NetworkStatsService.java | 9 ++-- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 1d5dc1d5df..098d8b6c60 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -16,6 +16,8 @@ package android.app.usage; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -28,8 +30,11 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.DataUsageRequest; import android.net.INetworkStatsService; +import android.net.Network; import android.net.NetworkStack; +import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; +import android.net.UnderlyingNetworkInfo; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; @@ -48,6 +53,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.NetworkIdentityUtils; +import java.util.List; import java.util.Objects; /** @@ -633,6 +639,50 @@ public class NetworkStatsManager { return template; } + /** + * Notify {@code NetworkStatsService} about network status changed. + * + * Notifies NetworkStatsService of network state changes for data usage accounting purposes. + * + * To avoid races that attribute data usage to wrong network, such as new network with + * the same interface after SIM hot-swap, this function will not return until + * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from + * all data sources. + * + * @param defaultNetworks the list of all networks that could be used by network traffic that + * does not explicitly select a network. + * @param networkStateSnapshots a list of {@link NetworkStateSnapshot}s, one for + * each network that is currently connected. + * @param activeIface the active (i.e., connected) default network interface for the calling + * uid. Used to determine on which network future calls to + * {@link android.net.TrafficStats#incrementOperationCount} applies to. + * @param underlyingNetworkInfos the list of underlying network information for all + * currently-connected VPNs. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void notifyNetworkStatus( + @NonNull List defaultNetworks, + @NonNull List networkStateSnapshots, + @Nullable String activeIface, + @NonNull List underlyingNetworkInfos) { + try { + Objects.requireNonNull(defaultNetworks); + Objects.requireNonNull(networkStateSnapshots); + Objects.requireNonNull(underlyingNetworkInfos); + // TODO: Change internal namings after the name is decided. + mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]), + networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface, + underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0])); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private static class CallbackHandler extends Handler { private final int mNetworkType; private final String mSubscriberId; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3a5e10ed95..ebf1fe9d7c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -379,6 +379,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { case MSG_UPDATE_IFACES: { // If no cached states, ignore. if (mLastNetworkStateSnapshots == null) break; + // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing. updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); break; } @@ -1266,7 +1267,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(@Nullable Network[] defaultNetworks, + private void updateIfacesLocked(@NonNull Network[] defaultNetworks, @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1282,10 +1283,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); - if (defaultNetworks != null) { - // Caller is ConnectivityService. Update the list of default networks. - mDefaultNetworks = defaultNetworks; - } + // Update the list of default networks. + mDefaultNetworks = defaultNetworks; mLastNetworkStateSnapshots = snapshots; From 87107539df3369428f7e74a7874739f0846200f8 Mon Sep 17 00:00:00 2001 From: junyulai Date: Sat, 23 Jan 2021 11:00:10 +0800 Subject: [PATCH 575/881] [FUI18] Expose notifyNetworkStatus as system API Test: m -j doc-comment-check-docs Bug: 174123988 Merged-In: I11d4c9ab24de87fb2ad120e3787b78b73133e874 Change-Id: I11d4c9ab24de87fb2ad120e3787b78b73133e874 (cherry-picked from ag/13749978) --- .../app/usage/NetworkStatsManager.java | 50 +++++++++++++++++++ .../server/net/NetworkStatsService.java | 9 ++-- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 1d5dc1d5df..098d8b6c60 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -16,6 +16,8 @@ package android.app.usage; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -28,8 +30,11 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.DataUsageRequest; import android.net.INetworkStatsService; +import android.net.Network; import android.net.NetworkStack; +import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; +import android.net.UnderlyingNetworkInfo; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; @@ -48,6 +53,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.net.module.util.NetworkIdentityUtils; +import java.util.List; import java.util.Objects; /** @@ -633,6 +639,50 @@ public class NetworkStatsManager { return template; } + /** + * Notify {@code NetworkStatsService} about network status changed. + * + * Notifies NetworkStatsService of network state changes for data usage accounting purposes. + * + * To avoid races that attribute data usage to wrong network, such as new network with + * the same interface after SIM hot-swap, this function will not return until + * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from + * all data sources. + * + * @param defaultNetworks the list of all networks that could be used by network traffic that + * does not explicitly select a network. + * @param networkStateSnapshots a list of {@link NetworkStateSnapshot}s, one for + * each network that is currently connected. + * @param activeIface the active (i.e., connected) default network interface for the calling + * uid. Used to determine on which network future calls to + * {@link android.net.TrafficStats#incrementOperationCount} applies to. + * @param underlyingNetworkInfos the list of underlying network information for all + * currently-connected VPNs. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void notifyNetworkStatus( + @NonNull List defaultNetworks, + @NonNull List networkStateSnapshots, + @Nullable String activeIface, + @NonNull List underlyingNetworkInfos) { + try { + Objects.requireNonNull(defaultNetworks); + Objects.requireNonNull(networkStateSnapshots); + Objects.requireNonNull(underlyingNetworkInfos); + // TODO: Change internal namings after the name is decided. + mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]), + networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface, + underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0])); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private static class CallbackHandler extends Handler { private final int mNetworkType; private final String mSubscriberId; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3a5e10ed95..ebf1fe9d7c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -379,6 +379,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { case MSG_UPDATE_IFACES: { // If no cached states, ignore. if (mLastNetworkStateSnapshots == null) break; + // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing. updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); break; } @@ -1266,7 +1267,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(@Nullable Network[] defaultNetworks, + private void updateIfacesLocked(@NonNull Network[] defaultNetworks, @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1282,10 +1283,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); - if (defaultNetworks != null) { - // Caller is ConnectivityService. Update the list of default networks. - mDefaultNetworks = defaultNetworks; - } + // Update the list of default networks. + mDefaultNetworks = defaultNetworks; mLastNetworkStateSnapshots = snapshots; From 6ea46aec25e32ded5e5b012a1c279ceae30dc220 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 3 Mar 2021 12:09:05 +0800 Subject: [PATCH 576/881] [FUI22] Support getAllNetworkStateSnapshot Currently, ConnectivityService has getAllNetworkState but it is not ideal to expose as system API since the plan is to get rid of NetworkState. Thus, create a new one that returns NetworkStateSnapshot to fulfill the needs. Note the original getAllNetworkState cannot be deleted now since it has @UnsupportedAppUsage annotation. Test: atest FrameworksNetTests Bug: 174123988 Change-Id: Icddd434552b0e9ecbc8299e7242ec88cf3145aca --- core/java/android/net/NetworkStateSnapshot.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/java/android/net/NetworkStateSnapshot.java b/core/java/android/net/NetworkStateSnapshot.java index b3d8d4e614..0d26c2de86 100644 --- a/core/java/android/net/NetworkStateSnapshot.java +++ b/core/java/android/net/NetworkStateSnapshot.java @@ -24,6 +24,8 @@ import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import com.android.net.module.util.NetworkIdentityUtils; + import java.util.Objects; /** @@ -124,4 +126,15 @@ public final class NetworkStateSnapshot implements Parcelable { public int hashCode() { return Objects.hash(network, networkCapabilities, linkProperties, subscriberId, legacyType); } + + @Override + public String toString() { + return "NetworkStateSnapshot{" + + "network=" + network + + ", networkCapabilities=" + networkCapabilities + + ", linkProperties=" + linkProperties + + ", subscriberId='" + NetworkIdentityUtils.scrubSubscriberId(subscriberId) + '\'' + + ", legacyType=" + legacyType + + '}'; + } } From ebd239c88efa20518b2bb4da38960ee0c77dba99 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Fri, 5 Mar 2021 00:13:10 +0000 Subject: [PATCH 577/881] Revert "Use VERSION_CODES.S instead of VERSION_CODES.R + 1" This reverts commit 1745f3a7592fae9f572027f46df6441e61dc2bf5. Reason for revert: 1. The BUILD_VERSIONS.S is 1000, and thus it will prevent the code from requiring new algorithms on devices whose first sdk is 31 (e.g. cuttlefish), though these devices should be treated as first launched with SDK S. 2. It will break #testValidationForAlgosAddedInS, because the test code is using BUILD_VERSIONS.R to gate the test, which is inconsistent with the implementation. Bug: 181887451 Test: atest IpSecAlgorithmTest Change-Id: I5cd717c5ebd6086ae5cf9abf76311ae4fca0c6e9 --- core/java/android/net/IpSecAlgorithm.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 268002f1dd..8f1e2defd2 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -232,10 +232,11 @@ public final class IpSecAlgorithm implements Parcelable { ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO); ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO); - ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.S); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.S); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.S); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S); + // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined + ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1); } private static final Set ENABLED_ALGOS = From 5681dfba9c269b26d8e35c5f953ca309ad19de34 Mon Sep 17 00:00:00 2001 From: lifr Date: Wed, 3 Mar 2021 23:24:12 +0800 Subject: [PATCH 578/881] [CS07]Remove hidden API usage of NetworkCapabilities The connection service will become the mainline module. The mutable NetworkCapabilities is deprecated, and the NetworkCapabilities should be built through their Builder instead. Bug: 170598012 Test: atest EthernetServiceTests Change-Id: I09661ddda24d652ed791a7c6b093541e20a15e77 --- .../server/ethernet/EthernetTracker.java | 29 ++++---- .../server/ethernet/EthernetTrackerTest.java | 66 +++++-------------- 2 files changed, 30 insertions(+), 65 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 05b2782216..a831f34a5a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -459,7 +459,7 @@ final class EthernetTracker { String transport = tokens.length > 3 ? tokens[3] : null; NetworkCapabilities nc = createNetworkCapabilities( !TextUtils.isEmpty(capabilities) /* clear default capabilities */, capabilities, - transport); + transport).build(); mNetworkCapabilities.put(name, nc); if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) { @@ -469,25 +469,26 @@ final class EthernetTracker { } private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) { - NetworkCapabilities nc = createNetworkCapabilities(false /* clear default capabilities */); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + NetworkCapabilities.Builder builder = createNetworkCapabilities( + false /* clear default capabilities */, null, null) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); if (isTestIface) { - nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST); + builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST); } else { - nc.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } - return nc; + return builder.build(); } private static NetworkCapabilities createNetworkCapabilities(boolean clearDefaultCapabilities) { - return createNetworkCapabilities(clearDefaultCapabilities, null, null); + return createNetworkCapabilities(clearDefaultCapabilities, null, null).build(); } /** @@ -502,7 +503,7 @@ final class EthernetTracker { * will cause the override to be ignored. */ @VisibleForTesting - static NetworkCapabilities createNetworkCapabilities( + static NetworkCapabilities.Builder createNetworkCapabilities( boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities, @Nullable String overrideTransport) { @@ -566,7 +567,7 @@ final class EthernetTracker { builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); - return builder.build(); + return builder; } /** diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 12187889ac..43571bbc37 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -133,11 +133,11 @@ public class EthernetTrackerTest { } } - private NetworkCapabilitiesBuilder makeEthernetCapabilitiesBuilder(boolean clearAll) { - final NetworkCapabilitiesBuilder result = - clearAll ? new NetworkCapabilitiesBuilder().clearAll() - : new NetworkCapabilitiesBuilder(); - return result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) + private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) { + final NetworkCapabilities.Builder builder = + clearAll ? new NetworkCapabilities.Builder().clearAll() + : new NetworkCapabilities.Builder(); + return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); } @@ -153,14 +153,14 @@ public class EthernetTrackerTest { makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build(); NetworkCapabilities ethernetClearedWithCommonCaps = makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .addCapability(12) .addCapability(13) .addCapability(14) @@ -177,7 +177,7 @@ public class EthernetTrackerTest { makeEthernetCapabilitiesBuilder(false /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build(), false, "", ""); @@ -187,7 +187,7 @@ public class EthernetTrackerTest { makeEthernetCapabilitiesBuilder(false /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(NetworkCapabilities.TRANSPORT_ETHERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .addCapability(11) .addCapability(12) .build(), @@ -207,28 +207,28 @@ public class EthernetTrackerTest { makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(0) + .addTransportType(0) .build(), true, "", "0"); assertParsedNetworkCapabilities( makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(1) + .addTransportType(1) .build(), true, "", "1"); assertParsedNetworkCapabilities( makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(2) + .addTransportType(2) .build(), true, "", "2"); assertParsedNetworkCapabilities( makeEthernetCapabilitiesBuilder(true /* clearAll */) .setLinkUpstreamBandwidthKbps(100000) .setLinkDownstreamBandwidthKbps(100000) - .addTransport(3) + .addTransportType(3) .build(), true, "", "3"); @@ -256,7 +256,7 @@ public class EthernetTrackerTest { .addCapability(13) .addCapability(14) .addCapability(15) - .addTransport(3) + .addTransportType(3) .build(), true, "12,13,14,15", "3"); @@ -268,42 +268,6 @@ public class EthernetTrackerTest { boolean clearCapabilties, String configCapabiltiies,String configTransports) { assertEquals(expectedNetworkCapabilities, EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies, - configTransports)); - } - - private static class NetworkCapabilitiesBuilder { - private final NetworkCapabilities nc = new NetworkCapabilities(); - - NetworkCapabilitiesBuilder clearAll(){ - // This is THE ONLY one that doesn't return a reference to the object so I wrapped - // everything in a builder to keep things consistent and clean above. Fix if this - // ever changes - nc.clearAll(); - return this; - } - - NetworkCapabilitiesBuilder addCapability(int capability) { - nc.addCapability(capability); - return this; - } - - NetworkCapabilitiesBuilder addTransport(int transport) { - nc.addTransportType(transport); - return this; - } - - NetworkCapabilitiesBuilder setLinkUpstreamBandwidthKbps(int upKbps) { - nc.setLinkUpstreamBandwidthKbps(upKbps); - return this; - } - - NetworkCapabilitiesBuilder setLinkDownstreamBandwidthKbps(int downKbps) { - nc.setLinkDownstreamBandwidthKbps(downKbps); - return this; - } - - NetworkCapabilities build() { - return new NetworkCapabilities(nc); - } + configTransports).build()); } } From 50d48b94c7a28439e1efa81cc01bcd245e4c3e2a Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 4 Feb 2021 16:36:24 +0900 Subject: [PATCH 579/881] Rename StringNetworkSpecifier to Ethernet The new specifier represents ethernet interfaces more specifically and is part of the public API. Bug: 179329291 Test: atest CtsNetTestCases Change-Id: I6cba1709b3007a22d95849a1281237c77e1464a4 --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index b9ebf8974e..dba152cc4e 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.ConnectivityManager; +import android.net.EthernetNetworkSpecifier; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -33,7 +34,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkRequest; import android.net.NetworkSpecifier; -import android.net.StringNetworkSpecifier; import android.net.ip.IIpClient; import android.net.ip.IpClientCallbacks; import android.net.ip.IpClientUtil; @@ -219,8 +219,9 @@ public class EthernetNetworkFactory extends NetworkFactory { String requestedIface = null; NetworkSpecifier specifier = request.getNetworkSpecifier(); - if (specifier instanceof StringNetworkSpecifier) { - requestedIface = ((StringNetworkSpecifier) specifier).specifier; + if (specifier instanceof EthernetNetworkSpecifier) { + requestedIface = ((EthernetNetworkSpecifier) specifier) + .getInterfaceName(); } NetworkInterfaceState network = null; From 651a096e6f77a8cce5b9370e9c1199a6ad184ab1 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 8 Mar 2021 15:58:34 +0800 Subject: [PATCH 580/881] Replace ConnectivityManager.isNetworkTypeMobile usage in NSS ConnectivityManager is a part of connectivity mainline. The hidden methods dependency in ConnectivityManager should be removed to make it a moudle. NSS use isNetworkTypeMobile to check if the NetworkState belongs to a cellular network or not. It should be replaced by the NetworkCapabilities inside the NetworkState. The result of isNetworkTypeMobile relies on the legacy network type. The legacy network type comes from the network type of its network info. The replacement should consider VPN active case because the network type will not be TYPE_MOBILE. Thus, replace it with Networkcapabilities.getDisplayTransport() to get a transport that can be used to classify a network when displaying its info to users, i.e. it will return TRANSPORT_VPN for a vpn network on cellular network. Bug: 172183305 Test: atest FrameworksNetTests Change-Id: I2132a7288a93e4430cbd9efabc33ae56ce8bdd9b --- .../java/com/android/server/net/NetworkStatsService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index e0f534602d..7b376847fd 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -24,7 +24,6 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.ConnectivityManager.isNetworkTypeMobile; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; @@ -71,6 +70,7 @@ import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.SECOND_IN_MILLIS; +import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport; import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; @@ -1291,7 +1291,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkStateSnapshot snapshot : snapshots) { - final boolean isMobile = isNetworkTypeMobile(snapshot.legacyType); + final int displayTransport = + getDisplayTransport(snapshot.networkCapabilities.getTransportTypes()); + final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.network); final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED : getSubTypeForStateSnapshot(snapshot); From aa5bdbffacd69ce24b11c09d4eff74747dea5b17 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 4 Feb 2021 14:20:19 +0900 Subject: [PATCH 581/881] Add Ethernet, TestNetworkSpecifier API Rename StringNetworkSpecifier to EthernetNetworkSpecifier (its only production user), and make it module-lib API. The original StringNetworkSpecifier file is actually kept to satisfy some invalid dependencies; it will be removed separately. This allows specifying an Ethernet interface with a non-deprecated API: until this change the only way to do so would be to use NetworkRequest#setSpecifier(String), which is deprecated. Similarly, add the TestNetworkSpecifier API for TestNetworkManager, to replace previous usage of StringNetworkSpecifier. TestNetworkManager is module API, so TestNetworkSpecifier should be module API too. This allows tests to request the test interface specifically, without using the deprecated NetworkRequest#setSpecifier(String). Bug: 179329291 Test: m Change-Id: Iee569f5c8bbdc4bc979610e1191308281f3d4620 --- .../android/net/EthernetNetworkSpecifier.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 core/java/android/net/EthernetNetworkSpecifier.java diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/core/java/android/net/EthernetNetworkSpecifier.java new file mode 100644 index 0000000000..e1685887e8 --- /dev/null +++ b/core/java/android/net/EthernetNetworkSpecifier.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * A {@link NetworkSpecifier} used to identify ethernet interfaces. + * + * @see EthernetManager + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable { + + /** + * Name of the network interface. + */ + @NonNull + private final String mInterfaceName; + + public EthernetNetworkSpecifier(@NonNull String interfaceName) { + Preconditions.checkStringNotEmpty(interfaceName); + mInterfaceName = interfaceName; + } + + // This may be null in the future to support specifiers based on data other than the interface + // name. + @Nullable + public String getInterfaceName() { + return mInterfaceName; + } + + @Override + public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { + return equals(other); + } + + @Override + public boolean equals(@Nullable Object o) { + if (!(o instanceof EthernetNetworkSpecifier)) return false; + return TextUtils.equals(mInterfaceName, ((EthernetNetworkSpecifier) o).mInterfaceName); + } + + @Override + public int hashCode() { + return Objects.hashCode(mInterfaceName); + } + + @Override + public String toString() { + return "EthernetNetworkSpecifier (" + mInterfaceName + ")"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mInterfaceName); + } + + public static final @NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public EthernetNetworkSpecifier createFromParcel(Parcel in) { + return new EthernetNetworkSpecifier(in.readString()); + } + public EthernetNetworkSpecifier[] newArray(int size) { + return new EthernetNetworkSpecifier[size]; + } + }; +} From 2d5af929269778cd8e61e52981a8b864bd06176f Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 9 Mar 2021 09:31:17 +0000 Subject: [PATCH 582/881] Remove unused buildNetworkIdentity The overload using a NetworkState is now unused. Bug: 174123988 Change-Id: I22f2d2fffd2d70c08097d3217f01393ff8e75ab5 Test: m --- core/java/android/net/NetworkIdentity.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index a5ece7b713..b037261f0b 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -178,21 +178,6 @@ public class NetworkIdentity implements Comparable { return mOemManaged; } - /** - * Build a {@link NetworkIdentity} from the given {@link NetworkState} and - * {@code subType}, assuming that any mobile networks are using the current IMSI. - * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_* - * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. - */ - // TODO: Delete this function after NetworkPolicyManagerService finishes the migration. - public static NetworkIdentity buildNetworkIdentity(Context context, - NetworkState state, boolean defaultNetwork, @NetworkType int subType) { - final NetworkStateSnapshot snapshot = new NetworkStateSnapshot(state.network, - state.networkCapabilities, state.linkProperties, state.subscriberId, - state.legacyNetworkType); - return buildNetworkIdentity(context, snapshot, defaultNetwork, subType); - } - /** * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and * {@code subType}, assuming that any mobile networks are using the current IMSI. From b77d80da8cc36a7fa4369f2bce793a7309dcc7a6 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 4 Feb 2021 16:36:24 +0900 Subject: [PATCH 583/881] Rename StringNetworkSpecifier to Ethernet The new specifier represents ethernet interfaces more specifically and is part of the public API. Bug: 179329291 Test: atest CtsNetTestCases Merged-In: I6cba1709b3007a22d95849a1281237c77e1464a4 Change-Id: I6cba1709b3007a22d95849a1281237c77e1464a4 --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index b9ebf8974e..dba152cc4e 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.ConnectivityManager; +import android.net.EthernetNetworkSpecifier; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -33,7 +34,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkRequest; import android.net.NetworkSpecifier; -import android.net.StringNetworkSpecifier; import android.net.ip.IIpClient; import android.net.ip.IpClientCallbacks; import android.net.ip.IpClientUtil; @@ -219,8 +219,9 @@ public class EthernetNetworkFactory extends NetworkFactory { String requestedIface = null; NetworkSpecifier specifier = request.getNetworkSpecifier(); - if (specifier instanceof StringNetworkSpecifier) { - requestedIface = ((StringNetworkSpecifier) specifier).specifier; + if (specifier instanceof EthernetNetworkSpecifier) { + requestedIface = ((EthernetNetworkSpecifier) specifier) + .getInterfaceName(); } NetworkInterfaceState network = null; From fafaa4751a751918bf0053cfe28a8c3330f0a09a Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 10 Mar 2021 17:41:00 +0900 Subject: [PATCH 584/881] Annotate NSM heavy methods with @WorkerThread Test: TH Bug: 181906747 Change-Id: Ia30273466c1b91a3dcc5d36dac61f92185dec96e --- .../android/app/usage/NetworkStatsManager.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 098d8b6c60..9f1132b605 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -24,6 +24,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.annotation.WorkerThread; import android.app.usage.NetworkStats.Bucket; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -201,6 +202,7 @@ public class NetworkStatsManager { * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, * metered {@link NetworkStats.Bucket#METERED_ALL}, * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -219,6 +221,7 @@ public class NetworkStatsManager { * @return Bucket object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public Bucket querySummaryForDevice(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -240,6 +243,7 @@ public class NetworkStatsManager { * uid {@link NetworkStats.Bucket#UID_ALL}, tag {@link NetworkStats.Bucket#TAG_NONE}, * metered {@link NetworkStats.Bucket#METERED_ALL}, and roaming * {@link NetworkStats.Bucket#ROAMING_ALL}. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -258,6 +262,7 @@ public class NetworkStatsManager { * @return Bucket object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public Bucket querySummaryForUser(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -283,6 +288,7 @@ public class NetworkStatsManager { * means buckets' start and end timestamps are going to be the same as the 'startTime' and * 'endTime' parameters. State, uid, metered, and roaming are going to vary, and tag is going to * be the same. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -301,6 +307,7 @@ public class NetworkStatsManager { * @return Statistics object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public NetworkStats querySummary(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; @@ -326,9 +333,11 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid. + * This may take a long time, and apps should avoid calling this on their main thread. * * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ + @WorkerThread public NetworkStats queryDetailsForUid(int networkType, String subscriberId, long startTime, long endTime, int uid) throws SecurityException { return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, @@ -344,9 +353,11 @@ public class NetworkStatsManager { /** * Query network usage statistics details for a given uid and tag. + * This may take a long time, and apps should avoid calling this on their main thread. * * @see #queryDetailsForUidTagState(int, String, long, long, int, int, int) */ + @WorkerThread public NetworkStats queryDetailsForUidTag(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag) throws SecurityException { return queryDetailsForUidTagState(networkType, subscriberId, startTime, endTime, uid, @@ -365,6 +376,7 @@ public class NetworkStatsManager { *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -387,6 +399,7 @@ public class NetworkStatsManager { * @return Statistics object or null if an error happened during statistics collection. * @throws SecurityException if permissions are insufficient to read network statistics. */ + @WorkerThread public NetworkStats queryDetailsForUidTagState(int networkType, String subscriberId, long startTime, long endTime, int uid, int tag, int state) throws SecurityException { NetworkTemplate template; @@ -425,6 +438,7 @@ public class NetworkStatsManager { *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -443,6 +457,7 @@ public class NetworkStatsManager { * @return Statistics object or null if permissions are insufficient or error happened during * statistics collection. */ + @WorkerThread public NetworkStats queryDetails(int networkType, String subscriberId, long startTime, long endTime) throws SecurityException, RemoteException { NetworkTemplate template; From c9f9c3c5d20ea1a7db354929686d15822f6b1ff0 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 4 Feb 2021 14:20:19 +0900 Subject: [PATCH 585/881] Add Ethernet, TestNetworkSpecifier API Rename StringNetworkSpecifier to EthernetNetworkSpecifier (its only production user), and make it module-lib API. The original StringNetworkSpecifier file is actually kept to satisfy some invalid dependencies; it will be removed separately. This allows specifying an Ethernet interface with a non-deprecated API: until this change the only way to do so would be to use NetworkRequest#setSpecifier(String), which is deprecated. Similarly, add the TestNetworkSpecifier API for TestNetworkManager, to replace previous usage of StringNetworkSpecifier. TestNetworkManager is module API, so TestNetworkSpecifier should be module API too. This allows tests to request the test interface specifically, without using the deprecated NetworkRequest#setSpecifier(String). Bug: 179329291 Test: m Merged-In: Iee569f5c8bbdc4bc979610e1191308281f3d4620 Change-Id: Iee569f5c8bbdc4bc979610e1191308281f3d4620 --- .../android/net/EthernetNetworkSpecifier.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 core/java/android/net/EthernetNetworkSpecifier.java diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/core/java/android/net/EthernetNetworkSpecifier.java new file mode 100644 index 0000000000..e1685887e8 --- /dev/null +++ b/core/java/android/net/EthernetNetworkSpecifier.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.util.Preconditions; + +import java.util.Objects; + +/** + * A {@link NetworkSpecifier} used to identify ethernet interfaces. + * + * @see EthernetManager + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable { + + /** + * Name of the network interface. + */ + @NonNull + private final String mInterfaceName; + + public EthernetNetworkSpecifier(@NonNull String interfaceName) { + Preconditions.checkStringNotEmpty(interfaceName); + mInterfaceName = interfaceName; + } + + // This may be null in the future to support specifiers based on data other than the interface + // name. + @Nullable + public String getInterfaceName() { + return mInterfaceName; + } + + @Override + public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { + return equals(other); + } + + @Override + public boolean equals(@Nullable Object o) { + if (!(o instanceof EthernetNetworkSpecifier)) return false; + return TextUtils.equals(mInterfaceName, ((EthernetNetworkSpecifier) o).mInterfaceName); + } + + @Override + public int hashCode() { + return Objects.hashCode(mInterfaceName); + } + + @Override + public String toString() { + return "EthernetNetworkSpecifier (" + mInterfaceName + ")"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mInterfaceName); + } + + public static final @NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + public EthernetNetworkSpecifier createFromParcel(Parcel in) { + return new EthernetNetworkSpecifier(in.readString()); + } + public EthernetNetworkSpecifier[] newArray(int size) { + return new EthernetNetworkSpecifier[size]; + } + }; +} From 0ac4bcfb4ca677ab0657a1b6a2625fbaf8360d78 Mon Sep 17 00:00:00 2001 From: lifr Date: Thu, 4 Mar 2021 00:35:22 +0800 Subject: [PATCH 586/881] [CS09]Remove hidden API usage of NetworkRequest The connection service will become the mainline module. So, need to remove the hidden API usage of NetworkRequest. The NetworkRequest.type(TRACK_DEFAULT) is no longer sent to the factories. So, remove the (TRACK_DEFAULT) check to avoid using hidden API. Bug: 170598012 Test: atest EthernetServiceTests Change-Id: I5b5fed864318e9ac7e190c40d4f52076ab0eece8 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index b9ebf8974e..242fac8d8c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -88,10 +88,6 @@ public class EthernetNetworkFactory extends NetworkFactory { @Override public boolean acceptRequest(NetworkRequest request) { - if (request.type == NetworkRequest.Type.TRACK_DEFAULT) { - return false; - } - if (DBG) { Log.d(TAG, "acceptRequest, request: " + request); } From 2c264d7a259cf4812258825ee14ccf415be4b4f4 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 11 Mar 2021 17:39:49 +0800 Subject: [PATCH 587/881] Use new API - getIpSecNetIdRange() in IpSecService Use new API - getIpSecNetIdRange() to get the network ID range of IPSec tunnel interface. Bug: 172183305 Test: atest FrameworksNetTests:IpSecServiceTest Change-Id: Ib80f814f991e9f000a68f5c539d15d97cf56930e --- .../java/com/android/server/IpSecService.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 81d4b9da63..4c3c6ef21f 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -56,6 +56,7 @@ import android.system.Os; import android.system.OsConstants; import android.text.TextUtils; import android.util.Log; +import android.util.Range; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -756,13 +757,9 @@ public class IpSecService extends IIpSecService.Stub { } } - // These values have been reserved in NetIdManager - @VisibleForTesting static final int TUN_INTF_NETID_START = 0xFC00; - - public static final int TUN_INTF_NETID_RANGE = 0x0400; - private final SparseBooleanArray mTunnelNetIds = new SparseBooleanArray(); - private int mNextTunnelNetIdIndex = 0; + final Range mNetIdRange = ConnectivityManager.getIpSecNetIdRange(); + private int mNextTunnelNetId = mNetIdRange.getLower(); /** * Reserves a netId within the range of netIds allocated for IPsec tunnel interfaces @@ -775,11 +772,13 @@ public class IpSecService extends IIpSecService.Stub { */ @VisibleForTesting int reserveNetId() { + final int range = mNetIdRange.getUpper() - mNetIdRange.getLower() + 1; synchronized (mTunnelNetIds) { - for (int i = 0; i < TUN_INTF_NETID_RANGE; i++) { - int index = mNextTunnelNetIdIndex; - int netId = index + TUN_INTF_NETID_START; - if (++mNextTunnelNetIdIndex >= TUN_INTF_NETID_RANGE) mNextTunnelNetIdIndex = 0; + for (int i = 0; i < range; i++) { + final int netId = mNextTunnelNetId; + if (++mNextTunnelNetId > mNetIdRange.getUpper()) { + mNextTunnelNetId = mNetIdRange.getLower(); + } if (!mTunnelNetIds.get(netId)) { mTunnelNetIds.put(netId, true); return netId; From efbedc78e5c4a6294ae470560bc69461720663b4 Mon Sep 17 00:00:00 2001 From: Zhengyu Zhan Date: Wed, 6 Jan 2021 19:39:14 +0800 Subject: [PATCH 588/881] Support Dual ViLTE stats Some operator supports multiple VILTE, both two SIM cards can make VILTE call. We need to record VILTE data to different interface. Now NetworkStatsService has only one VILTE data interface: "vt_data0". All VILTE data stats will be recorded in this interface. Bug: 130871087 Test: NetworkStatsServiceTest#testDualVilteProviderStats Change-Id: I000ec756827bc42cac88dd0a2ca6b7999252357e --- .../server/net/NetworkStatsService.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 7b376847fd..de14831ec3 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -24,6 +24,7 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; @@ -65,6 +66,7 @@ import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; @@ -101,7 +103,9 @@ import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; +import android.net.NetworkSpecifier; import android.net.NetworkTemplate; +import android.net.TelephonyNetworkSpecifier; import android.net.TrafficStats; import android.net.UnderlyingNetworkInfo; import android.net.Uri; @@ -1320,8 +1324,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), ident.getRoaming(), true /* metered */, true /* onDefaultNetwork */, ident.getOemManaged()); - findOrCreateNetworkIdentitySet(mActiveIfaces, IFACE_VT).add(vtIdent); - findOrCreateNetworkIdentitySet(mActiveUidIfaces, IFACE_VT).add(vtIdent); + final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot); + findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent); + findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent); } if (isMobile) { @@ -1376,6 +1381,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]); } + private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { + if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR"); + } + + final NetworkSpecifier spec = state.networkCapabilities.getNetworkSpecifier(); + if (spec instanceof TelephonyNetworkSpecifier) { + return ((TelephonyNetworkSpecifier) spec).getSubscriptionId(); + } else { + Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier"); + return INVALID_SUBSCRIPTION_ID; + } + } + /** * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different From 1345717eec7c7e9f31cd14703551fbd83fbfed75 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 18 Mar 2021 14:45:22 +0800 Subject: [PATCH 589/881] Use clearAll() of NetworkCapabilities.Builder instead NetworkCapabilities#clearAll() is a hidden API, use clearAll() of NetworkCapabilities.Builder instead. Bug: 182963415 Test: m ethernet-service Test: atest EthernetServiceTests Change-Id: I87745b5f7a5817f95cdbc623b2313c181ff48f19 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index d17595ac9f..ad48844224 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -166,8 +166,9 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void updateCapabilityFilter() { - NetworkCapabilities capabilitiesFilter = new NetworkCapabilities(); - capabilitiesFilter.clearAll(); + NetworkCapabilities capabilitiesFilter = new NetworkCapabilities.Builder() + .clearAll() + .build(); for (NetworkInterfaceState iface: mTrackingInterfaces.values()) { capabilitiesFilter = mixInCapabilities(capabilitiesFilter, iface.mCapabilities); From de53718906374e33dfce1007de16c3b131ee52f4 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 19 Mar 2021 14:09:44 +0800 Subject: [PATCH 590/881] Replace references of request.networkCapabilies Replaced by request.canBesatisfiedBy() to avoid direct reference of hidden member. Bug: 182963415 Test: m ethernet-service Test: atest EthernetServiceTests Change-Id: I2a27410a6148c525e17a11cb1ba3570f04e60b5d --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index ad48844224..89334ba01a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -17,6 +17,7 @@ package com.android.server.ethernet; import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; + import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -50,8 +51,8 @@ import android.util.SparseArray; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; -import java.util.concurrent.ConcurrentHashMap; import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; /** * {@link NetworkFactory} that represents Ethernet networks. @@ -224,12 +225,12 @@ public class EthernetNetworkFactory extends NetworkFactory { NetworkInterfaceState network = null; if (!TextUtils.isEmpty(requestedIface)) { NetworkInterfaceState n = mTrackingInterfaces.get(requestedIface); - if (n != null && n.satisfied(request.networkCapabilities)) { + if (n != null && request.canBeSatisfiedBy(n.mCapabilities)) { network = n; } } else { for (NetworkInterfaceState n : mTrackingInterfaces.values()) { - if (n.satisfied(request.networkCapabilities) && n.mLinkUp) { + if (request.canBeSatisfiedBy(n.mCapabilities) && n.mLinkUp) { network = n; break; } From ddfc20d4f1639aa67e734011e3a2ad95f908665a Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 19 Mar 2021 14:15:39 +0800 Subject: [PATCH 591/881] Replace reference of NetworkAgent#setLegacyExtraInfo Bug: 182963415 Test: m ethernet-service Test: atest EthernetServiceTests Change-Id: I4a66f34daa129b3158e4dd2fb720c175611eaf69 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 89334ba01a..75e77b9596 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -473,6 +473,7 @@ public class EthernetNetworkFactory extends NetworkFactory { final NetworkAgentConfig config = new NetworkAgentConfig.Builder() .setLegacyType(mLegacyType) .setLegacyTypeName(NETWORK_TYPE) + .setLegacyExtraInfo(mHwAddress) .build(); mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(), NETWORK_TYPE, mCapabilities, mLinkProperties, @@ -487,7 +488,6 @@ public class EthernetNetworkFactory extends NetworkFactory { } }; mNetworkAgent.register(); - mNetworkAgent.setLegacyExtraInfo(mHwAddress); mNetworkAgent.markConnected(); } From f7d491808099b1ca203199da579f73073662e957 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 19 Mar 2021 15:14:23 +0800 Subject: [PATCH 592/881] Use public API instead of hidden API in EthernetTracker - Use public API of StaticIpConfiguration.Builder to set ipaddress, domains, gateway and dnsServers. - Use public constructor to create an instance of IpConfiguration and set IpAssignment, ProxySettings, StaticIpConfiguration and HttpProxy by public API. Bug: 182963415 Test: m ethernet-service Change-Id: Idce8bfe7afc31baa644c816afa1f8004987e8c6e --- .../server/ethernet/EthernetTracker.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index a831f34a5a..a190240edb 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -579,7 +579,8 @@ final class EthernetTracker { */ @VisibleForTesting static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) { - StaticIpConfiguration ipConfig = new StaticIpConfiguration(); + final StaticIpConfiguration.Builder staticIpConfigBuilder = + new StaticIpConfiguration.Builder(); for (String keyValueAsString : staticIpConfig.trim().split(" ")) { if (TextUtils.isEmpty(keyValueAsString)) continue; @@ -595,20 +596,20 @@ final class EthernetTracker { switch (key) { case "ip": - ipConfig.ipAddress = new LinkAddress(value); + staticIpConfigBuilder.setIpAddress(new LinkAddress(value)); break; case "domains": - ipConfig.domains = value; + staticIpConfigBuilder.setDomains(value); break; case "gateway": - ipConfig.gateway = InetAddress.parseNumericAddress(value); + staticIpConfigBuilder.setGateway(InetAddress.parseNumericAddress(value)); break; case "dns": { ArrayList dnsAddresses = new ArrayList<>(); for (String address: value.split(",")) { dnsAddresses.add(InetAddress.parseNumericAddress(address)); } - ipConfig.dnsServers.addAll(dnsAddresses); + staticIpConfigBuilder.setDnsServers(dnsAddresses); break; } default : { @@ -617,11 +618,18 @@ final class EthernetTracker { } } } - return new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, ipConfig, null); + final IpConfiguration ret = new IpConfiguration(); + ret.setIpAssignment(IpAssignment.STATIC); + ret.setProxySettings(ProxySettings.NONE); + ret.setStaticIpConfiguration(staticIpConfigBuilder.build()); + return ret; } private static IpConfiguration createDefaultIpConfiguration() { - return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); + final IpConfiguration ret = new IpConfiguration(); + ret.setIpAssignment(IpAssignment.DHCP); + ret.setProxySettings(ProxySettings.NONE); + return ret; } private void updateIfaceMatchRegexp() { From f16d4995f4e0c6dea625e2faa022c401312a51d4 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 19 Mar 2021 16:06:33 +0800 Subject: [PATCH 593/881] Use public API Network#getNetId() to get netid Network class will be a part of mainline module, external callers cannot call its hidden constant. Use public API - getNetId() to get netid instead. Bug: 182963397 Test: m Change-Id: I6d5dd0a8c3879df7bdc1d58e36022045c303bb40 --- services/core/java/com/android/server/IpSecService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 4c3c6ef21f..794cb9301d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1651,7 +1651,7 @@ public class IpSecService extends IIpSecService.Stub { c.getMode(), c.getSourceAddress(), c.getDestinationAddress(), - (c.getNetwork() != null) ? c.getNetwork().netId : 0, + (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0, spiRecord.getSpi(), c.getMarkValue(), c.getMarkMask(), From 4249f3b86810a2419a0ab7a34cb17382f15d61e2 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 19 Mar 2021 23:08:33 +0800 Subject: [PATCH 594/881] Use getAllInterfaceNames to get all interface names The current design is using hidden API - getStackedLinks() to get LinkProperties then call getInterfaceName() to get the interface name. In fact, this behavior could be replaced by system API - getAllInterfaceNames(). Bug: 182963397 Test: atest FrameworksNetTests Test: atest CtsNetTestCases Change-Id: Id2b19dc5099355af69d23a6d99d2b7e6c0e1e88a --- .../server/net/NetworkStatsService.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 7b376847fd..fe43c311da 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -92,7 +92,6 @@ import android.net.DataUsageRequest; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; -import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; @@ -131,6 +130,7 @@ import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionPlan; +import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -1358,17 +1358,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // (or non eBPF offloaded) TX they would appear on both, however egress interface // accounting is explicitly bypassed for traffic from the clat uid. // - final List stackedLinks = snapshot.linkProperties.getStackedLinks(); - for (LinkProperties stackedLink : stackedLinks) { - final String stackedIface = stackedLink.getInterfaceName(); - if (stackedIface != null) { - findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); - findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); + // TODO: This code might be combined to above code. + for (String iface : snapshot.linkProperties.getAllInterfaceNames()) { + // baseIface has been handled, so ignore it. + if (TextUtils.equals(baseIface, iface)) continue; + if (iface != null) { + findOrCreateNetworkIdentitySet(mActiveIfaces, iface).add(ident); + findOrCreateNetworkIdentitySet(mActiveUidIfaces, iface).add(ident); if (isMobile) { - mobileIfaces.add(stackedIface); + mobileIfaces.add(iface); } - mStatsFactory.noteStackedIface(stackedIface, baseIface); + mStatsFactory.noteStackedIface(iface, baseIface); } } } From 7a4706989607d068ef31b9fd14176ccf26ee6041 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 3 Feb 2021 00:51:29 +0800 Subject: [PATCH 595/881] Migrate hidden API in IpConfigStore to formal API IpConfiguration and StaticIpConfiguration are included in framework-connectivity which cannot have external hidden API usages dependencies on them. IpConfiguration and StaticIpConfiguration provide builder and getter methods for the fields of the objects which are formal APIs. So, replace the usages in IpConfigStore with those formal APIs to remove the dependencies. Bug: 178777253 Test: FrameworksServicesTests:IpConfigStoreTest Change-Id: Ie9e6af0efe2c39667bb8faa1e3a498b1f61e1432 --- .../com/android/server/net/IpConfigStore.java | 87 ++++++++++--------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index cc3a002adc..512d2192b9 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -42,6 +42,8 @@ import java.io.IOException; import java.io.InputStream; import java.net.Inet4Address; import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; public class IpConfigStore { private static final String TAG = "IpConfigStore"; @@ -83,25 +85,25 @@ public class IpConfigStore { boolean written = false; try { - switch (config.ipAssignment) { + switch (config.getIpAssignment()) { case STATIC: out.writeUTF(IP_ASSIGNMENT_KEY); - out.writeUTF(config.ipAssignment.toString()); - StaticIpConfiguration staticIpConfiguration = config.staticIpConfiguration; + out.writeUTF(config.getIpAssignment().toString()); + StaticIpConfiguration staticIpConfiguration = config.getStaticIpConfiguration(); if (staticIpConfiguration != null) { - if (staticIpConfiguration.ipAddress != null) { - LinkAddress ipAddress = staticIpConfiguration.ipAddress; + if (staticIpConfiguration.getIpAddress() != null) { + LinkAddress ipAddress = staticIpConfiguration.getIpAddress(); out.writeUTF(LINK_ADDRESS_KEY); out.writeUTF(ipAddress.getAddress().getHostAddress()); out.writeInt(ipAddress.getPrefixLength()); } - if (staticIpConfiguration.gateway != null) { + if (staticIpConfiguration.getGateway() != null) { out.writeUTF(GATEWAY_KEY); out.writeInt(0); // Default route. out.writeInt(1); // Have a gateway. - out.writeUTF(staticIpConfiguration.gateway.getHostAddress()); + out.writeUTF(staticIpConfiguration.getGateway().getHostAddress()); } - for (InetAddress inetAddr : staticIpConfiguration.dnsServers) { + for (InetAddress inetAddr : staticIpConfiguration.getDnsServers()) { out.writeUTF(DNS_KEY); out.writeUTF(inetAddr.getHostAddress()); } @@ -110,7 +112,7 @@ public class IpConfigStore { break; case DHCP: out.writeUTF(IP_ASSIGNMENT_KEY); - out.writeUTF(config.ipAssignment.toString()); + out.writeUTF(config.getIpAssignment().toString()); written = true; break; case UNASSIGNED: @@ -121,13 +123,13 @@ public class IpConfigStore { break; } - switch (config.proxySettings) { + switch (config.getProxySettings()) { case STATIC: - ProxyInfo proxyProperties = config.httpProxy; + ProxyInfo proxyProperties = config.getHttpProxy(); String exclusionList = ProxyUtils.exclusionListAsString( proxyProperties.getExclusionList()); out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); + out.writeUTF(config.getProxySettings().toString()); out.writeUTF(PROXY_HOST_KEY); out.writeUTF(proxyProperties.getHost()); out.writeUTF(PROXY_PORT_KEY); @@ -139,16 +141,16 @@ public class IpConfigStore { written = true; break; case PAC: - ProxyInfo proxyPacProperties = config.httpProxy; + ProxyInfo proxyPacProperties = config.getHttpProxy(); out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); + out.writeUTF(config.getProxySettings().toString()); out.writeUTF(PROXY_PAC_FILE); out.writeUTF(proxyPacProperties.getPacFileUrl().toString()); written = true; break; case NONE: out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); + out.writeUTF(config.getProxySettings().toString()); written = true; break; case UNASSIGNED: @@ -267,11 +269,14 @@ public class IpConfigStore { IpAssignment ipAssignment = IpAssignment.DHCP; ProxySettings proxySettings = ProxySettings.NONE; StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); + LinkAddress linkAddress = null; + InetAddress gatewayAddress = null; String proxyHost = null; String pacFileUrl = null; int proxyPort = -1; String exclusionList = null; String key; + final List dnsServers = new ArrayList<>(); do { key = in.readUTF(); @@ -286,15 +291,15 @@ public class IpConfigStore { } else if (key.equals(IP_ASSIGNMENT_KEY)) { ipAssignment = IpAssignment.valueOf(in.readUTF()); } else if (key.equals(LINK_ADDRESS_KEY)) { - LinkAddress linkAddr = + LinkAddress parsedLinkAddress = new LinkAddress( InetAddresses.parseNumericAddress(in.readUTF()), in.readInt()); - if (linkAddr.getAddress() instanceof Inet4Address && - staticIpConfiguration.ipAddress == null) { - staticIpConfiguration.ipAddress = linkAddr; + if (parsedLinkAddress.getAddress() instanceof Inet4Address + && linkAddress == null) { + linkAddress = parsedLinkAddress; } else { - loge("Non-IPv4 or duplicate address: " + linkAddr); + loge("Non-IPv4 or duplicate address: " + parsedLinkAddress); } } else if (key.equals(GATEWAY_KEY)) { LinkAddress dest = null; @@ -302,8 +307,8 @@ public class IpConfigStore { if (version == 1) { // only supported default gateways - leave the dest/prefix empty gateway = InetAddresses.parseNumericAddress(in.readUTF()); - if (staticIpConfiguration.gateway == null) { - staticIpConfiguration.gateway = gateway; + if (gatewayAddress == null) { + gatewayAddress = gateway; } else { loge("Duplicate gateway: " + gateway.getHostAddress()); } @@ -318,16 +323,14 @@ public class IpConfigStore { gateway = InetAddresses.parseNumericAddress(in.readUTF()); } RouteInfo route = new RouteInfo(dest, gateway); - if (route.isIPv4Default() && - staticIpConfiguration.gateway == null) { - staticIpConfiguration.gateway = gateway; + if (route.isIPv4Default() && gatewayAddress == null) { + gatewayAddress = gateway; } else { loge("Non-IPv4 default or duplicate route: " + route); } } } else if (key.equals(DNS_KEY)) { - staticIpConfiguration.dnsServers.add( - InetAddresses.parseNumericAddress(in.readUTF())); + dnsServers.add(InetAddresses.parseNumericAddress(in.readUTF())); } else if (key.equals(PROXY_SETTINGS_KEY)) { proxySettings = ProxySettings.valueOf(in.readUTF()); } else if (key.equals(PROXY_HOST_KEY)) { @@ -348,25 +351,31 @@ public class IpConfigStore { } } while (true); + staticIpConfiguration = new StaticIpConfiguration.Builder() + .setIpAddress(linkAddress) + .setGateway(gatewayAddress) + .setDnsServers(dnsServers) + .build(); + if (uniqueToken != null) { IpConfiguration config = new IpConfiguration(); networks.put(uniqueToken, config); switch (ipAssignment) { case STATIC: - config.staticIpConfiguration = staticIpConfiguration; - config.ipAssignment = ipAssignment; + config.setStaticIpConfiguration(staticIpConfiguration); + config.setIpAssignment(ipAssignment); break; case DHCP: - config.ipAssignment = ipAssignment; + config.setIpAssignment(ipAssignment); break; case UNASSIGNED: loge("BUG: Found UNASSIGNED IP on file, use DHCP"); - config.ipAssignment = IpAssignment.DHCP; + config.setIpAssignment(IpAssignment.DHCP); break; default: loge("Ignore invalid ip assignment while reading."); - config.ipAssignment = IpAssignment.UNASSIGNED; + config.setIpAssignment(IpAssignment.UNASSIGNED); break; } @@ -374,25 +383,25 @@ public class IpConfigStore { case STATIC: ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy(proxyHost, proxyPort, ProxyUtils.exclusionStringAsList(exclusionList)); - config.proxySettings = proxySettings; - config.httpProxy = proxyInfo; + config.setProxySettings(proxySettings); + config.setHttpProxy(proxyInfo); break; case PAC: ProxyInfo proxyPacProperties = ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl)); - config.proxySettings = proxySettings; - config.httpProxy = proxyPacProperties; + config.setProxySettings(proxySettings); + config.setHttpProxy(proxyPacProperties); break; case NONE: - config.proxySettings = proxySettings; + config.setProxySettings(proxySettings); break; case UNASSIGNED: loge("BUG: Found UNASSIGNED proxy on file, use NONE"); - config.proxySettings = ProxySettings.NONE; + config.setProxySettings(ProxySettings.NONE); break; default: loge("Ignore invalid proxy settings while reading"); - config.proxySettings = ProxySettings.UNASSIGNED; + config.setProxySettings(ProxySettings.UNASSIGNED); break; } } else { From 2c6db2fa857ea0a87246e6eda048e5ca394f0e1d Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 18 Mar 2021 21:35:45 +0800 Subject: [PATCH 596/881] Fix IpConfigStore dependencies on framework-connectivity This change fixes IpConfigStore dependencies on framework-connectivity hidden APIs. - Use the version of SystemApi to new RouteInfo. - Inline the implementation of isIPv4Default() directly because isDefaultRoute() is a public API so it can be used in this class. Bug: 178777253 Test: FrameworksServicesTests:IpConfigStoreTest Change-Id: I5ed1bc8bc8bee5b0c795fd8577a2d64628998e51 --- .../java/com/android/server/net/IpConfigStore.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index 512d2192b9..df1eb6d9fe 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -22,7 +22,6 @@ import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; import android.net.ProxyInfo; -import android.net.RouteInfo; import android.net.StaticIpConfiguration; import android.net.Uri; import android.util.ArrayMap; @@ -322,11 +321,14 @@ public class IpConfigStore { if (in.readInt() == 1) { gateway = InetAddresses.parseNumericAddress(in.readUTF()); } - RouteInfo route = new RouteInfo(dest, gateway); - if (route.isIPv4Default() && gatewayAddress == null) { + // If the destination is a default IPv4 route, use the gateway + // address unless already set. + if (dest.getAddress() instanceof Inet4Address + && dest.getPrefixLength() == 0 && gatewayAddress == null) { gatewayAddress = gateway; } else { - loge("Non-IPv4 default or duplicate route: " + route); + loge("Non-IPv4 default or duplicate route: " + + dest.getAddress()); } } } else if (key.equals(DNS_KEY)) { From a8b818a48764a9d1fe067e0cc8064402df5d4a08 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 19 Mar 2021 15:14:23 +0800 Subject: [PATCH 597/881] Use public API instead of hidden API in EthernetTracker - Use public API of StaticIpConfiguration.Builder to set ipaddress, domains, gateway and dnsServers. - Use public constructor to create an instance of IpConfiguration and set IpAssignment, ProxySettings, StaticIpConfiguration and HttpProxy by public API. Bug: 182963415 Test: m ethernet-service Change-Id: Idce8bfe7afc31baa644c816afa1f8004987e8c6e Merged-In: Idce8bfe7afc31baa644c816afa1f8004987e8c6e --- .../server/ethernet/EthernetTracker.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index a831f34a5a..a190240edb 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -579,7 +579,8 @@ final class EthernetTracker { */ @VisibleForTesting static IpConfiguration parseStaticIpConfiguration(String staticIpConfig) { - StaticIpConfiguration ipConfig = new StaticIpConfiguration(); + final StaticIpConfiguration.Builder staticIpConfigBuilder = + new StaticIpConfiguration.Builder(); for (String keyValueAsString : staticIpConfig.trim().split(" ")) { if (TextUtils.isEmpty(keyValueAsString)) continue; @@ -595,20 +596,20 @@ final class EthernetTracker { switch (key) { case "ip": - ipConfig.ipAddress = new LinkAddress(value); + staticIpConfigBuilder.setIpAddress(new LinkAddress(value)); break; case "domains": - ipConfig.domains = value; + staticIpConfigBuilder.setDomains(value); break; case "gateway": - ipConfig.gateway = InetAddress.parseNumericAddress(value); + staticIpConfigBuilder.setGateway(InetAddress.parseNumericAddress(value)); break; case "dns": { ArrayList dnsAddresses = new ArrayList<>(); for (String address: value.split(",")) { dnsAddresses.add(InetAddress.parseNumericAddress(address)); } - ipConfig.dnsServers.addAll(dnsAddresses); + staticIpConfigBuilder.setDnsServers(dnsAddresses); break; } default : { @@ -617,11 +618,18 @@ final class EthernetTracker { } } } - return new IpConfiguration(IpAssignment.STATIC, ProxySettings.NONE, ipConfig, null); + final IpConfiguration ret = new IpConfiguration(); + ret.setIpAssignment(IpAssignment.STATIC); + ret.setProxySettings(ProxySettings.NONE); + ret.setStaticIpConfiguration(staticIpConfigBuilder.build()); + return ret; } private static IpConfiguration createDefaultIpConfiguration() { - return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); + final IpConfiguration ret = new IpConfiguration(); + ret.setIpAssignment(IpAssignment.DHCP); + ret.setProxySettings(ProxySettings.NONE); + return ret; } private void updateIfaceMatchRegexp() { From 00f7776ec2a4cb4082032de8eb14ca136eb7e848 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 10:33:16 +0800 Subject: [PATCH 598/881] [SP28] Add API for set data warning To have better control and race-free of set data warning to tether offload hardware, an interface of set warning and limit at the same time in the NetworkStatsProvider is needed. This is a no-op change which expose such interface with minimum changes in service side to get build pass. The implementation would be included in follow-up patches. Test: atest NetworkStatsServiceTest Test: atest NetworkPolicyManagerServiceTest Test: atest GtsNetworkStackHostTestCases Test: m doc-comment-check-docs Bug: 149467454 Bug: 170699770 Bug: 170179169 Ignore-AOSP-First: avoid long automerger delay Change-Id: I6ee661497f7dedb871c85786d1950cab951d8aa2 --- .../provider/INetworkStatsProvider.aidl | 2 +- .../INetworkStatsProviderCallback.aidl | 2 +- .../provider/NetworkStatsProvider.java | 58 ++++++++++++++++--- .../server/net/NetworkStatsService.java | 10 ++-- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl index 4078b24921..74c3ba44b6 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl @@ -23,6 +23,6 @@ package android.net.netstats.provider; */ oneway interface INetworkStatsProvider { void onRequestStatsUpdate(int token); - void onSetLimit(String iface, long quotaBytes); void onSetAlert(long quotaBytes); + void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes); } diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index bd336dd348..7eaa01e262 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -26,6 +26,6 @@ import android.net.NetworkStats; oneway interface INetworkStatsProviderCallback { void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); void notifyAlertReached(); - void notifyLimitReached(); + void notifyWarningOrLimitReached(); void unregister(); } diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java index 7639d2244c..65b336ad6f 100644 --- a/core/java/android/net/netstats/provider/NetworkStatsProvider.java +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -29,7 +29,8 @@ import android.os.RemoteException; @SystemApi public abstract class NetworkStatsProvider { /** - * A value used by {@link #onSetLimit} and {@link #onSetAlert} indicates there is no limit. + * A value used by {@link #onSetLimit}, {@link #onSetAlert} and {@link #onSetWarningAndLimit} + * indicates there is no limit. */ public static final int QUOTA_UNLIMITED = -1; @@ -42,13 +43,13 @@ public abstract class NetworkStatsProvider { } @Override - public void onSetLimit(String iface, long quotaBytes) { - NetworkStatsProvider.this.onSetLimit(iface, quotaBytes); + public void onSetAlert(long quotaBytes) { + NetworkStatsProvider.this.onSetAlert(quotaBytes); } @Override - public void onSetAlert(long quotaBytes) { - NetworkStatsProvider.this.onSetAlert(quotaBytes); + public void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes) { + NetworkStatsProvider.this.onSetWarningAndLimit(iface, warningBytes, limitBytes); } }; @@ -145,11 +146,28 @@ public abstract class NetworkStatsProvider { } /** - * Notify system that the quota set by {@code onSetLimit} has been reached. + * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached. + * + * @hide + */ + // TODO: Expose as system API. + public void notifyWarningReached() { + try { + // Reuse the code path to notify warning reached with limit reached + // since framework handles them in the same way. + getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Notify system that the quota set by {@link #onSetLimit} or limit set by + * {@link #onSetWarningAndLimit} has been reached. */ public void notifyLimitReached() { try { - getProviderCallbackBinderOrThrow().notifyLimitReached(); + getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } @@ -180,8 +198,34 @@ public abstract class NetworkStatsProvider { * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. */ + // TODO: deprecate this once onSetWarningAndLimit is ready. public abstract void onSetLimit(@NonNull String iface, long quotaBytes); + /** + * Called by {@code NetworkStatsService} when setting the interface quotas for the specified + * upstream interface. If a provider implements {@link #onSetWarningAndLimit}, the system + * will not call {@link #onSetLimit}. When this method is called, the implementation + * should behave as follows: + * 1. If {@code warningBytes} is reached on {@code iface}, block all further traffic on + * {@code iface} and call {@link NetworkStatsProvider@notifyWarningReached()}. + * 2. If {@code limitBytes} is reached on {@code iface}, block all further traffic on + * {@code iface} and call {@link NetworkStatsProvider#notifyLimitReached()}. + * + * @param iface the interface requiring the operation. + * @param warningBytes the warning defined as the number of bytes, starting from zero and + * counting from now. A value of {@link #QUOTA_UNLIMITED} indicates + * there is no warning. + * @param limitBytes the limit defined as the number of bytes, starting from zero and counting + * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. + * + * @hide + */ + // TODO: Expose as system API. + public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) { + // Backward compatibility for those who didn't override this function. + onSetLimit(iface, limitBytes); + } + /** * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index fe43c311da..785e487ed1 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1676,7 +1676,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); + // TODO: Set warning accordingly. + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, + NetworkStatsProvider.QUOTA_UNLIMITED, quota)); } } @@ -2071,10 +2073,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void notifyLimitReached() { - Log.d(TAG, mTag + ": onLimitReached"); + public void notifyWarningOrLimitReached() { + Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); LocalServices.getService(NetworkPolicyManagerInternal.class) - .onStatsProviderLimitReached(mTag); + .onStatsProviderWarningOrLimitReached(mTag); } @Override From 0141e8f8f8cfa0a935a9fd892f706d42dcc346d6 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 24 Mar 2021 14:17:19 +0800 Subject: [PATCH 599/881] [SP29] Send interface warning bytes to NetworkStatsProvider This change contains necessary modification in NPMS and NSS to send warning bytes to NetworkStatsProvider. But since no any provider has been upgraded to handle such parameter. Thus, no behavior change is made in this patch. Test: atest NetworkPolicyManagerServiceTest NetworkStatsServiceTest Test: atest NetworkPolicyManagerServiceTest#testStatsProviderWarningAndLimitReached Bug: 149467454 Bug: 170699770 Bug: 170179169 Ignore-AOSP-First: avoid long automerger delay Change-Id: I6c4863030c36328db571294fd12a40e59864def5 --- .../com/android/server/net/NetworkStatsService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 785e487ed1..de5aae07d6 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1674,11 +1674,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { - if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - // TODO: Set warning accordingly. + public void setStatsProviderWarningAndLimitAsync( + @NonNull String iface, long warning, long limit) { + if (LOGV) { + Slog.v(TAG, "setStatsProviderWarningAndLimitAsync(" + + iface + "," + warning + "," + limit + ")"); + } invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, - NetworkStatsProvider.QUOTA_UNLIMITED, quota)); + warning, limit)); } } From a22175603b1d3ce3486b2b61e611b4b062799ff9 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 19:45:05 +0800 Subject: [PATCH 600/881] [SP31] Expose onSetWarningAndLimit System API Test: atest NetworkPolicyManagerServiceTest NetworkStatsServiceTest Bug: 149467454 CTS-Coverage-Bug: 183598414 Ignore-AOSP-First: avoid long automerger delay Change-Id: I6f5e22e3a7b80a38cae9f3c5d7296a1dff34facf --- .../net/netstats/provider/NetworkStatsProvider.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java index 65b336ad6f..23fc06927e 100644 --- a/core/java/android/net/netstats/provider/NetworkStatsProvider.java +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -147,10 +147,7 @@ public abstract class NetworkStatsProvider { /** * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached. - * - * @hide */ - // TODO: Expose as system API. public void notifyWarningReached() { try { // Reuse the code path to notify warning reached with limit reached @@ -198,7 +195,6 @@ public abstract class NetworkStatsProvider { * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. */ - // TODO: deprecate this once onSetWarningAndLimit is ready. public abstract void onSetLimit(@NonNull String iface, long quotaBytes); /** @@ -217,10 +213,7 @@ public abstract class NetworkStatsProvider { * there is no warning. * @param limitBytes the limit defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. - * - * @hide */ - // TODO: Expose as system API. public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) { // Backward compatibility for those who didn't override this function. onSetLimit(iface, limitBytes); From 8482bac84f334452f30e55ce4efa143271ced841 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 10:33:16 +0800 Subject: [PATCH 601/881] [SP28] Add API for set data warning To have better control and race-free of set data warning to tether offload hardware, an interface of set warning and limit at the same time in the NetworkStatsProvider is needed. This is a no-op change which expose such interface with minimum changes in service side to get build pass. The implementation would be included in follow-up patches. Test: atest NetworkStatsServiceTest Test: atest NetworkPolicyManagerServiceTest Test: atest GtsNetworkStackHostTestCases Test: m doc-comment-check-docs Bug: 149467454 Bug: 170699770 Bug: 170179169 Merged-In: I6ee661497f7dedb871c85786d1950cab951d8aa2 Change-Id: I6ee661497f7dedb871c85786d1950cab951d8aa2 (cherry-picked from ag/13959436) --- .../provider/INetworkStatsProvider.aidl | 2 +- .../INetworkStatsProviderCallback.aidl | 2 +- .../provider/NetworkStatsProvider.java | 58 ++++++++++++++++--- .../server/net/NetworkStatsService.java | 10 ++-- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl index 4078b24921..74c3ba44b6 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl @@ -23,6 +23,6 @@ package android.net.netstats.provider; */ oneway interface INetworkStatsProvider { void onRequestStatsUpdate(int token); - void onSetLimit(String iface, long quotaBytes); void onSetAlert(long quotaBytes); + void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes); } diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index bd336dd348..7eaa01e262 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -26,6 +26,6 @@ import android.net.NetworkStats; oneway interface INetworkStatsProviderCallback { void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); void notifyAlertReached(); - void notifyLimitReached(); + void notifyWarningOrLimitReached(); void unregister(); } diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java index 7639d2244c..65b336ad6f 100644 --- a/core/java/android/net/netstats/provider/NetworkStatsProvider.java +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -29,7 +29,8 @@ import android.os.RemoteException; @SystemApi public abstract class NetworkStatsProvider { /** - * A value used by {@link #onSetLimit} and {@link #onSetAlert} indicates there is no limit. + * A value used by {@link #onSetLimit}, {@link #onSetAlert} and {@link #onSetWarningAndLimit} + * indicates there is no limit. */ public static final int QUOTA_UNLIMITED = -1; @@ -42,13 +43,13 @@ public abstract class NetworkStatsProvider { } @Override - public void onSetLimit(String iface, long quotaBytes) { - NetworkStatsProvider.this.onSetLimit(iface, quotaBytes); + public void onSetAlert(long quotaBytes) { + NetworkStatsProvider.this.onSetAlert(quotaBytes); } @Override - public void onSetAlert(long quotaBytes) { - NetworkStatsProvider.this.onSetAlert(quotaBytes); + public void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes) { + NetworkStatsProvider.this.onSetWarningAndLimit(iface, warningBytes, limitBytes); } }; @@ -145,11 +146,28 @@ public abstract class NetworkStatsProvider { } /** - * Notify system that the quota set by {@code onSetLimit} has been reached. + * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached. + * + * @hide + */ + // TODO: Expose as system API. + public void notifyWarningReached() { + try { + // Reuse the code path to notify warning reached with limit reached + // since framework handles them in the same way. + getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Notify system that the quota set by {@link #onSetLimit} or limit set by + * {@link #onSetWarningAndLimit} has been reached. */ public void notifyLimitReached() { try { - getProviderCallbackBinderOrThrow().notifyLimitReached(); + getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } @@ -180,8 +198,34 @@ public abstract class NetworkStatsProvider { * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. */ + // TODO: deprecate this once onSetWarningAndLimit is ready. public abstract void onSetLimit(@NonNull String iface, long quotaBytes); + /** + * Called by {@code NetworkStatsService} when setting the interface quotas for the specified + * upstream interface. If a provider implements {@link #onSetWarningAndLimit}, the system + * will not call {@link #onSetLimit}. When this method is called, the implementation + * should behave as follows: + * 1. If {@code warningBytes} is reached on {@code iface}, block all further traffic on + * {@code iface} and call {@link NetworkStatsProvider@notifyWarningReached()}. + * 2. If {@code limitBytes} is reached on {@code iface}, block all further traffic on + * {@code iface} and call {@link NetworkStatsProvider#notifyLimitReached()}. + * + * @param iface the interface requiring the operation. + * @param warningBytes the warning defined as the number of bytes, starting from zero and + * counting from now. A value of {@link #QUOTA_UNLIMITED} indicates + * there is no warning. + * @param limitBytes the limit defined as the number of bytes, starting from zero and counting + * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. + * + * @hide + */ + // TODO: Expose as system API. + public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) { + // Backward compatibility for those who didn't override this function. + onSetLimit(iface, limitBytes); + } + /** * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 7b376847fd..d878347104 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1675,7 +1675,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); + // TODO: Set warning accordingly. + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, + NetworkStatsProvider.QUOTA_UNLIMITED, quota)); } } @@ -2070,10 +2072,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void notifyLimitReached() { - Log.d(TAG, mTag + ": onLimitReached"); + public void notifyWarningOrLimitReached() { + Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); LocalServices.getService(NetworkPolicyManagerInternal.class) - .onStatsProviderLimitReached(mTag); + .onStatsProviderWarningOrLimitReached(mTag); } @Override From 49642c1eae19e4bc5104b5845facd1dbee823ca1 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 24 Mar 2021 14:17:19 +0800 Subject: [PATCH 602/881] [SP29] Send interface warning bytes to NetworkStatsProvider This change contains necessary modification in NPMS and NSS to send warning bytes to NetworkStatsProvider. But since no any provider has been upgraded to handle such parameter. Thus, no behavior change is made in this patch. Test: atest NetworkPolicyManagerServiceTest NetworkStatsServiceTest Test: atest NetworkPolicyManagerServiceTest#testStatsProviderWarningAndLimitReached Bug: 149467454 Bug: 170699770 Bug: 170179169 Merged-In: I6c4863030c36328db571294fd12a40e59864def5 Change-Id: I6c4863030c36328db571294fd12a40e59864def5 (cherry-picked from ag/13982166) --- .../com/android/server/net/NetworkStatsService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index d878347104..600f53b9b3 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1673,11 +1673,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { - if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - // TODO: Set warning accordingly. + public void setStatsProviderWarningAndLimitAsync( + @NonNull String iface, long warning, long limit) { + if (LOGV) { + Slog.v(TAG, "setStatsProviderWarningAndLimitAsync(" + + iface + "," + warning + "," + limit + ")"); + } invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, - NetworkStatsProvider.QUOTA_UNLIMITED, quota)); + warning, limit)); } } From 46ecccc4d4a510726803f7af6057d0c04be9dd70 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 19:45:05 +0800 Subject: [PATCH 603/881] [SP31] Expose onSetWarningAndLimit System API Test: atest NetworkPolicyManagerServiceTest NetworkStatsServiceTest Bug: 149467454 CTS-Coverage-Bug: 183598414 Merged-In: I6f5e22e3a7b80a38cae9f3c5d7296a1dff34facf Change-Id: I6f5e22e3a7b80a38cae9f3c5d7296a1dff34facf (cherry-picked from ag/13981689) --- .../net/netstats/provider/NetworkStatsProvider.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java index 65b336ad6f..23fc06927e 100644 --- a/core/java/android/net/netstats/provider/NetworkStatsProvider.java +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -147,10 +147,7 @@ public abstract class NetworkStatsProvider { /** * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached. - * - * @hide */ - // TODO: Expose as system API. public void notifyWarningReached() { try { // Reuse the code path to notify warning reached with limit reached @@ -198,7 +195,6 @@ public abstract class NetworkStatsProvider { * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. */ - // TODO: deprecate this once onSetWarningAndLimit is ready. public abstract void onSetLimit(@NonNull String iface, long quotaBytes); /** @@ -217,10 +213,7 @@ public abstract class NetworkStatsProvider { * there is no warning. * @param limitBytes the limit defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. - * - * @hide */ - // TODO: Expose as system API. public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) { // Backward compatibility for those who didn't override this function. onSetLimit(iface, limitBytes); From bd7052a00a557cf41c9c1ac2de38e47f8cced0f3 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 19 Mar 2021 23:08:33 +0800 Subject: [PATCH 604/881] Use getAllInterfaceNames to get all interface names The current design is using hidden API - getStackedLinks() to get LinkProperties then call getInterfaceName() to get the interface name. In fact, this behavior could be replaced by system API - getAllInterfaceNames(). Bug: 182963397 Test: atest FrameworksNetTests Test: atest CtsNetTestCases Change-Id: Id2b19dc5099355af69d23a6d99d2b7e6c0e1e88a Merged-In: Id2b19dc5099355af69d23a6d99d2b7e6c0e1e88a (cherry-picked from ag/13927660) --- .../server/net/NetworkStatsService.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 7b376847fd..fe43c311da 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -92,7 +92,6 @@ import android.net.DataUsageRequest; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; -import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; @@ -131,6 +130,7 @@ import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionPlan; +import android.text.TextUtils; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -1358,17 +1358,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // (or non eBPF offloaded) TX they would appear on both, however egress interface // accounting is explicitly bypassed for traffic from the clat uid. // - final List stackedLinks = snapshot.linkProperties.getStackedLinks(); - for (LinkProperties stackedLink : stackedLinks) { - final String stackedIface = stackedLink.getInterfaceName(); - if (stackedIface != null) { - findOrCreateNetworkIdentitySet(mActiveIfaces, stackedIface).add(ident); - findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident); + // TODO: This code might be combined to above code. + for (String iface : snapshot.linkProperties.getAllInterfaceNames()) { + // baseIface has been handled, so ignore it. + if (TextUtils.equals(baseIface, iface)) continue; + if (iface != null) { + findOrCreateNetworkIdentitySet(mActiveIfaces, iface).add(ident); + findOrCreateNetworkIdentitySet(mActiveUidIfaces, iface).add(ident); if (isMobile) { - mobileIfaces.add(stackedIface); + mobileIfaces.add(iface); } - mStatsFactory.noteStackedIface(stackedIface, baseIface); + mStatsFactory.noteStackedIface(iface, baseIface); } } } From a3bf03ed4007dc4890360a3f2662cd00fef86d5f Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 19 Mar 2021 16:06:33 +0800 Subject: [PATCH 605/881] Use public API Network#getNetId() to get netid Network class will be a part of mainline module, external callers cannot call its hidden constant. Use public API - getNetId() to get netid instead. Bug: 182963397 Test: m Change-Id: I6d5dd0a8c3879df7bdc1d58e36022045c303bb40 Merged-In: I6d5dd0a8c3879df7bdc1d58e36022045c303bb40 (cherry-picked from ag/13927649) --- services/core/java/com/android/server/IpSecService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 4c3c6ef21f..794cb9301d 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1651,7 +1651,7 @@ public class IpSecService extends IIpSecService.Stub { c.getMode(), c.getSourceAddress(), c.getDestinationAddress(), - (c.getNetwork() != null) ? c.getNetwork().netId : 0, + (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0, spiRecord.getSpi(), c.getMarkValue(), c.getMarkMask(), From d5b622ebd67675e256a45c2a32fbcb071f5d2502 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Tue, 30 Mar 2021 16:54:45 +0800 Subject: [PATCH 606/881] Add transport type in capabilities filter of EthernetNetworkFacotry Bug: 167544279 Test: atest EthernetServiceTests Change-Id: Ie64e3cff0ace413f14682736de7a1b65fa93e705 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 75e77b9596..f9e8b00562 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -169,6 +169,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private void updateCapabilityFilter() { NetworkCapabilities capabilitiesFilter = new NetworkCapabilities.Builder() .clearAll() + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build(); for (NetworkInterfaceState iface: mTrackingInterfaces.values()) { From b0e21ab9af58e65eea042898468fa9139d5ff2dc Mon Sep 17 00:00:00 2001 From: lesl Date: Tue, 9 Mar 2021 23:50:11 +0800 Subject: [PATCH 607/881] Fix Wi-Fi SSID null handling When Wi-Fi SSID is null in NetworkCapabilities, get Wi-Fi SSID from connection info (WifiInfo) which is non-null design. Bug: 176396812 Test: FrameworksNetTests NetworkPolicyManagerServiceTest Change-Id: I59c7d8f7e176d0c6bb100721269f3f6165f0ca21 --- core/java/android/net/NetworkIdentity.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index b037261f0b..1eef7d9a53 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -198,15 +198,11 @@ public class NetworkIdentity implements Comparable { final int oemManaged = getOemBitfield(snapshot.networkCapabilities); if (legacyType == TYPE_WIFI) { - if (snapshot.networkCapabilities.getSsid() != null) { - networkId = snapshot.networkCapabilities.getSsid(); - if (networkId == null) { - // TODO: Figure out if this code path never runs. If so, remove them. - final WifiManager wifi = (WifiManager) context.getSystemService( - Context.WIFI_SERVICE); - final WifiInfo info = wifi.getConnectionInfo(); - networkId = info != null ? info.getSSID() : null; - } + networkId = snapshot.networkCapabilities.getSsid(); + if (networkId == null) { + final WifiManager wifi = context.getSystemService(WifiManager.class); + final WifiInfo info = wifi.getConnectionInfo(); + networkId = info != null ? info.getSSID() : null; } } From 481a85d41f2c9ae41cb2861df0abcba1495e6e95 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 3 Feb 2021 00:51:29 +0800 Subject: [PATCH 608/881] Migrate hidden API in IpConfigStore to formal API IpConfiguration and StaticIpConfiguration are included in framework-connectivity which cannot have external hidden API usages dependencies on them. IpConfiguration and StaticIpConfiguration provide builder and getter methods for the fields of the objects which are formal APIs. So, replace the usages in IpConfigStore with those formal APIs to remove the dependencies. (cherry-picked from ag/13929104) Bug: 178777253 Test: FrameworksServicesTests:IpConfigStoreTest Merged-In: Ie9e6af0efe2c39667bb8faa1e3a498b1f61e1432 Change-Id: Ie9e6af0efe2c39667bb8faa1e3a498b1f61e1432 --- .../com/android/server/net/IpConfigStore.java | 87 ++++++++++--------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index cc3a002adc..512d2192b9 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -42,6 +42,8 @@ import java.io.IOException; import java.io.InputStream; import java.net.Inet4Address; import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; public class IpConfigStore { private static final String TAG = "IpConfigStore"; @@ -83,25 +85,25 @@ public class IpConfigStore { boolean written = false; try { - switch (config.ipAssignment) { + switch (config.getIpAssignment()) { case STATIC: out.writeUTF(IP_ASSIGNMENT_KEY); - out.writeUTF(config.ipAssignment.toString()); - StaticIpConfiguration staticIpConfiguration = config.staticIpConfiguration; + out.writeUTF(config.getIpAssignment().toString()); + StaticIpConfiguration staticIpConfiguration = config.getStaticIpConfiguration(); if (staticIpConfiguration != null) { - if (staticIpConfiguration.ipAddress != null) { - LinkAddress ipAddress = staticIpConfiguration.ipAddress; + if (staticIpConfiguration.getIpAddress() != null) { + LinkAddress ipAddress = staticIpConfiguration.getIpAddress(); out.writeUTF(LINK_ADDRESS_KEY); out.writeUTF(ipAddress.getAddress().getHostAddress()); out.writeInt(ipAddress.getPrefixLength()); } - if (staticIpConfiguration.gateway != null) { + if (staticIpConfiguration.getGateway() != null) { out.writeUTF(GATEWAY_KEY); out.writeInt(0); // Default route. out.writeInt(1); // Have a gateway. - out.writeUTF(staticIpConfiguration.gateway.getHostAddress()); + out.writeUTF(staticIpConfiguration.getGateway().getHostAddress()); } - for (InetAddress inetAddr : staticIpConfiguration.dnsServers) { + for (InetAddress inetAddr : staticIpConfiguration.getDnsServers()) { out.writeUTF(DNS_KEY); out.writeUTF(inetAddr.getHostAddress()); } @@ -110,7 +112,7 @@ public class IpConfigStore { break; case DHCP: out.writeUTF(IP_ASSIGNMENT_KEY); - out.writeUTF(config.ipAssignment.toString()); + out.writeUTF(config.getIpAssignment().toString()); written = true; break; case UNASSIGNED: @@ -121,13 +123,13 @@ public class IpConfigStore { break; } - switch (config.proxySettings) { + switch (config.getProxySettings()) { case STATIC: - ProxyInfo proxyProperties = config.httpProxy; + ProxyInfo proxyProperties = config.getHttpProxy(); String exclusionList = ProxyUtils.exclusionListAsString( proxyProperties.getExclusionList()); out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); + out.writeUTF(config.getProxySettings().toString()); out.writeUTF(PROXY_HOST_KEY); out.writeUTF(proxyProperties.getHost()); out.writeUTF(PROXY_PORT_KEY); @@ -139,16 +141,16 @@ public class IpConfigStore { written = true; break; case PAC: - ProxyInfo proxyPacProperties = config.httpProxy; + ProxyInfo proxyPacProperties = config.getHttpProxy(); out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); + out.writeUTF(config.getProxySettings().toString()); out.writeUTF(PROXY_PAC_FILE); out.writeUTF(proxyPacProperties.getPacFileUrl().toString()); written = true; break; case NONE: out.writeUTF(PROXY_SETTINGS_KEY); - out.writeUTF(config.proxySettings.toString()); + out.writeUTF(config.getProxySettings().toString()); written = true; break; case UNASSIGNED: @@ -267,11 +269,14 @@ public class IpConfigStore { IpAssignment ipAssignment = IpAssignment.DHCP; ProxySettings proxySettings = ProxySettings.NONE; StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); + LinkAddress linkAddress = null; + InetAddress gatewayAddress = null; String proxyHost = null; String pacFileUrl = null; int proxyPort = -1; String exclusionList = null; String key; + final List dnsServers = new ArrayList<>(); do { key = in.readUTF(); @@ -286,15 +291,15 @@ public class IpConfigStore { } else if (key.equals(IP_ASSIGNMENT_KEY)) { ipAssignment = IpAssignment.valueOf(in.readUTF()); } else if (key.equals(LINK_ADDRESS_KEY)) { - LinkAddress linkAddr = + LinkAddress parsedLinkAddress = new LinkAddress( InetAddresses.parseNumericAddress(in.readUTF()), in.readInt()); - if (linkAddr.getAddress() instanceof Inet4Address && - staticIpConfiguration.ipAddress == null) { - staticIpConfiguration.ipAddress = linkAddr; + if (parsedLinkAddress.getAddress() instanceof Inet4Address + && linkAddress == null) { + linkAddress = parsedLinkAddress; } else { - loge("Non-IPv4 or duplicate address: " + linkAddr); + loge("Non-IPv4 or duplicate address: " + parsedLinkAddress); } } else if (key.equals(GATEWAY_KEY)) { LinkAddress dest = null; @@ -302,8 +307,8 @@ public class IpConfigStore { if (version == 1) { // only supported default gateways - leave the dest/prefix empty gateway = InetAddresses.parseNumericAddress(in.readUTF()); - if (staticIpConfiguration.gateway == null) { - staticIpConfiguration.gateway = gateway; + if (gatewayAddress == null) { + gatewayAddress = gateway; } else { loge("Duplicate gateway: " + gateway.getHostAddress()); } @@ -318,16 +323,14 @@ public class IpConfigStore { gateway = InetAddresses.parseNumericAddress(in.readUTF()); } RouteInfo route = new RouteInfo(dest, gateway); - if (route.isIPv4Default() && - staticIpConfiguration.gateway == null) { - staticIpConfiguration.gateway = gateway; + if (route.isIPv4Default() && gatewayAddress == null) { + gatewayAddress = gateway; } else { loge("Non-IPv4 default or duplicate route: " + route); } } } else if (key.equals(DNS_KEY)) { - staticIpConfiguration.dnsServers.add( - InetAddresses.parseNumericAddress(in.readUTF())); + dnsServers.add(InetAddresses.parseNumericAddress(in.readUTF())); } else if (key.equals(PROXY_SETTINGS_KEY)) { proxySettings = ProxySettings.valueOf(in.readUTF()); } else if (key.equals(PROXY_HOST_KEY)) { @@ -348,25 +351,31 @@ public class IpConfigStore { } } while (true); + staticIpConfiguration = new StaticIpConfiguration.Builder() + .setIpAddress(linkAddress) + .setGateway(gatewayAddress) + .setDnsServers(dnsServers) + .build(); + if (uniqueToken != null) { IpConfiguration config = new IpConfiguration(); networks.put(uniqueToken, config); switch (ipAssignment) { case STATIC: - config.staticIpConfiguration = staticIpConfiguration; - config.ipAssignment = ipAssignment; + config.setStaticIpConfiguration(staticIpConfiguration); + config.setIpAssignment(ipAssignment); break; case DHCP: - config.ipAssignment = ipAssignment; + config.setIpAssignment(ipAssignment); break; case UNASSIGNED: loge("BUG: Found UNASSIGNED IP on file, use DHCP"); - config.ipAssignment = IpAssignment.DHCP; + config.setIpAssignment(IpAssignment.DHCP); break; default: loge("Ignore invalid ip assignment while reading."); - config.ipAssignment = IpAssignment.UNASSIGNED; + config.setIpAssignment(IpAssignment.UNASSIGNED); break; } @@ -374,25 +383,25 @@ public class IpConfigStore { case STATIC: ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy(proxyHost, proxyPort, ProxyUtils.exclusionStringAsList(exclusionList)); - config.proxySettings = proxySettings; - config.httpProxy = proxyInfo; + config.setProxySettings(proxySettings); + config.setHttpProxy(proxyInfo); break; case PAC: ProxyInfo proxyPacProperties = ProxyInfo.buildPacProxy(Uri.parse(pacFileUrl)); - config.proxySettings = proxySettings; - config.httpProxy = proxyPacProperties; + config.setProxySettings(proxySettings); + config.setHttpProxy(proxyPacProperties); break; case NONE: - config.proxySettings = proxySettings; + config.setProxySettings(proxySettings); break; case UNASSIGNED: loge("BUG: Found UNASSIGNED proxy on file, use NONE"); - config.proxySettings = ProxySettings.NONE; + config.setProxySettings(ProxySettings.NONE); break; default: loge("Ignore invalid proxy settings while reading"); - config.proxySettings = ProxySettings.UNASSIGNED; + config.setProxySettings(ProxySettings.UNASSIGNED); break; } } else { From c6cb931f32e6b953c368159484ded548819b4a80 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 18 Mar 2021 21:35:45 +0800 Subject: [PATCH 609/881] Fix IpConfigStore dependencies on framework-connectivity This change fixes IpConfigStore dependencies on framework-connectivity hidden APIs. - Use the version of SystemApi to new RouteInfo. - Inline the implementation of isIPv4Default() directly because isDefaultRoute() is a public API so it can be used in this class. (cherry-picked from ag/13945685) Bug: 178777253 Test: FrameworksServicesTests:IpConfigStoreTest Merged-In: I5ed1bc8bc8bee5b0c795fd8577a2d64628998e51 Change-Id: I5ed1bc8bc8bee5b0c795fd8577a2d64628998e51 --- .../java/com/android/server/net/IpConfigStore.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index 512d2192b9..df1eb6d9fe 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -22,7 +22,6 @@ import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; import android.net.ProxyInfo; -import android.net.RouteInfo; import android.net.StaticIpConfiguration; import android.net.Uri; import android.util.ArrayMap; @@ -322,11 +321,14 @@ public class IpConfigStore { if (in.readInt() == 1) { gateway = InetAddresses.parseNumericAddress(in.readUTF()); } - RouteInfo route = new RouteInfo(dest, gateway); - if (route.isIPv4Default() && gatewayAddress == null) { + // If the destination is a default IPv4 route, use the gateway + // address unless already set. + if (dest.getAddress() instanceof Inet4Address + && dest.getPrefixLength() == 0 && gatewayAddress == null) { gatewayAddress = gateway; } else { - loge("Non-IPv4 default or duplicate route: " + route); + loge("Non-IPv4 default or duplicate route: " + + dest.getAddress()); } } } else if (key.equals(DNS_KEY)) { From 5b5b782644999b5c2cc7f1204444b09faef80d89 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 8 Apr 2021 15:32:08 +0900 Subject: [PATCH 610/881] Add documentation on EthernetNetworkSpecifier API Add javadoc on the constructor and getInterfaceName method. Fixes: 182979732 Test: m Change-Id: Iced805149a8344b953331501b48184661be0053a --- core/java/android/net/EthernetNetworkSpecifier.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/core/java/android/net/EthernetNetworkSpecifier.java index e1685887e8..62c5761442 100644 --- a/core/java/android/net/EthernetNetworkSpecifier.java +++ b/core/java/android/net/EthernetNetworkSpecifier.java @@ -42,15 +42,22 @@ public final class EthernetNetworkSpecifier extends NetworkSpecifier implements @NonNull private final String mInterfaceName; + /** + * Create a new EthernetNetworkSpecifier. + * @param interfaceName Name of the ethernet interface the specifier refers to. + */ public EthernetNetworkSpecifier(@NonNull String interfaceName) { Preconditions.checkStringNotEmpty(interfaceName); mInterfaceName = interfaceName; } - // This may be null in the future to support specifiers based on data other than the interface - // name. + /** + * Get the name of the ethernet interface the specifier refers to. + */ @Nullable public String getInterfaceName() { + // This may be null in the future to support specifiers based on data other than the + // interface name. return mInterfaceName; } From 4e878ad3f3e2a49b4295e508725bcb0f1b17a64a Mon Sep 17 00:00:00 2001 From: paulhu Date: Fri, 9 Apr 2021 15:47:36 +0800 Subject: [PATCH 611/881] Rename FIRST_SDK_INT to DEVICE_INITIAL_SDK_INT As API review feedback, rename Build#VERSION#FIRST_SDK_INT to Build#VERSION#DEVICE_INITIAL_SDK_INT. As well as update all usage in frameworks and tests. Bug: 184735771 Test: m Change-Id: I72660959cb4e638a8e80fcf2f4e96ea172969f44 --- core/java/android/net/IpSecAlgorithm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 8f1e2defd2..7ef5bac092 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -354,7 +354,7 @@ public final class IpSecAlgorithm implements Parcelable { } for (Entry entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) { - if (Build.VERSION.FIRST_SDK_INT >= entry.getValue()) { + if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= entry.getValue()) { enabledAlgos.add(entry.getKey()); } } From ae6367012acf56f7dc998a9a03f0079694b93e1d Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 8 Apr 2021 19:42:30 +0800 Subject: [PATCH 612/881] Resolve hidden connectivity methods dependency This commit resolves the dependency under batterystatstests, servicestests and coretests with hidden connectivity module codes. Because of connectivity modularization work, the hidden connectivity methods are not accessible outside modules. Update tests with alternative ways. Bug: 182859030 Test: atest Change-Id: I8294ae4167ee5f95137e0be0f7464429ed3f3322 --- .../android/server/net/IpConfigStoreTest.java | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java index 401d6e30df..2f771260ac 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java @@ -39,6 +39,8 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.InetAddress; +import java.util.ArrayList; import java.util.Arrays; /** @@ -53,8 +55,8 @@ public class IpConfigStoreTest { ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); DataOutputStream outputStream = new DataOutputStream(byteStream); - IpConfiguration expectedConfig = new IpConfiguration(IpAssignment.DHCP, - ProxySettings.NONE, null, null); + final IpConfiguration expectedConfig = + newIpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null); // Emulate writing to old format. writeDhcpConfigV2(outputStream, KEY_CONFIG, expectedConfig); @@ -78,18 +80,23 @@ public class IpConfigStoreTest { final String DNS_IP_ADDR_1 = "1.2.3.4"; final String DNS_IP_ADDR_2 = "5.6.7.8"; - StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); - staticIpConfiguration.ipAddress = new LinkAddress(IP_ADDR_1); - staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); - staticIpConfiguration.dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); + final ArrayList dnsServers = new ArrayList<>(); + dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); + dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); + final StaticIpConfiguration staticIpConfiguration1 = new StaticIpConfiguration.Builder() + .setIpAddress(new LinkAddress(IP_ADDR_1)) + .setDnsServers(dnsServers).build(); + final StaticIpConfiguration staticIpConfiguration2 = new StaticIpConfiguration.Builder() + .setIpAddress(new LinkAddress(IP_ADDR_2)) + .setDnsServers(dnsServers).build(); ProxyInfo proxyInfo = ProxyInfo.buildDirectProxy("10.10.10.10", 88, Arrays.asList("host1", "host2")); - IpConfiguration expectedConfig1 = new IpConfiguration(IpAssignment.STATIC, - ProxySettings.STATIC, staticIpConfiguration, proxyInfo); - IpConfiguration expectedConfig2 = new IpConfiguration(expectedConfig1); - expectedConfig2.getStaticIpConfiguration().ipAddress = new LinkAddress(IP_ADDR_2); + IpConfiguration expectedConfig1 = newIpConfiguration(IpAssignment.STATIC, + ProxySettings.STATIC, staticIpConfiguration1, proxyInfo); + IpConfiguration expectedConfig2 = newIpConfiguration(IpAssignment.STATIC, + ProxySettings.STATIC, staticIpConfiguration2, proxyInfo); ArrayMap expectedNetworks = new ArrayMap<>(); expectedNetworks.put(IFACE_1, expectedConfig1); @@ -107,14 +114,24 @@ public class IpConfigStoreTest { assertEquals(expectedNetworks.get(IFACE_2), actualNetworks.get(IFACE_2)); } + private IpConfiguration newIpConfiguration(IpAssignment ipAssignment, + ProxySettings proxySettings, StaticIpConfiguration staticIpConfig, ProxyInfo info) { + final IpConfiguration config = new IpConfiguration(); + config.setIpAssignment(ipAssignment); + config.setProxySettings(proxySettings); + config.setStaticIpConfiguration(staticIpConfig); + config.setHttpProxy(info); + return config; + } + // This is simplified snapshot of code that was used to store values in V2 format (key as int). private static void writeDhcpConfigV2(DataOutputStream out, int configKey, IpConfiguration config) throws IOException { out.writeInt(2); // VERSION 2 - switch (config.ipAssignment) { + switch (config.getIpAssignment()) { case DHCP: out.writeUTF("ipAssignment"); - out.writeUTF(config.ipAssignment.toString()); + out.writeUTF(config.getIpAssignment().toString()); break; default: fail("Not supported in test environment"); From 8cc30c0ad122dbd2e72d640c7d530bd4a3032338 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 14 Apr 2021 16:31:37 +0800 Subject: [PATCH 613/881] Remove hidden connectivity methods usage in ethernet test Bug: 182859030 Test: atest EthernetTrackerTest Test: 1. remove framework-connectivity.impl from framework bp 2. cd frameworks/opt/net/ethernet/tests ; mm Change-Id: Ifaeebfca75dc77eec30dd722ddb3166610795b26 --- .../server/ethernet/EthernetTrackerTest.java | 70 ++++++------------- 1 file changed, 21 insertions(+), 49 deletions(-) diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 43571bbc37..22b1b6939e 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -19,6 +19,7 @@ package com.android.server.ethernet; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import android.net.InetAddresses; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -33,6 +34,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.net.InetAddress; +import java.util.ArrayList; @SmallTest @RunWith(AndroidJUnit4.class) @@ -46,28 +48,26 @@ public class EthernetTrackerTest { assertStaticConfiguration(new StaticIpConfiguration(), ""); // Setting only the IP address properly cascades and assumes defaults - assertStaticConfiguration( - new StaticIpConfigBuilder().setIp("192.0.2.10/24").build(), - "ip=192.0.2.10/24"); + assertStaticConfiguration(new StaticIpConfiguration.Builder() + .setIpAddress(new LinkAddress("192.0.2.10/24")).build(), "ip=192.0.2.10/24"); + final ArrayList dnsAddresses = new ArrayList<>(); + dnsAddresses.add(InetAddresses.parseNumericAddress("4.4.4.4")); + dnsAddresses.add(InetAddresses.parseNumericAddress("8.8.8.8")); // Setting other fields properly cascades them - assertStaticConfiguration( - new StaticIpConfigBuilder() - .setIp("192.0.2.10/24") - .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) - .setGateway("192.0.2.1") - .setDomains("android") - .build(), + assertStaticConfiguration(new StaticIpConfiguration.Builder() + .setIpAddress(new LinkAddress("192.0.2.10/24")) + .setDnsServers(dnsAddresses) + .setGateway(InetAddresses.parseNumericAddress("192.0.2.1")) + .setDomains("android").build(), "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android"); // Verify order doesn't matter - assertStaticConfiguration( - new StaticIpConfigBuilder() - .setIp("192.0.2.10/24") - .setDns(new String[] {"4.4.4.4", "8.8.8.8"}) - .setGateway("192.0.2.1") - .setDomains("android") - .build(), + assertStaticConfiguration(new StaticIpConfiguration.Builder() + .setIpAddress(new LinkAddress("192.0.2.10/24")) + .setDnsServers(dnsAddresses) + .setGateway(InetAddresses.parseNumericAddress("192.0.2.1")) + .setDomains("android").build(), "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 "); } @@ -96,43 +96,15 @@ public class EthernetTrackerTest { private void assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig, String configAsString) { - IpConfiguration expectedIpConfiguration = new IpConfiguration(IpAssignment.STATIC, - ProxySettings.NONE, expectedStaticIpConfig, null); + final IpConfiguration expectedIpConfiguration = new IpConfiguration(); + expectedIpConfiguration.setIpAssignment(IpAssignment.STATIC); + expectedIpConfiguration.setProxySettings(ProxySettings.NONE); + expectedIpConfiguration.setStaticIpConfiguration(expectedStaticIpConfig); assertEquals(expectedIpConfiguration, EthernetTracker.parseStaticIpConfiguration(configAsString)); } - private static class StaticIpConfigBuilder { - private final StaticIpConfiguration config = new StaticIpConfiguration(); - - StaticIpConfigBuilder setIp(String address) { - config.ipAddress = new LinkAddress(address); - return this; - } - - StaticIpConfigBuilder setDns(String[] dnsArray) { - for (String dns : dnsArray) { - config.dnsServers.add(InetAddress.parseNumericAddress(dns)); - } - return this; - } - - StaticIpConfigBuilder setGateway(String gateway) { - config.gateway = InetAddress.parseNumericAddress(gateway); - return this; - } - - StaticIpConfigBuilder setDomains(String domains) { - config.domains = domains; - return this; - } - - StaticIpConfiguration build() { - return new StaticIpConfiguration(config); - } - } - private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) { final NetworkCapabilities.Builder builder = clearAll ? new NetworkCapabilities.Builder().clearAll() From f9707258edcdd478fe92a3ba6f2c4d35cc8b1ba4 Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 31 Dec 2020 17:26:28 +0800 Subject: [PATCH 614/881] wifi data usage: support to get carrier merged wifi network. Carrier merged wifi network is a specific cerrier wifi network which provides the same user experience as mobile. To support data usage accounting for carrier merged wifi, the change provide several APIs in NetworkTemplate: 1. extend buildTemplateWifi so it could be used for matching wifi networks with subscriber Id (IMSI). 2. add buildTemplateCarrier to let NetworkPolicyManagerService creates a single policy for a given carrier regardless of network type. Bug: 176396812 Test: atest -c NetworkTemplateTest Test: atest -c NetworkStatsServiceTest Test: Manual Test with test code on mobile and wifi network. 1. buildTemplateCarrier includes the carrier wifi and mobile usage 2. buildTemplateWifi can get carrier wifi usage and support the filter via subscriberId Change-Id: I667b4adf3eec0bdd3a7385109dd8c1fae8e7be32 --- core/java/android/net/NetworkTemplate.java | 160 +++++++++++++++++++-- 1 file changed, 147 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index c83dd99c2a..d3c8957494 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -82,6 +82,24 @@ public class NetworkTemplate implements Parcelable { public static final int MATCH_WIFI_WILDCARD = 7; public static final int MATCH_BLUETOOTH = 8; public static final int MATCH_PROXY = 9; + public static final int MATCH_CARRIER = 10; + + /** + * Value of the match rule of the subscriberId to match networks with specific subscriberId. + */ + public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0; + /** + * Value of the match rule of the subscriberId to match networks with any subscriberId which + * includes null and non-null. + */ + public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1; + + /** + * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that + * should be fixed), so it's not possible to want to match null vs + * non-null. Therefore it's fine to use null as a sentinel for Network ID. + */ + public static final String WIFI_NETWORKID_ALL = null; /** * Include all network types when filtering. This is meant to merge in with the @@ -125,6 +143,7 @@ public class NetworkTemplate implements Parcelable { case MATCH_WIFI_WILDCARD: case MATCH_BLUETOOTH: case MATCH_PROXY: + case MATCH_CARRIER: return true; default: @@ -168,10 +187,12 @@ public class NetworkTemplate implements Parcelable { @NetworkType int ratType) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL); + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_EXACT); } return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL); + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @@ -189,6 +210,8 @@ public class NetworkTemplate implements Parcelable { */ @UnsupportedAppUsage public static NetworkTemplate buildTemplateWifiWildcard() { + // TODO: Consider replace this with MATCH_WIFI with NETWORK_ID_ALL + // and SUBSCRIBER_ID_MATCH_RULE_ALL. return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null); } @@ -202,8 +225,27 @@ public class NetworkTemplate implements Parcelable { * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the * given SSID. */ - public static NetworkTemplate buildTemplateWifi(String networkId) { - return new NetworkTemplate(MATCH_WIFI, null, networkId); + public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) { + Objects.requireNonNull(networkId); + return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */, + new String[] { null } /* matchSubscriberIds */, + networkId, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_ALL); + } + + /** + * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID, + * and IMSI. + * + * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID. + */ + public static NetworkTemplate buildTemplateWifi(@Nullable String networkId, + @Nullable String subscriberId) { + return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId }, + networkId, METERED_ALL, ROAMING_ALL, + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @@ -231,6 +273,14 @@ public class NetworkTemplate implements Parcelable { return new NetworkTemplate(MATCH_PROXY, null, null); } + /** + * Template to match all carrier networks with the given IMSI. + */ + public static NetworkTemplate buildTemplateCarrier(@NonNull String subscriberId) { + Objects.requireNonNull(subscriberId); + return new NetworkTemplate(MATCH_CARRIER, subscriberId, null); + } + private final int mMatchRule; private final String mSubscriberId; @@ -251,10 +301,26 @@ public class NetworkTemplate implements Parcelable { private final int mRoaming; private final int mDefaultNetwork; private final int mSubType; + private final int mSubscriberIdMatchRule; // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}. private final int mOemManaged; + private void checkValidSubscriberIdMatchRule() { + switch (mMatchRule) { + case MATCH_MOBILE: + case MATCH_CARRIER: + // MOBILE and CARRIER templates must always specify a subscriber ID. + if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { + throw new IllegalArgumentException("Invalid SubscriberIdMatchRule" + + "on match rule: " + getMatchRuleName(mMatchRule)); + } + return; + default: + return; + } + } + @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); @@ -263,14 +329,25 @@ public class NetworkTemplate implements Parcelable { public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL); + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_EXACT); + } + + // TODO: Remove it after updating all of the caller. + public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, + String networkId, int metered, int roaming, int defaultNetwork, int subType, + int oemManaged) { + this(matchRule, subscriberId, matchSubscriberIds, networkId, metered, roaming, + defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT); } public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId, int metered, int roaming, int defaultNetwork, int subType, - int oemManaged) { + int oemManaged, int subscriberIdMatchRule) { mMatchRule = matchRule; mSubscriberId = subscriberId; + // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when + // mSubscriberId is null mMatchSubscriberIds = matchSubscriberIds; mNetworkId = networkId; mMetered = metered; @@ -278,7 +355,8 @@ public class NetworkTemplate implements Parcelable { mDefaultNetwork = defaultNetwork; mSubType = subType; mOemManaged = oemManaged; - + mSubscriberIdMatchRule = subscriberIdMatchRule; + checkValidSubscriberIdMatchRule(); if (!isKnownMatchRule(matchRule)) { Log.e(TAG, "Unknown network template rule " + matchRule + " will not match any identity."); @@ -295,6 +373,7 @@ public class NetworkTemplate implements Parcelable { mDefaultNetwork = in.readInt(); mSubType = in.readInt(); mOemManaged = in.readInt(); + mSubscriberIdMatchRule = in.readInt(); } @Override @@ -308,6 +387,7 @@ public class NetworkTemplate implements Parcelable { dest.writeInt(mDefaultNetwork); dest.writeInt(mSubType); dest.writeInt(mOemManaged); + dest.writeInt(mSubscriberIdMatchRule); } @Override @@ -346,13 +426,15 @@ public class NetworkTemplate implements Parcelable { if (mOemManaged != OEM_MANAGED_ALL) { builder.append(", oemManaged=").append(mOemManaged); } + builder.append(", subscriberIdMatchRule=") + .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule)); return builder.toString(); } @Override public int hashCode() { return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, - mDefaultNetwork, mSubType, mOemManaged); + mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule); } @Override @@ -366,11 +448,23 @@ public class NetworkTemplate implements Parcelable { && mRoaming == other.mRoaming && mDefaultNetwork == other.mDefaultNetwork && mSubType == other.mSubType - && mOemManaged == other.mOemManaged; + && mOemManaged == other.mOemManaged + && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule; } return false; } + private String subscriberIdMatchRuleToString(int rule) { + switch (rule) { + case SUBSCRIBER_ID_MATCH_RULE_EXACT: + return "EXACT_MATCH"; + case SUBSCRIBER_ID_MATCH_RULE_ALL: + return "ALL"; + default: + return "Unknown rule " + rule; + } + } + public boolean isMatchRuleMobile() { switch (mMatchRule) { case MATCH_MOBILE: @@ -386,6 +480,14 @@ public class NetworkTemplate implements Parcelable { case MATCH_MOBILE_WILDCARD: case MATCH_WIFI_WILDCARD: return false; + case MATCH_CARRIER: + return mSubscriberId != null; + case MATCH_WIFI: + if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) + && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { + return false; + } + return true; default: return true; } @@ -405,6 +507,10 @@ public class NetworkTemplate implements Parcelable { return mNetworkId; } + public int getSubscriberIdMatchRule() { + return mSubscriberIdMatchRule; + } + /** * Test if given {@link NetworkIdentity} matches this template. */ @@ -429,6 +535,8 @@ public class NetworkTemplate implements Parcelable { return matchesBluetooth(ident); case MATCH_PROXY: return matchesProxy(ident); + case MATCH_CARRIER: + return matchesCarrier(ident); default: // We have no idea what kind of network template we are, so we // just claim not to match anything. @@ -466,8 +574,23 @@ public class NetworkTemplate implements Parcelable { || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType); } - public boolean matchesSubscriberId(String subscriberId) { - return ArrayUtils.contains(mMatchSubscriberIds, subscriberId); + /** + * Check if this template matches {@code subscriberId}. Returns true if this + * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a + * {@code mMatchSubscriberIds} array that contains {@code subscriberId}. + */ + public boolean matchesSubscriberId(@Nullable String subscriberId) { + return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL + || ArrayUtils.contains(mMatchSubscriberIds, subscriberId); + } + + /** + * Check if network with matching SSID. Returns true when the SSID matches, or when + * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}. + */ + private boolean matchesWifiNetworkId(@Nullable String networkId) { + return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) + || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId)); } /** @@ -566,8 +689,8 @@ public class NetworkTemplate implements Parcelable { private boolean matchesWifi(NetworkIdentity ident) { switch (ident.mType) { case TYPE_WIFI: - return Objects.equals( - sanitizeSsid(mNetworkId), sanitizeSsid(ident.mNetworkId)); + return matchesSubscriberId(ident.mSubscriberId) + && matchesWifiNetworkId(ident.mNetworkId); default: return false; } @@ -583,6 +706,15 @@ public class NetworkTemplate implements Parcelable { return false; } + /** + * Check if matches carrier network. The carrier networks means it includes the subscriberId. + */ + private boolean matchesCarrier(NetworkIdentity ident) { + return ident.mSubscriberId != null + && !ArrayUtils.isEmpty(mMatchSubscriberIds) + && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); + } + private boolean matchesMobileWildcard(NetworkIdentity ident) { if (ident.mType == TYPE_WIMAX) { return true; @@ -635,6 +767,8 @@ public class NetworkTemplate implements Parcelable { return "BLUETOOTH"; case MATCH_PROXY: return "PROXY"; + case MATCH_CARRIER: + return "CARRIER"; default: return "UNKNOWN(" + matchRule + ")"; } From 69c1f216b11d002fc2719e8167942f3fbcc8c6b5 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 16 Apr 2021 23:20:23 +0800 Subject: [PATCH 615/881] Add getters to UnderlyingNetworkInfo Address API review feedback, add getters to UnderlyingNetworkInfo instead of exposing fields. Instead of wasting memory by converting this into an array, have migrateTun take a List. In turn, tunAdjustmentInit should also take a List. Bug: 183972554 Test: atest android.net.UnderlyingNetworkInfoTest Change-Id: Id59744097208d91298a25ef110ade91a9cf291a1 --- core/java/android/net/NetworkStats.java | 31 +++++----- .../android/net/UnderlyingNetworkInfo.java | 60 ++++++++++++------- .../server/net/NetworkStatsFactory.java | 4 +- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index d42beae601..6ccbab7ed8 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -38,6 +38,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Predicate; @@ -1423,11 +1424,11 @@ public final class NetworkStats implements Parcelable { * @hide */ public void migrateTun(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces) { + @NonNull List underlyingIfaces) { // Combined usage by all apps using VPN. final Entry tunIfaceTotal = new Entry(); // Usage by VPN, grouped by its {@code underlyingIfaces}. - final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; + final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.size()]; // Usage by VPN, summed across all its {@code underlyingIfaces}. final Entry underlyingIfacesTotal = new Entry(); @@ -1468,7 +1469,7 @@ public final class NetworkStats implements Parcelable { * {@code underlyingIfaces} */ private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull List underlyingIfaces, @NonNull Entry tunIfaceTotal, @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { final Entry recycle = new Entry(); for (int i = 0; i < size; i++) { @@ -1488,8 +1489,8 @@ public final class NetworkStats implements Parcelable { if (recycle.uid == tunUid) { // Add up traffic through tunUid's underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - if (Objects.equals(underlyingIfaces[j], recycle.iface)) { + for (int j = 0; j < underlyingIfaces.size(); j++) { + if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) { perInterfaceTotal[j].add(recycle); underlyingIfacesTotal.add(recycle); break; @@ -1515,12 +1516,12 @@ public final class NetworkStats implements Parcelable { * underlyingIfaces} */ private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull List underlyingIfaces, @NonNull Entry tunIfaceTotal, @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { // Traffic that should be moved off of each underlying interface for tunUid (see // deductTrafficFromVpnApp below). - final Entry[] moved = new Entry[underlyingIfaces.length]; - for (int i = 0; i < underlyingIfaces.length; i++) { + final Entry[] moved = new Entry[underlyingIfaces.size()]; + for (int i = 0; i < underlyingIfaces.size(); i++) { moved[i] = new Entry(); } @@ -1582,8 +1583,8 @@ public final class NetworkStats implements Parcelable { } // In a second pass, distribute these values across interfaces in the proportion that // each interface represents of the total traffic of the underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - tmpEntry.iface = underlyingIfaces[j]; + for (int j = 0; j < underlyingIfaces.size(); j++) { + tmpEntry.iface = underlyingIfaces.get(j); tmpEntry.rxBytes = 0; // Reset 'set' to correct value since it gets updated when adding debug info below. tmpEntry.set = set[i]; @@ -1638,14 +1639,14 @@ public final class NetworkStats implements Parcelable { private void deductTrafficFromVpnApp( int tunUid, - @NonNull String[] underlyingIfaces, + @NonNull List underlyingIfaces, @NonNull Entry[] moved) { - for (int i = 0; i < underlyingIfaces.length; i++) { + for (int i = 0; i < underlyingIfaces.size(); i++) { moved[i].uid = tunUid; // Add debug info moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; - moved[i].iface = underlyingIfaces[i]; + moved[i].iface = underlyingIfaces.get(i); moved[i].metered = METERED_ALL; moved[i].roaming = ROAMING_ALL; moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; @@ -1658,7 +1659,7 @@ public final class NetworkStats implements Parcelable { // METERED_NO, which should be the case as it comes directly from the /proc file. // We only blend in the roaming data after applying these adjustments, by checking the // NetworkIdentity of the underlying iface. - final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, + final int idxVpnBackground = findIndex(underlyingIfaces.get(i), tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnBackground != -1) { // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed @@ -1666,7 +1667,7 @@ public final class NetworkStats implements Parcelable { tunSubtract(idxVpnBackground, this, moved[i]); } - final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, + final int idxVpnForeground = findIndex(underlyingIfaces.get(i), tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnForeground != -1) { tunSubtract(idxVpnForeground, this, moved[i]); diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java index 7bf9231239..459fdacef8 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.java +++ b/core/java/android/net/UnderlyingNetworkInfo.java @@ -37,36 +37,56 @@ import java.util.Objects; @SystemApi(client = MODULE_LIBRARIES) public final class UnderlyingNetworkInfo implements Parcelable { /** The owner of this network. */ - public final int ownerUid; + private final int mOwnerUid; + /** The interface name of this network. */ @NonNull - public final String iface; + private final String mIface; + /** The names of the interfaces underlying this network. */ @NonNull - public final List underlyingIfaces; + private final List mUnderlyingIfaces; public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface, @NonNull List underlyingIfaces) { Objects.requireNonNull(iface); Objects.requireNonNull(underlyingIfaces); - this.ownerUid = ownerUid; - this.iface = iface; - this.underlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces)); + mOwnerUid = ownerUid; + mIface = iface; + mUnderlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces)); } private UnderlyingNetworkInfo(@NonNull Parcel in) { - this.ownerUid = in.readInt(); - this.iface = in.readString(); - this.underlyingIfaces = new ArrayList<>(); - in.readList(this.underlyingIfaces, null /*classLoader*/); + mOwnerUid = in.readInt(); + mIface = in.readString(); + List underlyingIfaces = new ArrayList<>(); + in.readList(underlyingIfaces, null /*classLoader*/); + mUnderlyingIfaces = Collections.unmodifiableList(underlyingIfaces); + } + + /** Get the owner of this network. */ + public int getOwnerUid() { + return mOwnerUid; + } + + /** Get the interface name of this network. */ + @NonNull + public String getIface() { + return mIface; + } + + /** Get the names of the interfaces underlying this network. */ + @NonNull + public List getUnderlyingIfaces() { + return mUnderlyingIfaces; } @Override public String toString() { return "UnderlyingNetworkInfo{" - + "ownerUid=" + ownerUid - + ", iface='" + iface + '\'' - + ", underlyingIfaces='" + underlyingIfaces.toString() + '\'' + + "ownerUid=" + mOwnerUid + + ", iface='" + mIface + '\'' + + ", underlyingIfaces='" + mUnderlyingIfaces.toString() + '\'' + '}'; } @@ -77,9 +97,9 @@ public final class UnderlyingNetworkInfo implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(ownerUid); - dest.writeString(iface); - dest.writeList(underlyingIfaces); + dest.writeInt(mOwnerUid); + dest.writeString(mIface); + dest.writeList(mUnderlyingIfaces); } @NonNull @@ -103,13 +123,13 @@ public final class UnderlyingNetworkInfo implements Parcelable { if (this == o) return true; if (!(o instanceof UnderlyingNetworkInfo)) return false; final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o; - return ownerUid == that.ownerUid - && Objects.equals(iface, that.iface) - && Objects.equals(underlyingIfaces, that.underlyingIfaces); + return mOwnerUid == that.getOwnerUid() + && Objects.equals(mIface, that.getIface()) + && Objects.equals(mUnderlyingIfaces, that.getUnderlyingIfaces()); } @Override public int hashCode() { - return Objects.hash(ownerUid, iface, underlyingIfaces); + return Objects.hash(mOwnerUid, mIface, mUnderlyingIfaces); } } diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index d042b882fe..e7c0a50163 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -382,8 +382,8 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (UnderlyingNetworkInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.iface, - info.underlyingIfaces.toArray(new String[0])); + delta.migrateTun(info.getOwnerUid(), info.getIface(), + info.getUnderlyingIfaces()); // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } From 80a4d561a344c4e19578c3e0d5951c0baf16f6ee Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 20 Apr 2021 17:19:46 +0800 Subject: [PATCH 616/881] Add getters to NetworkStateSnapshot Address API council feedback, add getters to NetworkStateSnapshot instead of exposing the bare fields directly. Bug: 183972826 Test: FrameworksNetTests Change-Id: Id1707753b42ae88d2b95e4bd00a792609434e4f5 --- core/java/android/net/NetworkIdentity.java | 12 +-- .../android/net/NetworkStateSnapshot.java | 92 ++++++++++++------- .../server/net/NetworkStatsService.java | 21 ++--- 3 files changed, 77 insertions(+), 48 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 1eef7d9a53..3bde6fa691 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -186,19 +186,19 @@ public class NetworkIdentity implements Comparable { */ public static NetworkIdentity buildNetworkIdentity(Context context, NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) { - final int legacyType = snapshot.legacyType; + final int legacyType = snapshot.getLegacyType(); - final String subscriberId = snapshot.subscriberId; + final String subscriberId = snapshot.getSubscriberId(); String networkId = null; - boolean roaming = !snapshot.networkCapabilities.hasCapability( + boolean roaming = !snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - boolean metered = !snapshot.networkCapabilities.hasCapability( + boolean metered = !snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - final int oemManaged = getOemBitfield(snapshot.networkCapabilities); + final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities()); if (legacyType == TYPE_WIFI) { - networkId = snapshot.networkCapabilities.getSsid(); + networkId = snapshot.getNetworkCapabilities().getSsid(); if (networkId == null) { final WifiManager wifi = context.getSystemService(WifiManager.class); final WifiInfo info = wifi.getConnectionInfo(); diff --git a/core/java/android/net/NetworkStateSnapshot.java b/core/java/android/net/NetworkStateSnapshot.java index 0d26c2de86..9df861a6ff 100644 --- a/core/java/android/net/NetworkStateSnapshot.java +++ b/core/java/android/net/NetworkStateSnapshot.java @@ -37,47 +37,76 @@ import java.util.Objects; public final class NetworkStateSnapshot implements Parcelable { /** The network associated with this snapshot. */ @NonNull - public final Network network; + private final Network mNetwork; /** The {@link NetworkCapabilities} of the network associated with this snapshot. */ @NonNull - public final NetworkCapabilities networkCapabilities; + private final NetworkCapabilities mNetworkCapabilities; /** The {@link LinkProperties} of the network associated with this snapshot. */ @NonNull - public final LinkProperties linkProperties; + private final LinkProperties mLinkProperties; /** * The Subscriber Id of the network associated with this snapshot. See * {@link android.telephony.TelephonyManager#getSubscriberId()}. */ @Nullable - public final String subscriberId; + private final String mSubscriberId; /** * The legacy type of the network associated with this snapshot. See * {@code ConnectivityManager#TYPE_*}. */ - public final int legacyType; + private final int mLegacyType; public NetworkStateSnapshot(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities, @NonNull LinkProperties linkProperties, @Nullable String subscriberId, int legacyType) { - this.network = Objects.requireNonNull(network); - this.networkCapabilities = Objects.requireNonNull(networkCapabilities); - this.linkProperties = Objects.requireNonNull(linkProperties); - this.subscriberId = subscriberId; - this.legacyType = legacyType; + mNetwork = Objects.requireNonNull(network); + mNetworkCapabilities = Objects.requireNonNull(networkCapabilities); + mLinkProperties = Objects.requireNonNull(linkProperties); + mSubscriberId = subscriberId; + mLegacyType = legacyType; } /** @hide */ public NetworkStateSnapshot(@NonNull Parcel in) { - network = in.readParcelable(null); - networkCapabilities = in.readParcelable(null); - linkProperties = in.readParcelable(null); - subscriberId = in.readString(); - legacyType = in.readInt(); + mNetwork = in.readParcelable(null); + mNetworkCapabilities = in.readParcelable(null); + mLinkProperties = in.readParcelable(null); + mSubscriberId = in.readString(); + mLegacyType = in.readInt(); + } + + /** Get the network associated with this snapshot */ + @NonNull + public Network getNetwork() { + return mNetwork; + } + + /** Get {@link NetworkCapabilities} of the network associated with this snapshot. */ + @NonNull + public NetworkCapabilities getNetworkCapabilities() { + return mNetworkCapabilities; + } + + /** Get the {@link LinkProperties} of the network associated with this snapshot. */ + @NonNull + public LinkProperties getLinkProperties() { + return mLinkProperties; + } + + /** Get the Subscriber Id of the network associated with this snapshot. */ + @Nullable + public String getSubscriberId() { + return mSubscriberId; + } + + /** Get the legacy type of the network associated with this snapshot. */ + public int getLegacyType() { + return mLegacyType; } @Override @@ -87,11 +116,11 @@ public final class NetworkStateSnapshot implements Parcelable { @Override public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeParcelable(network, flags); - out.writeParcelable(networkCapabilities, flags); - out.writeParcelable(linkProperties, flags); - out.writeString(subscriberId); - out.writeInt(legacyType); + out.writeParcelable(mNetwork, flags); + out.writeParcelable(mNetworkCapabilities, flags); + out.writeParcelable(mLinkProperties, flags); + out.writeString(mSubscriberId); + out.writeInt(mLegacyType); } @NonNull @@ -115,26 +144,27 @@ public final class NetworkStateSnapshot implements Parcelable { if (this == o) return true; if (!(o instanceof NetworkStateSnapshot)) return false; NetworkStateSnapshot that = (NetworkStateSnapshot) o; - return legacyType == that.legacyType - && Objects.equals(network, that.network) - && Objects.equals(networkCapabilities, that.networkCapabilities) - && Objects.equals(linkProperties, that.linkProperties) - && Objects.equals(subscriberId, that.subscriberId); + return mLegacyType == that.mLegacyType + && Objects.equals(mNetwork, that.mNetwork) + && Objects.equals(mNetworkCapabilities, that.mNetworkCapabilities) + && Objects.equals(mLinkProperties, that.mLinkProperties) + && Objects.equals(mSubscriberId, that.mSubscriberId); } @Override public int hashCode() { - return Objects.hash(network, networkCapabilities, linkProperties, subscriberId, legacyType); + return Objects.hash(mNetwork, + mNetworkCapabilities, mLinkProperties, mSubscriberId, mLegacyType); } @Override public String toString() { return "NetworkStateSnapshot{" - + "network=" + network - + ", networkCapabilities=" + networkCapabilities - + ", linkProperties=" + linkProperties - + ", subscriberId='" + NetworkIdentityUtils.scrubSubscriberId(subscriberId) + '\'' - + ", legacyType=" + legacyType + + "network=" + mNetwork + + ", networkCapabilities=" + mNetworkCapabilities + + ", linkProperties=" + mLinkProperties + + ", subscriberId='" + NetworkIdentityUtils.scrubSubscriberId(mSubscriberId) + '\'' + + ", legacyType=" + mLegacyType + '}'; } } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 19f5e3cd5d..3c14440c64 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -24,7 +24,6 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; @@ -97,12 +96,12 @@ import android.net.INetworkStatsSession; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; +import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; -import android.net.NetworkSpecifier; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; import android.net.TrafficStats; @@ -1296,9 +1295,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkStateSnapshot snapshot : snapshots) { final int displayTransport = - getDisplayTransport(snapshot.networkCapabilities.getTransportTypes()); + getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes()); final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); - final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.network); + final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.getNetwork()); final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED : getSubTypeForStateSnapshot(snapshot); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot, @@ -1306,7 +1305,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Traffic occurring on the base interface is always counted for // both total usage and UID details. - final String baseIface = snapshot.linkProperties.getInterfaceName(); + final String baseIface = snapshot.getLinkProperties().getInterfaceName(); if (baseIface != null) { findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident); findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident); @@ -1316,7 +1315,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // If IMS is metered, then the IMS network usage has already included VT usage. // VT is considered always metered in framework's layer. If VT is not metered // per carrier's policy, modem will report 0 usage for VT calls. - if (snapshot.networkCapabilities.hasCapability( + if (snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) { // Copy the identify from IMS one but mark it as metered. @@ -1364,7 +1363,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // accounting is explicitly bypassed for traffic from the clat uid. // // TODO: This code might be combined to above code. - for (String iface : snapshot.linkProperties.getAllInterfaceNames()) { + for (String iface : snapshot.getLinkProperties().getAllInterfaceNames()) { // baseIface has been handled, so ignore it. if (TextUtils.equals(baseIface, iface)) continue; if (iface != null) { @@ -1383,11 +1382,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { - if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR"); } - final NetworkSpecifier spec = state.networkCapabilities.getNetworkSpecifier(); + final NetworkSpecifier spec = state.getNetworkCapabilities().getNetworkSpecifier(); if (spec instanceof TelephonyNetworkSpecifier) { return ((TelephonyNetworkSpecifier) spec).getSubscriptionId(); } else { @@ -1402,11 +1401,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * transport types do not actually fill this value. */ private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) { - if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return 0; } - return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.subscriberId); + return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.getSubscriberId()); } private static NetworkIdentitySet findOrCreateNetworkIdentitySet( From 9ea496b0ae81ec03e68674b4650e018fee941102 Mon Sep 17 00:00:00 2001 From: Nazanin Date: Thu, 15 Apr 2021 14:18:15 -0700 Subject: [PATCH 617/881] Security fix: enforce read privilege permission to check package privileges in TelephonyManager Bug: 180938364 Test: cts Change-Id: I08c346c46b9e87dceaa1faf35fa36b954d88f9b0 --- .../com/android/server/net/NetworkStatsAccess.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 7cdc4cc747..d25eae409d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -27,6 +27,7 @@ import android.app.AppOpsManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; +import android.os.Binder; import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; @@ -108,9 +109,16 @@ public final class NetworkStatsAccess { DevicePolicyManagerInternal.class); final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - boolean hasCarrierPrivileges = tm != null && - tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == - TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; + boolean hasCarrierPrivileges; + final long token = Binder.clearCallingIdentity(); + try { + hasCarrierPrivileges = tm != null + && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; + } finally { + Binder.restoreCallingIdentity(token); + } + final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); final int appId = UserHandle.getAppId(callingUid); if (hasCarrierPrivileges || isDeviceOwner From 57d1c1bf53eb0bc8995252a0f90c474fcb3b9922 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 10:33:16 +0800 Subject: [PATCH 618/881] [SP28] Add API for set data warning To have better control and race-free of set data warning to tether offload hardware, an interface of set warning and limit at the same time in the NetworkStatsProvider is needed. This is a no-op change which expose such interface with minimum changes in service side to get build pass. The implementation would be included in follow-up patches. Test: atest NetworkStatsServiceTest Test: atest NetworkPolicyManagerServiceTest Test: atest GtsNetworkStackHostTestCases Test: m doc-comment-check-docs Bug: 149467454 Bug: 170699770 Bug: 170179169 Merged-In: I6ee661497f7dedb871c85786d1950cab951d8aa2 Change-Id: I6ee661497f7dedb871c85786d1950cab951d8aa2 (cherry-picked from ag/13959436) --- .../provider/INetworkStatsProvider.aidl | 2 +- .../INetworkStatsProviderCallback.aidl | 2 +- .../provider/NetworkStatsProvider.java | 58 ++++++++++++++++--- .../server/net/NetworkStatsService.java | 10 ++-- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl index 4078b24921..74c3ba44b6 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl @@ -23,6 +23,6 @@ package android.net.netstats.provider; */ oneway interface INetworkStatsProvider { void onRequestStatsUpdate(int token); - void onSetLimit(String iface, long quotaBytes); void onSetAlert(long quotaBytes); + void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes); } diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index bd336dd348..7eaa01e262 100644 --- a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -26,6 +26,6 @@ import android.net.NetworkStats; oneway interface INetworkStatsProviderCallback { void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); void notifyAlertReached(); - void notifyLimitReached(); + void notifyWarningOrLimitReached(); void unregister(); } diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java index 7639d2244c..65b336ad6f 100644 --- a/core/java/android/net/netstats/provider/NetworkStatsProvider.java +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -29,7 +29,8 @@ import android.os.RemoteException; @SystemApi public abstract class NetworkStatsProvider { /** - * A value used by {@link #onSetLimit} and {@link #onSetAlert} indicates there is no limit. + * A value used by {@link #onSetLimit}, {@link #onSetAlert} and {@link #onSetWarningAndLimit} + * indicates there is no limit. */ public static final int QUOTA_UNLIMITED = -1; @@ -42,13 +43,13 @@ public abstract class NetworkStatsProvider { } @Override - public void onSetLimit(String iface, long quotaBytes) { - NetworkStatsProvider.this.onSetLimit(iface, quotaBytes); + public void onSetAlert(long quotaBytes) { + NetworkStatsProvider.this.onSetAlert(quotaBytes); } @Override - public void onSetAlert(long quotaBytes) { - NetworkStatsProvider.this.onSetAlert(quotaBytes); + public void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes) { + NetworkStatsProvider.this.onSetWarningAndLimit(iface, warningBytes, limitBytes); } }; @@ -145,11 +146,28 @@ public abstract class NetworkStatsProvider { } /** - * Notify system that the quota set by {@code onSetLimit} has been reached. + * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached. + * + * @hide + */ + // TODO: Expose as system API. + public void notifyWarningReached() { + try { + // Reuse the code path to notify warning reached with limit reached + // since framework handles them in the same way. + getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); + } catch (RemoteException e) { + e.rethrowAsRuntimeException(); + } + } + + /** + * Notify system that the quota set by {@link #onSetLimit} or limit set by + * {@link #onSetWarningAndLimit} has been reached. */ public void notifyLimitReached() { try { - getProviderCallbackBinderOrThrow().notifyLimitReached(); + getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } @@ -180,8 +198,34 @@ public abstract class NetworkStatsProvider { * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. */ + // TODO: deprecate this once onSetWarningAndLimit is ready. public abstract void onSetLimit(@NonNull String iface, long quotaBytes); + /** + * Called by {@code NetworkStatsService} when setting the interface quotas for the specified + * upstream interface. If a provider implements {@link #onSetWarningAndLimit}, the system + * will not call {@link #onSetLimit}. When this method is called, the implementation + * should behave as follows: + * 1. If {@code warningBytes} is reached on {@code iface}, block all further traffic on + * {@code iface} and call {@link NetworkStatsProvider@notifyWarningReached()}. + * 2. If {@code limitBytes} is reached on {@code iface}, block all further traffic on + * {@code iface} and call {@link NetworkStatsProvider#notifyLimitReached()}. + * + * @param iface the interface requiring the operation. + * @param warningBytes the warning defined as the number of bytes, starting from zero and + * counting from now. A value of {@link #QUOTA_UNLIMITED} indicates + * there is no warning. + * @param limitBytes the limit defined as the number of bytes, starting from zero and counting + * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. + * + * @hide + */ + // TODO: Expose as system API. + public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) { + // Backward compatibility for those who didn't override this function. + onSetLimit(iface, limitBytes); + } + /** * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index ba9f486092..191ff096c8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1660,7 +1660,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetLimit(iface, quota)); + // TODO: Set warning accordingly. + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, + NetworkStatsProvider.QUOTA_UNLIMITED, quota)); } } @@ -2051,10 +2053,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void notifyLimitReached() { - Log.d(TAG, mTag + ": onLimitReached"); + public void notifyWarningOrLimitReached() { + Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); LocalServices.getService(NetworkPolicyManagerInternal.class) - .onStatsProviderLimitReached(mTag); + .onStatsProviderWarningOrLimitReached(mTag); } @Override From 7d627db6612792d5c2cc0e56e3d00293ba357ad2 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 24 Mar 2021 14:17:19 +0800 Subject: [PATCH 619/881] [SP29] Send interface warning bytes to NetworkStatsProvider This change contains necessary modification in NPMS and NSS to send warning bytes to NetworkStatsProvider. But since no any provider has been upgraded to handle such parameter. Thus, no behavior change is made in this patch. Test: atest NetworkPolicyManagerServiceTest NetworkStatsServiceTest Test: atest NetworkPolicyManagerServiceTest#testStatsProviderWarningAndLimitReached Bug: 149467454 Bug: 170699770 Bug: 170179169 Merged-In: I6c4863030c36328db571294fd12a40e59864def5 Change-Id: I6c4863030c36328db571294fd12a40e59864def5 (cherry-picked from ag/13982166) --- .../com/android/server/net/NetworkStatsService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 191ff096c8..0bc20540a7 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1658,11 +1658,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void setStatsProviderLimitAsync(@NonNull String iface, long quota) { - if (LOGV) Slog.v(TAG, "setStatsProviderLimitAsync(" + iface + "," + quota + ")"); - // TODO: Set warning accordingly. + public void setStatsProviderWarningAndLimitAsync( + @NonNull String iface, long warning, long limit) { + if (LOGV) { + Slog.v(TAG, "setStatsProviderWarningAndLimitAsync(" + + iface + "," + warning + "," + limit + ")"); + } invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, - NetworkStatsProvider.QUOTA_UNLIMITED, quota)); + warning, limit)); } } From 32631f5a6ca72a900f6eef5b026b83ae3a40683c Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 19:45:05 +0800 Subject: [PATCH 620/881] [SP31] Expose onSetWarningAndLimit System API Test: atest NetworkPolicyManagerServiceTest NetworkStatsServiceTest Bug: 149467454 CTS-Coverage-Bug: 183598414 Merged-In: I6f5e22e3a7b80a38cae9f3c5d7296a1dff34facf Change-Id: I6f5e22e3a7b80a38cae9f3c5d7296a1dff34facf (cherry-picked from ag/13981689 with fixed merged conflict) --- .../net/netstats/provider/NetworkStatsProvider.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/core/java/android/net/netstats/provider/NetworkStatsProvider.java index 65b336ad6f..23fc06927e 100644 --- a/core/java/android/net/netstats/provider/NetworkStatsProvider.java +++ b/core/java/android/net/netstats/provider/NetworkStatsProvider.java @@ -147,10 +147,7 @@ public abstract class NetworkStatsProvider { /** * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached. - * - * @hide */ - // TODO: Expose as system API. public void notifyWarningReached() { try { // Reuse the code path to notify warning reached with limit reached @@ -198,7 +195,6 @@ public abstract class NetworkStatsProvider { * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. */ - // TODO: deprecate this once onSetWarningAndLimit is ready. public abstract void onSetLimit(@NonNull String iface, long quotaBytes); /** @@ -217,10 +213,7 @@ public abstract class NetworkStatsProvider { * there is no warning. * @param limitBytes the limit defined as the number of bytes, starting from zero and counting * from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit. - * - * @hide */ - // TODO: Expose as system API. public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) { // Backward compatibility for those who didn't override this function. onSetLimit(iface, limitBytes); From 484e857368608f5d0d01787cb793b46b15934c88 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 20 Apr 2021 17:19:46 +0800 Subject: [PATCH 621/881] Add getters to NetworkStateSnapshot Address API council feedback, add getters to NetworkStateSnapshot instead of exposing the bare fields directly. (cherry picked from ag/14233655) Bug: 183972826 Test: FrameworksNetTests Merged-In: Id1707753b42ae88d2b95e4bd00a792609434e4f5 Change-Id: Id1707753b42ae88d2b95e4bd00a792609434e4f5 --- core/java/android/net/NetworkIdentity.java | 12 +-- .../android/net/NetworkStateSnapshot.java | 92 ++++++++++++------- .../server/net/NetworkStatsService.java | 21 ++--- 3 files changed, 77 insertions(+), 48 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 1eef7d9a53..3bde6fa691 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -186,19 +186,19 @@ public class NetworkIdentity implements Comparable { */ public static NetworkIdentity buildNetworkIdentity(Context context, NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) { - final int legacyType = snapshot.legacyType; + final int legacyType = snapshot.getLegacyType(); - final String subscriberId = snapshot.subscriberId; + final String subscriberId = snapshot.getSubscriberId(); String networkId = null; - boolean roaming = !snapshot.networkCapabilities.hasCapability( + boolean roaming = !snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - boolean metered = !snapshot.networkCapabilities.hasCapability( + boolean metered = !snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_METERED); - final int oemManaged = getOemBitfield(snapshot.networkCapabilities); + final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities()); if (legacyType == TYPE_WIFI) { - networkId = snapshot.networkCapabilities.getSsid(); + networkId = snapshot.getNetworkCapabilities().getSsid(); if (networkId == null) { final WifiManager wifi = context.getSystemService(WifiManager.class); final WifiInfo info = wifi.getConnectionInfo(); diff --git a/core/java/android/net/NetworkStateSnapshot.java b/core/java/android/net/NetworkStateSnapshot.java index 0d26c2de86..9df861a6ff 100644 --- a/core/java/android/net/NetworkStateSnapshot.java +++ b/core/java/android/net/NetworkStateSnapshot.java @@ -37,47 +37,76 @@ import java.util.Objects; public final class NetworkStateSnapshot implements Parcelable { /** The network associated with this snapshot. */ @NonNull - public final Network network; + private final Network mNetwork; /** The {@link NetworkCapabilities} of the network associated with this snapshot. */ @NonNull - public final NetworkCapabilities networkCapabilities; + private final NetworkCapabilities mNetworkCapabilities; /** The {@link LinkProperties} of the network associated with this snapshot. */ @NonNull - public final LinkProperties linkProperties; + private final LinkProperties mLinkProperties; /** * The Subscriber Id of the network associated with this snapshot. See * {@link android.telephony.TelephonyManager#getSubscriberId()}. */ @Nullable - public final String subscriberId; + private final String mSubscriberId; /** * The legacy type of the network associated with this snapshot. See * {@code ConnectivityManager#TYPE_*}. */ - public final int legacyType; + private final int mLegacyType; public NetworkStateSnapshot(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities, @NonNull LinkProperties linkProperties, @Nullable String subscriberId, int legacyType) { - this.network = Objects.requireNonNull(network); - this.networkCapabilities = Objects.requireNonNull(networkCapabilities); - this.linkProperties = Objects.requireNonNull(linkProperties); - this.subscriberId = subscriberId; - this.legacyType = legacyType; + mNetwork = Objects.requireNonNull(network); + mNetworkCapabilities = Objects.requireNonNull(networkCapabilities); + mLinkProperties = Objects.requireNonNull(linkProperties); + mSubscriberId = subscriberId; + mLegacyType = legacyType; } /** @hide */ public NetworkStateSnapshot(@NonNull Parcel in) { - network = in.readParcelable(null); - networkCapabilities = in.readParcelable(null); - linkProperties = in.readParcelable(null); - subscriberId = in.readString(); - legacyType = in.readInt(); + mNetwork = in.readParcelable(null); + mNetworkCapabilities = in.readParcelable(null); + mLinkProperties = in.readParcelable(null); + mSubscriberId = in.readString(); + mLegacyType = in.readInt(); + } + + /** Get the network associated with this snapshot */ + @NonNull + public Network getNetwork() { + return mNetwork; + } + + /** Get {@link NetworkCapabilities} of the network associated with this snapshot. */ + @NonNull + public NetworkCapabilities getNetworkCapabilities() { + return mNetworkCapabilities; + } + + /** Get the {@link LinkProperties} of the network associated with this snapshot. */ + @NonNull + public LinkProperties getLinkProperties() { + return mLinkProperties; + } + + /** Get the Subscriber Id of the network associated with this snapshot. */ + @Nullable + public String getSubscriberId() { + return mSubscriberId; + } + + /** Get the legacy type of the network associated with this snapshot. */ + public int getLegacyType() { + return mLegacyType; } @Override @@ -87,11 +116,11 @@ public final class NetworkStateSnapshot implements Parcelable { @Override public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeParcelable(network, flags); - out.writeParcelable(networkCapabilities, flags); - out.writeParcelable(linkProperties, flags); - out.writeString(subscriberId); - out.writeInt(legacyType); + out.writeParcelable(mNetwork, flags); + out.writeParcelable(mNetworkCapabilities, flags); + out.writeParcelable(mLinkProperties, flags); + out.writeString(mSubscriberId); + out.writeInt(mLegacyType); } @NonNull @@ -115,26 +144,27 @@ public final class NetworkStateSnapshot implements Parcelable { if (this == o) return true; if (!(o instanceof NetworkStateSnapshot)) return false; NetworkStateSnapshot that = (NetworkStateSnapshot) o; - return legacyType == that.legacyType - && Objects.equals(network, that.network) - && Objects.equals(networkCapabilities, that.networkCapabilities) - && Objects.equals(linkProperties, that.linkProperties) - && Objects.equals(subscriberId, that.subscriberId); + return mLegacyType == that.mLegacyType + && Objects.equals(mNetwork, that.mNetwork) + && Objects.equals(mNetworkCapabilities, that.mNetworkCapabilities) + && Objects.equals(mLinkProperties, that.mLinkProperties) + && Objects.equals(mSubscriberId, that.mSubscriberId); } @Override public int hashCode() { - return Objects.hash(network, networkCapabilities, linkProperties, subscriberId, legacyType); + return Objects.hash(mNetwork, + mNetworkCapabilities, mLinkProperties, mSubscriberId, mLegacyType); } @Override public String toString() { return "NetworkStateSnapshot{" - + "network=" + network - + ", networkCapabilities=" + networkCapabilities - + ", linkProperties=" + linkProperties - + ", subscriberId='" + NetworkIdentityUtils.scrubSubscriberId(subscriberId) + '\'' - + ", legacyType=" + legacyType + + "network=" + mNetwork + + ", networkCapabilities=" + mNetworkCapabilities + + ", linkProperties=" + mLinkProperties + + ", subscriberId='" + NetworkIdentityUtils.scrubSubscriberId(mSubscriberId) + '\'' + + ", legacyType=" + mLegacyType + '}'; } } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 19f5e3cd5d..3c14440c64 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -24,7 +24,6 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; @@ -97,12 +96,12 @@ import android.net.INetworkStatsSession; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; +import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; -import android.net.NetworkSpecifier; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; import android.net.TrafficStats; @@ -1296,9 +1295,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkStateSnapshot snapshot : snapshots) { final int displayTransport = - getDisplayTransport(snapshot.networkCapabilities.getTransportTypes()); + getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes()); final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); - final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.network); + final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.getNetwork()); final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED : getSubTypeForStateSnapshot(snapshot); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot, @@ -1306,7 +1305,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Traffic occurring on the base interface is always counted for // both total usage and UID details. - final String baseIface = snapshot.linkProperties.getInterfaceName(); + final String baseIface = snapshot.getLinkProperties().getInterfaceName(); if (baseIface != null) { findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident); findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident); @@ -1316,7 +1315,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // If IMS is metered, then the IMS network usage has already included VT usage. // VT is considered always metered in framework's layer. If VT is not metered // per carrier's policy, modem will report 0 usage for VT calls. - if (snapshot.networkCapabilities.hasCapability( + if (snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) { // Copy the identify from IMS one but mark it as metered. @@ -1364,7 +1363,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // accounting is explicitly bypassed for traffic from the clat uid. // // TODO: This code might be combined to above code. - for (String iface : snapshot.linkProperties.getAllInterfaceNames()) { + for (String iface : snapshot.getLinkProperties().getAllInterfaceNames()) { // baseIface has been handled, so ignore it. if (TextUtils.equals(baseIface, iface)) continue; if (iface != null) { @@ -1383,11 +1382,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { - if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR"); } - final NetworkSpecifier spec = state.networkCapabilities.getNetworkSpecifier(); + final NetworkSpecifier spec = state.getNetworkCapabilities().getNetworkSpecifier(); if (spec instanceof TelephonyNetworkSpecifier) { return ((TelephonyNetworkSpecifier) spec).getSubscriptionId(); } else { @@ -1402,11 +1401,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * transport types do not actually fill this value. */ private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) { - if (!state.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { + if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return 0; } - return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.subscriberId); + return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.getSubscriberId()); } private static NetworkIdentitySet findOrCreateNetworkIdentitySet( From 2b24a738ee12d1e4e0ead9ed6def97c143966004 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 16 Apr 2021 23:20:23 +0800 Subject: [PATCH 622/881] Add getters to UnderlyingNetworkInfo Address API review feedback, add getters to UnderlyingNetworkInfo instead of exposing fields. Instead of wasting memory by converting this into an array, have migrateTun take a List. In turn, tunAdjustmentInit should also take a List. (cherry picked from ag/14211075) Bug: 183972554 Test: atest android.net.UnderlyingNetworkInfoTest Merged-In: Id59744097208d91298a25ef110ade91a9cf291a1 Change-Id: Id59744097208d91298a25ef110ade91a9cf291a1 --- core/java/android/net/NetworkStats.java | 31 +++++----- .../android/net/UnderlyingNetworkInfo.java | 60 ++++++++++++------- .../server/net/NetworkStatsFactory.java | 4 +- 3 files changed, 58 insertions(+), 37 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index d42beae601..6ccbab7ed8 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -38,6 +38,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Predicate; @@ -1423,11 +1424,11 @@ public final class NetworkStats implements Parcelable { * @hide */ public void migrateTun(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces) { + @NonNull List underlyingIfaces) { // Combined usage by all apps using VPN. final Entry tunIfaceTotal = new Entry(); // Usage by VPN, grouped by its {@code underlyingIfaces}. - final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length]; + final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.size()]; // Usage by VPN, summed across all its {@code underlyingIfaces}. final Entry underlyingIfacesTotal = new Entry(); @@ -1468,7 +1469,7 @@ public final class NetworkStats implements Parcelable { * {@code underlyingIfaces} */ private void tunAdjustmentInit(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull List underlyingIfaces, @NonNull Entry tunIfaceTotal, @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { final Entry recycle = new Entry(); for (int i = 0; i < size; i++) { @@ -1488,8 +1489,8 @@ public final class NetworkStats implements Parcelable { if (recycle.uid == tunUid) { // Add up traffic through tunUid's underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - if (Objects.equals(underlyingIfaces[j], recycle.iface)) { + for (int j = 0; j < underlyingIfaces.size(); j++) { + if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) { perInterfaceTotal[j].add(recycle); underlyingIfacesTotal.add(recycle); break; @@ -1515,12 +1516,12 @@ public final class NetworkStats implements Parcelable { * underlyingIfaces} */ private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface, - @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal, + @NonNull List underlyingIfaces, @NonNull Entry tunIfaceTotal, @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) { // Traffic that should be moved off of each underlying interface for tunUid (see // deductTrafficFromVpnApp below). - final Entry[] moved = new Entry[underlyingIfaces.length]; - for (int i = 0; i < underlyingIfaces.length; i++) { + final Entry[] moved = new Entry[underlyingIfaces.size()]; + for (int i = 0; i < underlyingIfaces.size(); i++) { moved[i] = new Entry(); } @@ -1582,8 +1583,8 @@ public final class NetworkStats implements Parcelable { } // In a second pass, distribute these values across interfaces in the proportion that // each interface represents of the total traffic of the underlying interfaces. - for (int j = 0; j < underlyingIfaces.length; j++) { - tmpEntry.iface = underlyingIfaces[j]; + for (int j = 0; j < underlyingIfaces.size(); j++) { + tmpEntry.iface = underlyingIfaces.get(j); tmpEntry.rxBytes = 0; // Reset 'set' to correct value since it gets updated when adding debug info below. tmpEntry.set = set[i]; @@ -1638,14 +1639,14 @@ public final class NetworkStats implements Parcelable { private void deductTrafficFromVpnApp( int tunUid, - @NonNull String[] underlyingIfaces, + @NonNull List underlyingIfaces, @NonNull Entry[] moved) { - for (int i = 0; i < underlyingIfaces.length; i++) { + for (int i = 0; i < underlyingIfaces.size(); i++) { moved[i].uid = tunUid; // Add debug info moved[i].set = SET_DBG_VPN_OUT; moved[i].tag = TAG_NONE; - moved[i].iface = underlyingIfaces[i]; + moved[i].iface = underlyingIfaces.get(i); moved[i].metered = METERED_ALL; moved[i].roaming = ROAMING_ALL; moved[i].defaultNetwork = DEFAULT_NETWORK_ALL; @@ -1658,7 +1659,7 @@ public final class NetworkStats implements Parcelable { // METERED_NO, which should be the case as it comes directly from the /proc file. // We only blend in the roaming data after applying these adjustments, by checking the // NetworkIdentity of the underlying iface. - final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT, + final int idxVpnBackground = findIndex(underlyingIfaces.get(i), tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnBackground != -1) { // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed @@ -1666,7 +1667,7 @@ public final class NetworkStats implements Parcelable { tunSubtract(idxVpnBackground, this, moved[i]); } - final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND, + final int idxVpnForeground = findIndex(underlyingIfaces.get(i), tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnForeground != -1) { tunSubtract(idxVpnForeground, this, moved[i]); diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java index 7bf9231239..459fdacef8 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.java +++ b/core/java/android/net/UnderlyingNetworkInfo.java @@ -37,36 +37,56 @@ import java.util.Objects; @SystemApi(client = MODULE_LIBRARIES) public final class UnderlyingNetworkInfo implements Parcelable { /** The owner of this network. */ - public final int ownerUid; + private final int mOwnerUid; + /** The interface name of this network. */ @NonNull - public final String iface; + private final String mIface; + /** The names of the interfaces underlying this network. */ @NonNull - public final List underlyingIfaces; + private final List mUnderlyingIfaces; public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface, @NonNull List underlyingIfaces) { Objects.requireNonNull(iface); Objects.requireNonNull(underlyingIfaces); - this.ownerUid = ownerUid; - this.iface = iface; - this.underlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces)); + mOwnerUid = ownerUid; + mIface = iface; + mUnderlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces)); } private UnderlyingNetworkInfo(@NonNull Parcel in) { - this.ownerUid = in.readInt(); - this.iface = in.readString(); - this.underlyingIfaces = new ArrayList<>(); - in.readList(this.underlyingIfaces, null /*classLoader*/); + mOwnerUid = in.readInt(); + mIface = in.readString(); + List underlyingIfaces = new ArrayList<>(); + in.readList(underlyingIfaces, null /*classLoader*/); + mUnderlyingIfaces = Collections.unmodifiableList(underlyingIfaces); + } + + /** Get the owner of this network. */ + public int getOwnerUid() { + return mOwnerUid; + } + + /** Get the interface name of this network. */ + @NonNull + public String getIface() { + return mIface; + } + + /** Get the names of the interfaces underlying this network. */ + @NonNull + public List getUnderlyingIfaces() { + return mUnderlyingIfaces; } @Override public String toString() { return "UnderlyingNetworkInfo{" - + "ownerUid=" + ownerUid - + ", iface='" + iface + '\'' - + ", underlyingIfaces='" + underlyingIfaces.toString() + '\'' + + "ownerUid=" + mOwnerUid + + ", iface='" + mIface + '\'' + + ", underlyingIfaces='" + mUnderlyingIfaces.toString() + '\'' + '}'; } @@ -77,9 +97,9 @@ public final class UnderlyingNetworkInfo implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(ownerUid); - dest.writeString(iface); - dest.writeList(underlyingIfaces); + dest.writeInt(mOwnerUid); + dest.writeString(mIface); + dest.writeList(mUnderlyingIfaces); } @NonNull @@ -103,13 +123,13 @@ public final class UnderlyingNetworkInfo implements Parcelable { if (this == o) return true; if (!(o instanceof UnderlyingNetworkInfo)) return false; final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o; - return ownerUid == that.ownerUid - && Objects.equals(iface, that.iface) - && Objects.equals(underlyingIfaces, that.underlyingIfaces); + return mOwnerUid == that.getOwnerUid() + && Objects.equals(mIface, that.getIface()) + && Objects.equals(mUnderlyingIfaces, that.getUnderlyingIfaces()); } @Override public int hashCode() { - return Objects.hash(ownerUid, iface, underlyingIfaces); + return Objects.hash(mOwnerUid, mIface, mUnderlyingIfaces); } } diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index d042b882fe..e7c0a50163 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -382,8 +382,8 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (UnderlyingNetworkInfo info : vpnArray) { - delta.migrateTun(info.ownerUid, info.iface, - info.underlyingIfaces.toArray(new String[0])); + delta.migrateTun(info.getOwnerUid(), info.getIface(), + info.getUnderlyingIfaces()); // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } From e94d9bf54c6c1b0c54c24ed36686bc28df043e70 Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 30 Mar 2021 10:55:37 +0800 Subject: [PATCH 623/881] Enforce ACCESS_NETWORK_STATE to getAvailableInterfaces() getAvailableInterfaces() will return available ethernet interfaces which are the information about networks. So it should enforce ACCESS_NETWORK_STATE permission check to ensure the applications are allowed to access the information. Bug: 174573778 Test: TetheringTests Test: CtsTetheringTest Change-Id: I7aaa5225d56f2feecc51ba263489ed0ce02fd651 --- .../src/com/android/server/ethernet/EthernetServiceImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 3fc6aab758..c06f61e446 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -87,6 +87,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public String[] getAvailableInterfaces() throws RemoteException { + enforceAccessPermission(); + return mTracker.getInterfaces(checkUseRestrictedNetworksPermission()); } From 4ddc7c782f09a5c41c8037407749dd411a35930f Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 28 Apr 2021 17:21:21 +0800 Subject: [PATCH 624/881] Rename *Iface* APIs to *Interface* Address API review feedback, other APIs have been refering to these as "interface" instead of "iface" so migrate the APIs named *Iface* to *Interface*. Bug: 183972554 Test: atest android.net.UnderlyingNetworkInfoTest Change-Id: I38b476e762fb57fa88c4a789092d0af6f5330d80 --- core/java/android/net/UnderlyingNetworkInfo.java | 8 ++++---- .../java/com/android/server/net/NetworkStatsFactory.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java index 459fdacef8..33f9375c03 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.java +++ b/core/java/android/net/UnderlyingNetworkInfo.java @@ -71,13 +71,13 @@ public final class UnderlyingNetworkInfo implements Parcelable { /** Get the interface name of this network. */ @NonNull - public String getIface() { + public String getInterface() { return mIface; } /** Get the names of the interfaces underlying this network. */ @NonNull - public List getUnderlyingIfaces() { + public List getUnderlyingInterfaces() { return mUnderlyingIfaces; } @@ -124,8 +124,8 @@ public final class UnderlyingNetworkInfo implements Parcelable { if (!(o instanceof UnderlyingNetworkInfo)) return false; final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o; return mOwnerUid == that.getOwnerUid() - && Objects.equals(mIface, that.getIface()) - && Objects.equals(mUnderlyingIfaces, that.getUnderlyingIfaces()); + && Objects.equals(mIface, that.getInterface()) + && Objects.equals(mUnderlyingIfaces, that.getUnderlyingInterfaces()); } @Override diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index e7c0a50163..431b00914f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -382,8 +382,8 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (UnderlyingNetworkInfo info : vpnArray) { - delta.migrateTun(info.getOwnerUid(), info.getIface(), - info.getUnderlyingIfaces()); + delta.migrateTun(info.getOwnerUid(), info.getInterface(), + info.getUnderlyingInterfaces()); // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } From 126eca96fafc7aafe08a3836b46818dfe6bf7807 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Tue, 30 Mar 2021 16:54:45 +0800 Subject: [PATCH 625/881] Add transport type in capabilities filter of EthernetNetworkFacotry Bug: 167544279 Test: atest EthernetServiceTests Change-Id: Ie64e3cff0ace413f14682736de7a1b65fa93e705 Merged-In: Ie64e3cff0ace413f14682736de7a1b65fa93e705 (Cherry-picked from ag/14031548) --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 1 + 1 file changed, 1 insertion(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 75e77b9596..f9e8b00562 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -169,6 +169,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private void updateCapabilityFilter() { NetworkCapabilities capabilitiesFilter = new NetworkCapabilities.Builder() .clearAll() + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build(); for (NetworkInterfaceState iface: mTrackingInterfaces.values()) { From 0492286d6fbe0c5281286c08315e5220b682aa41 Mon Sep 17 00:00:00 2001 From: Chris Weir Date: Fri, 12 Mar 2021 12:51:00 -0800 Subject: [PATCH 626/881] Print human-readable OEM managed states For NetworkTemplate and NetworkIdentity, print human-readable representations of the OEM managed state in the classes' respective toString() functions. Bug: 180557699 Test: Manual - run atest NetworkTemplateTest NetworkIdentityTest and verify that the logcat output shows the String representation of the OEM managed state correctly. Change-Id: Ia180b911f91f41937ac713e6b3691d82f682e146 --- core/java/android/net/NetworkIdentity.java | 32 ++++++++++++++++++++-- core/java/android/net/NetworkTemplate.java | 15 +++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index b037261f0b..13408bf2cd 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -26,8 +26,10 @@ import android.service.NetworkIdentityProto; import android.telephony.Annotation.NetworkType; import android.util.proto.ProtoOutputStream; +import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.NetworkIdentityUtils; +import java.util.ArrayList; import java.util.Objects; /** @@ -121,11 +123,37 @@ public class NetworkIdentity implements Comparable { } builder.append(", metered=").append(mMetered); builder.append(", defaultNetwork=").append(mDefaultNetwork); - // TODO(180557699): Print a human readable string for OEM managed state. - builder.append(", oemManaged=").append(mOemManaged); + builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged)); return builder.append("}").toString(); } + /** + * Get the human readable representation of a bitfield representing the OEM managed state of a + * network. + */ + static String getOemManagedNames(int oemManaged) { + if (oemManaged == OEM_NONE) { + return "OEM_NONE"; + } + final int[] bitPositions = NetworkCapabilitiesUtils.unpackBits(oemManaged); + final ArrayList oemManagedNames = new ArrayList(); + for (int position : bitPositions) { + oemManagedNames.add(nameOfOemManaged(1 << position)); + } + return String.join(",", oemManagedNames); + } + + private static String nameOfOemManaged(int oemManagedBit) { + switch (oemManagedBit) { + case OEM_PAID: + return "OEM_PAID"; + case OEM_PRIVATE: + return "OEM_PRIVATE"; + default: + return "Invalid(" + oemManagedBit + ")"; + } + } + public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index c83dd99c2a..755e8fda4f 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -344,7 +344,7 @@ public class NetworkTemplate implements Parcelable { builder.append(", subType=").append(mSubType); } if (mOemManaged != OEM_MANAGED_ALL) { - builder.append(", oemManaged=").append(mOemManaged); + builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged)); } return builder.toString(); } @@ -640,6 +640,19 @@ public class NetworkTemplate implements Parcelable { } } + private static String getOemManagedNames(int oemManaged) { + switch (oemManaged) { + case OEM_MANAGED_ALL: + return "OEM_MANAGED_ALL"; + case OEM_MANAGED_NO: + return "OEM_MANAGED_NO"; + case OEM_MANAGED_YES: + return "OEM_MANAGED_YES"; + default: + return NetworkIdentity.getOemManagedNames(oemManaged); + } + } + /** * Examine the given template and normalize if it refers to a "merged" * mobile subscriber. We pick the "lowest" merged subscriber as the primary From 1684f790d94cef14603dfa6f71ee87872eb51498 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 15 Apr 2021 11:59:16 -0700 Subject: [PATCH 627/881] Add internal support for IPsec forward policies This change adds support for IPsec forward policies, which are necessary for packets to be allowed to be forwarded to another interface, as is the case with tethering. This is necessary and useful only within the system server, and as such is not exposed as a public API. This change is safe, since the addition of a FWD policy on IPsec tunnel interfaces will by default block forwarded traffic (as would be the case without this patch). In the event that the (system) owner of the tunnel requires support for forwarded packets (eg tethering), this patch allows application of transforms in the FWD direction as well. This will be used to ensure that the VCN can be used as the underlying network for the purposes of tethering. Bug: 185495453 Test: atest IpSecServiceTest Test: atest IpSecServiceParameterizedTest Test: manual testing with tethering over VCN Change-Id: I74ecea71f1954029f6fbdbe34598c82e0aac386b --- core/java/android/net/IpSecManager.java | 10 ++++++++ .../java/com/android/server/IpSecService.java | 23 +++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 98acd98cc4..01d1aa533a 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -78,6 +78,16 @@ public final class IpSecManager { */ public static final int DIRECTION_OUT = 1; + /** + * Used when applying a transform to direct traffic through an {@link IpSecTransform} for + * forwarding between interfaces. + * + *

See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}. + * + * @hide + */ + public static final int DIRECTION_FWD = 2; + /** * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. * diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index 794cb9301d..d574e74d39 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -49,6 +49,7 @@ import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; import android.os.ParcelFileDescriptor; +import android.os.Process; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.system.ErrnoException; @@ -65,6 +66,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import com.android.net.module.util.NetdUtils; +import com.android.net.module.util.PermissionUtils; import libcore.io.IoUtils; @@ -466,8 +468,7 @@ public class IpSecService extends IIpSecService.Stub { /** Safety method; guards against access of other user's UserRecords */ private void checkCallerUid(int uid) { - if (uid != Binder.getCallingUid() - && android.os.Process.SYSTEM_UID != Binder.getCallingUid()) { + if (uid != Binder.getCallingUid() && Process.SYSTEM_UID != Binder.getCallingUid()) { throw new SecurityException("Attempted access of unowned resources"); } } @@ -1105,11 +1106,15 @@ public class IpSecService extends IIpSecService.Stub { * Checks the user-provided direction field and throws an IllegalArgumentException if it is not * DIRECTION_IN or DIRECTION_OUT */ - private static void checkDirection(int direction) { + private void checkDirection(int direction) { switch (direction) { case IpSecManager.DIRECTION_OUT: case IpSecManager.DIRECTION_IN: return; + case IpSecManager.DIRECTION_FWD: + // Only NETWORK_STACK or PERMISSION_NETWORK_STACK allowed to use forward policies + PermissionUtils.enforceNetworkStackPermission(mContext); + return; } throw new IllegalArgumentException("Invalid Direction: " + direction); } @@ -1353,6 +1358,16 @@ public class IpSecService extends IIpSecService.Stub { ikey, 0xffffffff, resourceId); + netd.ipSecAddSecurityPolicy( + callerUid, + selAddrFamily, + IpSecManager.DIRECTION_FWD, + remoteAddr, + localAddr, + 0, + ikey, + 0xffffffff, + resourceId); } userRecord.mTunnelInterfaceRecords.put( @@ -1820,7 +1835,7 @@ public class IpSecService extends IIpSecService.Stub { int mark = (direction == IpSecManager.DIRECTION_OUT) ? tunnelInterfaceInfo.getOkey() - : tunnelInterfaceInfo.getIkey(); + : tunnelInterfaceInfo.getIkey(); // Ikey also used for FWD policies try { // Default to using the invalid SPI of 0 for inbound SAs. This allows policies to skip From 3f1b6f2aaaa9a18b8ebe3b320e1f94b90a0c51ac Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 10 May 2021 23:09:44 +0800 Subject: [PATCH 628/881] Add return type javadoc to NetworkStateSnapshot#getLegacyType Add javadoc to document the return type is the legacy network type in getLegacyType. Bug: 183972826 Test: only update javadoc Change-Id: I7757253af5955f7d489d6349c090dcba146cfd7f --- core/java/android/net/NetworkStateSnapshot.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkStateSnapshot.java b/core/java/android/net/NetworkStateSnapshot.java index 9df861a6ff..3915634392 100644 --- a/core/java/android/net/NetworkStateSnapshot.java +++ b/core/java/android/net/NetworkStateSnapshot.java @@ -104,7 +104,10 @@ public final class NetworkStateSnapshot implements Parcelable { return mSubscriberId; } - /** Get the legacy type of the network associated with this snapshot. */ + /** + * Get the legacy type of the network associated with this snapshot. + * @return the legacy network type. See {@code ConnectivityManager#TYPE_*}. + */ public int getLegacyType() { return mLegacyType; } From 0c8ff5c720941fef2b861771d278e01bf0e932b9 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 10 May 2021 18:26:02 -0700 Subject: [PATCH 629/881] Add clarifying comments on for IPsec forward policies This change adds clarifying comments for the usage of the forward policies in IPsec, and corrects a comment to properly specify the permissions allowed. Bug: 185495453 Test: Comment-only changes Change-Id: I6d36522c344c41b0ebd90d46b216d115b678dd31 --- .../core/java/com/android/server/IpSecService.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index d574e74d39..d6ee95131e 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -1112,7 +1112,7 @@ public class IpSecService extends IIpSecService.Stub { case IpSecManager.DIRECTION_IN: return; case IpSecManager.DIRECTION_FWD: - // Only NETWORK_STACK or PERMISSION_NETWORK_STACK allowed to use forward policies + // Only NETWORK_STACK or MAINLINE_NETWORK_STACK allowed to use forward policies PermissionUtils.enforceNetworkStackPermission(mContext); return; } @@ -1358,6 +1358,16 @@ public class IpSecService extends IIpSecService.Stub { ikey, 0xffffffff, resourceId); + + // Add a forwarding policy on the tunnel interface. In order to support forwarding + // the IpSecTunnelInterface must have a forwarding policy matching the incoming SA. + // + // Unless a IpSecTransform is also applied against this interface in DIRECTION_FWD, + // forwarding will be blocked by default (as would be the case if this policy was + // absent). + // + // This is necessary only on the tunnel interface, and not any the interface to + // which traffic will be forwarded to. netd.ipSecAddSecurityPolicy( callerUid, selAddrFamily, From 249507940f5cd49b8601b7faa3f859686eb8fc85 Mon Sep 17 00:00:00 2001 From: lesl Date: Fri, 7 May 2021 18:15:17 +0800 Subject: [PATCH 630/881] Add metered filter for API: buildTemplateCarrier This CL modifies NetworkTemplate#buildTemplateCarrier to force on metered carrier network and rename to buildTemplateCarrierMetered. This method was introduced recently and has no callers. This method will be used in Settings and NetworkPolicyManagerService to display and manage data usage on carrier metered networks. Settings/NetworkPolicyManagerService will use it instead of the existing method buildTemplateMobileAll method, which only matches metered networks. That code will change from matching metered mobile networks to matching metered carrier networks. Note: The carrier metered network includes metered mobile network and metered "merged carrier wifi network" that is a specific cerrier wifi network which provides the same user experience as mobile. Bug: 176396812 Test: atest -c NetworkTemplateTest Change-Id: I7196d62bb60844458a6c4b1d94e2baccb71e15cd --- core/java/android/net/NetworkTemplate.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index d3c8957494..fd446cdf5c 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -274,11 +274,14 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match all carrier networks with the given IMSI. + * Template to match all metered carrier networks with the given IMSI. */ - public static NetworkTemplate buildTemplateCarrier(@NonNull String subscriberId) { + public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { Objects.requireNonNull(subscriberId); - return new NetworkTemplate(MATCH_CARRIER, subscriberId, null); + return new NetworkTemplate(MATCH_CARRIER, subscriberId, + new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL, + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_EXACT); } private final int mMatchRule; From fb5fbaba3304b6e33c34dfeb12df10fdc37b8003 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 28 Apr 2021 17:21:21 +0800 Subject: [PATCH 631/881] Rename *Iface* APIs to *Interface* Address API review feedback, other APIs have been refering to these as "interface" instead of "iface" so migrate the APIs named *Iface* to *Interface*. (cherry-picked from ag/14326779) Bug: 183972554 Test: atest android.net.UnderlyingNetworkInfoTest Merged-In: I38b476e762fb57fa88c4a789092d0af6f5330d80 Change-Id: I38b476e762fb57fa88c4a789092d0af6f5330d80 --- core/java/android/net/UnderlyingNetworkInfo.java | 8 ++++---- .../java/com/android/server/net/NetworkStatsFactory.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java index 459fdacef8..33f9375c03 100644 --- a/core/java/android/net/UnderlyingNetworkInfo.java +++ b/core/java/android/net/UnderlyingNetworkInfo.java @@ -71,13 +71,13 @@ public final class UnderlyingNetworkInfo implements Parcelable { /** Get the interface name of this network. */ @NonNull - public String getIface() { + public String getInterface() { return mIface; } /** Get the names of the interfaces underlying this network. */ @NonNull - public List getUnderlyingIfaces() { + public List getUnderlyingInterfaces() { return mUnderlyingIfaces; } @@ -124,8 +124,8 @@ public final class UnderlyingNetworkInfo implements Parcelable { if (!(o instanceof UnderlyingNetworkInfo)) return false; final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o; return mOwnerUid == that.getOwnerUid() - && Objects.equals(mIface, that.getIface()) - && Objects.equals(mUnderlyingIfaces, that.getUnderlyingIfaces()); + && Objects.equals(mIface, that.getInterface()) + && Objects.equals(mUnderlyingIfaces, that.getUnderlyingInterfaces()); } @Override diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index e7c0a50163..431b00914f 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -382,8 +382,8 @@ public class NetworkStatsFactory { // Migrate data usage over a VPN to the TUN network. for (UnderlyingNetworkInfo info : vpnArray) { - delta.migrateTun(info.getOwnerUid(), info.getIface(), - info.getUnderlyingIfaces()); + delta.migrateTun(info.getOwnerUid(), info.getInterface(), + info.getUnderlyingInterfaces()); // Filter out debug entries as that may lead to over counting. delta.filterDebugEntries(); } From c01a9cf396db61c920d6364e970bf937fb175b11 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 13 May 2021 10:21:59 +0800 Subject: [PATCH 632/881] Replace clearAll with withoutDefaultCapabilities in NC#Builder Update the naming and usgae according to API review feedback. Bug: 184735772 Test: atest EthernetTrackerTest Change-Id: Ie8dc0bcdf46ceebda5d6062231b48c1f63b250f6 --- .../android/server/ethernet/EthernetNetworkFactory.java | 4 ++-- .../src/com/android/server/ethernet/EthernetTracker.java | 7 +++---- .../com/android/server/ethernet/EthernetTrackerTest.java | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index f9e8b00562..aa80e4de2d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -167,8 +167,8 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void updateCapabilityFilter() { - NetworkCapabilities capabilitiesFilter = new NetworkCapabilities.Builder() - .clearAll() + NetworkCapabilities capabilitiesFilter = + NetworkCapabilities.Builder.withoutDefaultCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build(); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index a190240edb..b2b60fcb83 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -507,10 +507,9 @@ final class EthernetTracker { boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities, @Nullable String overrideTransport) { - final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); - if (clearDefaultCapabilities) { - builder.clearAll(); // Remove default capabilities and transports - } + final NetworkCapabilities.Builder builder = clearDefaultCapabilities + ? NetworkCapabilities.Builder.withoutDefaultCapabilities() + : new NetworkCapabilities.Builder(); // Determine the transport type. If someone has tried to define an override transport then // attempt to add it. Since we can only have one override, all errors with it will diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 22b1b6939e..ee9f349a28 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -107,7 +107,7 @@ public class EthernetTrackerTest { private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) { final NetworkCapabilities.Builder builder = - clearAll ? new NetworkCapabilities.Builder().clearAll() + clearAll ? NetworkCapabilities.Builder.withoutDefaultCapabilities() : new NetworkCapabilities.Builder(); return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) From ca8079ec689021c0f1a2d2f06603bcf643b2381f Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 13 May 2021 10:21:59 +0800 Subject: [PATCH 633/881] Replace clearAll with withoutDefaultCapabilities in NC#Builder Update the naming and usgae according to API review feedback. Bug: 184735772 Test: atest EthernetTrackerTest Change-Id: Ie8dc0bcdf46ceebda5d6062231b48c1f63b250f6 Merged-In: Ie8dc0bcdf46ceebda5d6062231b48c1f63b250f6 --- .../android/server/ethernet/EthernetNetworkFactory.java | 4 ++-- .../src/com/android/server/ethernet/EthernetTracker.java | 7 +++---- .../com/android/server/ethernet/EthernetTrackerTest.java | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index f9e8b00562..aa80e4de2d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -167,8 +167,8 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void updateCapabilityFilter() { - NetworkCapabilities capabilitiesFilter = new NetworkCapabilities.Builder() - .clearAll() + NetworkCapabilities capabilitiesFilter = + NetworkCapabilities.Builder.withoutDefaultCapabilities() .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .build(); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index a190240edb..b2b60fcb83 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -507,10 +507,9 @@ final class EthernetTracker { boolean clearDefaultCapabilities, @Nullable String commaSeparatedCapabilities, @Nullable String overrideTransport) { - final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(); - if (clearDefaultCapabilities) { - builder.clearAll(); // Remove default capabilities and transports - } + final NetworkCapabilities.Builder builder = clearDefaultCapabilities + ? NetworkCapabilities.Builder.withoutDefaultCapabilities() + : new NetworkCapabilities.Builder(); // Determine the transport type. If someone has tried to define an override transport then // attempt to add it. Since we can only have one override, all errors with it will diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 22b1b6939e..ee9f349a28 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -107,7 +107,7 @@ public class EthernetTrackerTest { private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) { final NetworkCapabilities.Builder builder = - clearAll ? new NetworkCapabilities.Builder().clearAll() + clearAll ? NetworkCapabilities.Builder.withoutDefaultCapabilities() : new NetworkCapabilities.Builder(); return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) From b679f00398c439ef639d47ef27acab8a0d04a0f6 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 5 Mar 2021 10:35:11 +0800 Subject: [PATCH 634/881] [FUI27] Fix internal naming of notifyNetworkStatus Test: TH Bug: 174123988 Change-Id: I970ee365ca221956ee85788005d331374b5fa71a --- .../app/usage/NetworkStatsManager.java | 15 ++++---- .../android/net/INetworkStatsService.aidl | 4 +-- .../server/net/NetworkStatsService.java | 36 ++++++++++--------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 9f1132b605..6cb4b5e9b3 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -655,14 +655,14 @@ public class NetworkStatsManager { } /** - * Notify {@code NetworkStatsService} about network status changed. + * Notify {@code NetworkStatsService} about network status changed. * - * Notifies NetworkStatsService of network state changes for data usage accounting purposes. + * Notifies NetworkStatsService of network state changes for data usage accounting purposes. * - * To avoid races that attribute data usage to wrong network, such as new network with - * the same interface after SIM hot-swap, this function will not return until - * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from - * all data sources. + * To avoid races that attribute data usage to wrong network, such as new network with + * the same interface after SIM hot-swap, this function will not return until + * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from + * all data sources. * * @param defaultNetworks the list of all networks that could be used by network traffic that * does not explicitly select a network. @@ -689,8 +689,7 @@ public class NetworkStatsManager { Objects.requireNonNull(defaultNetworks); Objects.requireNonNull(networkStateSnapshots); Objects.requireNonNull(underlyingNetworkInfos); - // TODO: Change internal namings after the name is decided. - mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]), + mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]), networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface, underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0])); } catch (RemoteException e) { diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index dc3b88a7c3..12937b5cb2 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -65,8 +65,8 @@ interface INetworkStatsService { /** Increment data layer count of operations performed for UID and tag. */ void incrementOperationCount(int uid, int tag, int operationCount); - /** Force update of ifaces. */ - void forceUpdateIfaces( + /** Notify {@code NetworkStatsService} about network status changed. */ + void notifyNetworkStatus( in Network[] defaultNetworks, in NetworkStateSnapshot[] snapshots, in String activeIface, diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3c14440c64..4ee867b7d0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -181,7 +181,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int MSG_PERFORM_POLL = 1; // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; - private static final int MSG_UPDATE_IFACES = 3; + private static final int MSG_NOTIFY_NETWORK_STATUS = 3; // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent // deadlock. private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; @@ -379,11 +379,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performPoll(FLAG_PERSIST_ALL); break; } - case MSG_UPDATE_IFACES: { + case MSG_NOTIFY_NETWORK_STATUS: { // If no cached states, ignore. if (mLastNetworkStateSnapshots == null) break; // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing. - updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); + handleNotifyNetworkStatus( + mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); break; } case MSG_PERFORM_POLL_REGISTER_ALERT: { @@ -474,7 +475,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull Looper looper, @NonNull Executor executor, @NonNull NetworkStatsService service) { // TODO: Update RatType passively in NSS, instead of querying into the monitor - // when forceUpdateIface. + // when notifyNetworkStatus. return new NetworkStatsSubscriptionsMonitor(context, looper, executor, (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged()); } @@ -971,16 +972,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public void forceUpdateIfaces( - Network[] defaultNetworks, - NetworkStateSnapshot[] networkStates, - String activeIface, - UnderlyingNetworkInfo[] underlyingNetworkInfos) { + /** + * Notify {@code NetworkStatsService} about network status changed. + */ + public void notifyNetworkStatus( + @NonNull Network[] defaultNetworks, + @NonNull NetworkStateSnapshot[] networkStates, + @Nullable String activeIface, + @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) { checkNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks, networkStates, activeIface); + handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1244,12 +1248,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting public void handleOnCollapsedRatTypeChanged() { // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS); mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); + mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay()); } - private void updateIfaces( + private void handleNotifyNetworkStatus( Network[] defaultNetworks, NetworkStateSnapshot[] snapshots, String activeIface) { @@ -1257,7 +1261,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mWakeLock.acquire(); try { mActiveIface = activeIface; - updateIfacesLocked(defaultNetworks, snapshots); + handleNotifyNetworkStatusLocked(defaultNetworks, snapshots); } finally { mWakeLock.release(); } @@ -1270,10 +1274,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(@NonNull Network[] defaultNetworks, + private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks, @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; - if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); + if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()"); // take one last stats snapshot before updating iface mapping. this // isn't perfect, since the kernel may already be counting traffic from From dfc72377430e758cda679acb2b15ff1ed37eda51 Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 25 Feb 2021 23:15:07 +0800 Subject: [PATCH 635/881] Support to query TYPE_WIFI usage with subscriberId Previous the API ignores subscriberId when network type is WIFI. Allow caller to call querySummaryXXXX with TYPE: WIFI + subscriberId: IMSI to get carrier merged wifi usage which matches the wifi network with the given IMSI. Bug: 176396812 Test: atest -c NetworkStatsServiceTest Change-Id: Ia033521a24e2bb56182d74a41bb2b39710571782 --- core/java/android/app/usage/NetworkStatsManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 6cb4b5e9b3..fe99f8532a 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -644,7 +644,10 @@ public class NetworkStatsManager { : NetworkTemplate.buildTemplateMobileAll(subscriberId); break; case ConnectivityManager.TYPE_WIFI: - template = NetworkTemplate.buildTemplateWifiWildcard(); + template = subscriberId == null + ? NetworkTemplate.buildTemplateWifiWildcard() + : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, + subscriberId); break; default: throw new IllegalArgumentException("Cannot create template for network type " From 5f8c0b0b6b69d4f267f8d8585fd594edf3fb5a3a Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 5 Mar 2021 10:35:11 +0800 Subject: [PATCH 636/881] [FUI27] Fix internal naming of notifyNetworkStatus Test: TH Bug: 174123988 Merged-In: I970ee365ca221956ee85788005d331374b5fa71a Change-Id: I970ee365ca221956ee85788005d331374b5fa71a (cherry-picked from aosp/1620539) --- .../app/usage/NetworkStatsManager.java | 15 ++++---- .../android/net/INetworkStatsService.aidl | 4 +-- .../server/net/NetworkStatsService.java | 36 ++++++++++--------- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 9f1132b605..6cb4b5e9b3 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -655,14 +655,14 @@ public class NetworkStatsManager { } /** - * Notify {@code NetworkStatsService} about network status changed. + * Notify {@code NetworkStatsService} about network status changed. * - * Notifies NetworkStatsService of network state changes for data usage accounting purposes. + * Notifies NetworkStatsService of network state changes for data usage accounting purposes. * - * To avoid races that attribute data usage to wrong network, such as new network with - * the same interface after SIM hot-swap, this function will not return until - * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from - * all data sources. + * To avoid races that attribute data usage to wrong network, such as new network with + * the same interface after SIM hot-swap, this function will not return until + * {@code NetworkStatsService} finishes its work of retrieving traffic statistics from + * all data sources. * * @param defaultNetworks the list of all networks that could be used by network traffic that * does not explicitly select a network. @@ -689,8 +689,7 @@ public class NetworkStatsManager { Objects.requireNonNull(defaultNetworks); Objects.requireNonNull(networkStateSnapshots); Objects.requireNonNull(underlyingNetworkInfos); - // TODO: Change internal namings after the name is decided. - mService.forceUpdateIfaces(defaultNetworks.toArray(new Network[0]), + mService.notifyNetworkStatus(defaultNetworks.toArray(new Network[0]), networkStateSnapshots.toArray(new NetworkStateSnapshot[0]), activeIface, underlyingNetworkInfos.toArray(new UnderlyingNetworkInfo[0])); } catch (RemoteException e) { diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index dc3b88a7c3..12937b5cb2 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -65,8 +65,8 @@ interface INetworkStatsService { /** Increment data layer count of operations performed for UID and tag. */ void incrementOperationCount(int uid, int tag, int operationCount); - /** Force update of ifaces. */ - void forceUpdateIfaces( + /** Notify {@code NetworkStatsService} about network status changed. */ + void notifyNetworkStatus( in Network[] defaultNetworks, in NetworkStateSnapshot[] snapshots, in String activeIface, diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 3c14440c64..4ee867b7d0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -181,7 +181,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int MSG_PERFORM_POLL = 1; // Perform polling, persist network, and register the global alert again. private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; - private static final int MSG_UPDATE_IFACES = 3; + private static final int MSG_NOTIFY_NETWORK_STATUS = 3; // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent // deadlock. private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; @@ -379,11 +379,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { performPoll(FLAG_PERSIST_ALL); break; } - case MSG_UPDATE_IFACES: { + case MSG_NOTIFY_NETWORK_STATUS: { // If no cached states, ignore. if (mLastNetworkStateSnapshots == null) break; // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing. - updateIfaces(mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); + handleNotifyNetworkStatus( + mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); break; } case MSG_PERFORM_POLL_REGISTER_ALERT: { @@ -474,7 +475,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull Looper looper, @NonNull Executor executor, @NonNull NetworkStatsService service) { // TODO: Update RatType passively in NSS, instead of querying into the monitor - // when forceUpdateIface. + // when notifyNetworkStatus. return new NetworkStatsSubscriptionsMonitor(context, looper, executor, (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged()); } @@ -971,16 +972,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public void forceUpdateIfaces( - Network[] defaultNetworks, - NetworkStateSnapshot[] networkStates, - String activeIface, - UnderlyingNetworkInfo[] underlyingNetworkInfos) { + /** + * Notify {@code NetworkStatsService} about network status changed. + */ + public void notifyNetworkStatus( + @NonNull Network[] defaultNetworks, + @NonNull NetworkStateSnapshot[] networkStates, + @Nullable String activeIface, + @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) { checkNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(defaultNetworks, networkStates, activeIface); + handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface); } finally { Binder.restoreCallingIdentity(token); } @@ -1244,12 +1248,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @VisibleForTesting public void handleOnCollapsedRatTypeChanged() { // Protect service from frequently updating. Remove pending messages if any. - mHandler.removeMessages(MSG_UPDATE_IFACES); + mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS); mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_UPDATE_IFACES), mSettings.getPollDelay()); + mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay()); } - private void updateIfaces( + private void handleNotifyNetworkStatus( Network[] defaultNetworks, NetworkStateSnapshot[] snapshots, String activeIface) { @@ -1257,7 +1261,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mWakeLock.acquire(); try { mActiveIface = activeIface; - updateIfacesLocked(defaultNetworks, snapshots); + handleNotifyNetworkStatusLocked(defaultNetworks, snapshots); } finally { mWakeLock.release(); } @@ -1270,10 +1274,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * they are combined under a single {@link NetworkIdentitySet}. */ @GuardedBy("mStatsLock") - private void updateIfacesLocked(@NonNull Network[] defaultNetworks, + private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks, @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; - if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); + if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()"); // take one last stats snapshot before updating iface mapping. this // isn't perfect, since the kernel may already be counting traffic from From ee39c8deeccb845ea2b2a160c817071870308e87 Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 25 Feb 2021 23:15:07 +0800 Subject: [PATCH 637/881] Support to query TYPE_WIFI usage with subscriberId Previous the API ignores subscriberId when network type is WIFI. Allow caller to call querySummaryXXXX with TYPE: WIFI + subscriberId: IMSI to get carrier merged wifi usage which matches the wifi network with the given IMSI. Bug: 176396812 Test: atest -c NetworkStatsServiceTest Change-Id: Ia033521a24e2bb56182d74a41bb2b39710571782 Merged-In: Ia033521a24e2bb56182d74a41bb2b39710571782 --- core/java/android/app/usage/NetworkStatsManager.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 9f1132b605..65b9facc86 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -644,7 +644,10 @@ public class NetworkStatsManager { : NetworkTemplate.buildTemplateMobileAll(subscriberId); break; case ConnectivityManager.TYPE_WIFI: - template = NetworkTemplate.buildTemplateWifiWildcard(); + template = subscriberId == null + ? NetworkTemplate.buildTemplateWifiWildcard() + : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, + subscriberId); break; default: throw new IllegalArgumentException("Cannot create template for network type " From 067a1d2448ad21a53799741c6a6c8df841ead11a Mon Sep 17 00:00:00 2001 From: lesl Date: Fri, 7 May 2021 18:15:17 +0800 Subject: [PATCH 638/881] Add metered filter for API: buildTemplateCarrier This CL modifies NetworkTemplate#buildTemplateCarrier to force on metered carrier network and rename to buildTemplateCarrierMetered. This method was introduced recently and has no callers. This method will be used in Settings and NetworkPolicyManagerService to display and manage data usage on carrier metered networks. Settings/NetworkPolicyManagerService will use it instead of the existing method buildTemplateMobileAll method, which only matches metered networks. That code will change from matching metered mobile networks to matching metered carrier networks. Note: The carrier metered network includes metered mobile network and metered "merged carrier wifi network" that is a specific cerrier wifi network which provides the same user experience as mobile. Bug: 176396812 Test: atest -c NetworkTemplateTest Change-Id: I7196d62bb60844458a6c4b1d94e2baccb71e15cd Merged-In: I7196d62bb60844458a6c4b1d94e2baccb71e15cd --- core/java/android/net/NetworkTemplate.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index d3c8957494..fd446cdf5c 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -274,11 +274,14 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match all carrier networks with the given IMSI. + * Template to match all metered carrier networks with the given IMSI. */ - public static NetworkTemplate buildTemplateCarrier(@NonNull String subscriberId) { + public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { Objects.requireNonNull(subscriberId); - return new NetworkTemplate(MATCH_CARRIER, subscriberId, null); + return new NetworkTemplate(MATCH_CARRIER, subscriberId, + new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL, + DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, + SUBSCRIBER_ID_MATCH_RULE_EXACT); } private final int mMatchRule; From 41e74f4334d5191b3e0c69ce1a710da40b356870 Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 28 Jan 2021 15:58:23 +0800 Subject: [PATCH 639/881] carrier data usage: Use carrier template as default policy The carrier network means any network which linked with sepcific subscriberId (for instances: merged Wifi or mobile). Update default policy to use carrier network template to replace mobile template. No impact for current AOSP user because no any wifi network is merged wifi. (Because the merged wifi network requires to support from the wifi module). Also this change convert all of the old policies which template is TYEP_MOBILE to TYPE_CARRIER to match the default policy. Bug: 176396812 Test: atest -c NetworkPolicyManagerServiceTest Test: atest -c CtsHostsideNetworkTests Test: Manual Test with test code (Force wifi to merged wifi). The data will limit when using merged wifi. And mobile policy also work normally. Change-Id: I33c10f7549e713c52ce9afd5b8c4cce2abbda616 --- core/java/android/net/NetworkTemplate.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 352f2e99aa..68917a8288 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -514,6 +514,10 @@ public class NetworkTemplate implements Parcelable { return mSubscriberIdMatchRule; } + public int getMeteredness() { + return mMetered; + } + /** * Test if given {@link NetworkIdentity} matches this template. */ From 4ccd2e2d87fd3029c434c04bafc328cb0fad1ac8 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Thu, 20 May 2021 21:47:50 +0000 Subject: [PATCH 640/881] Improve documentation of IpSecTunnelInterface#setUnderlyingNetwork Clarify the consequence of adding IpSecTunnelInterface to the underlying network. Bug: 169855650 Test: builds Change-Id: I2e3c4fe735b3374b2ff6d23850970e36c0aafda5 Merged-In: I2e3c4fe735b3374b2ff6d23850970e36c0aafda5 --- core/java/android/net/IpSecManager.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 01d1aa533a..c10680761f 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -810,7 +810,9 @@ public final class IpSecManager { * * @param underlyingNetwork the new {@link Network} that will carry traffic for this tunnel. * This network MUST never be the network exposing this IpSecTunnelInterface, otherwise - * this method will throw an {@link IllegalArgumentException}. + * this method will throw an {@link IllegalArgumentException}. If the + * IpSecTunnelInterface is later added to this network, all outbound traffic will be + * blackholed. */ // TODO: b/169171001 Update the documentation when transform migration is supported. // The purpose of making updating network and applying transforms separate is to leave open From 1c5ecec86dad7b764e81c8425f65bdf819f3dd0d Mon Sep 17 00:00:00 2001 From: Pavan Kumar M Date: Mon, 24 May 2021 00:28:41 +0530 Subject: [PATCH 641/881] Gracefully handle integer overflows. Avoid recording negative data by doing integer-based math as much as possible, but switch to double-based math if we detect that we'd end up causing an overflow. Test : - Builds, Boots - High data throughput scenarios - NetworkStatsHistoryTest, NetworkStatsCollectionTest, NetworkStatsTest Bug: 119527458 Change-Id: I355fc9bd127da83c1dc70ab3b1261346d4fa5de0 --- core/java/android/net/NetworkStats.java | 47 ++++++++++++++----------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 6ccbab7ed8..710a8c65ea 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -16,6 +16,8 @@ package android.net; +import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -1553,32 +1555,37 @@ public final class NetworkStats implements Parcelable { // processes this every time device has transmitted/received amount equivalent to // global threshold alert (~ 2MB) across all interfaces. final long rxBytesAcrossUnderlyingIfaces = - underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes; + multiplySafeByRational(underlyingIfacesTotal.rxBytes, + rxBytes[i], tunIfaceTotal.rxBytes); // app must not be blamed for more than it consumed on tunIface totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces); } long totalRxPackets = 0; if (tunIfaceTotal.rxPackets > 0) { final long rxPacketsAcrossUnderlyingIfaces = - underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets; + multiplySafeByRational(underlyingIfacesTotal.rxPackets, + rxPackets[i], tunIfaceTotal.rxPackets); totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces); } long totalTxBytes = 0; if (tunIfaceTotal.txBytes > 0) { final long txBytesAcrossUnderlyingIfaces = - underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes; + multiplySafeByRational(underlyingIfacesTotal.txBytes, + txBytes[i], tunIfaceTotal.txBytes); totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces); } long totalTxPackets = 0; if (tunIfaceTotal.txPackets > 0) { final long txPacketsAcrossUnderlyingIfaces = - underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets; + multiplySafeByRational(underlyingIfacesTotal.txPackets, + txPackets[i], tunIfaceTotal.txPackets); totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces); } long totalOperations = 0; if (tunIfaceTotal.operations > 0) { final long operationsAcrossUnderlyingIfaces = - underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations; + multiplySafeByRational(underlyingIfacesTotal.operations, + operations[i], tunIfaceTotal.operations); totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces); } // In a second pass, distribute these values across interfaces in the proportion that @@ -1590,37 +1597,37 @@ public final class NetworkStats implements Parcelable { tmpEntry.set = set[i]; if (underlyingIfacesTotal.rxBytes > 0) { tmpEntry.rxBytes = - totalRxBytes - * perInterfaceTotal[j].rxBytes - / underlyingIfacesTotal.rxBytes; + multiplySafeByRational(totalRxBytes, + perInterfaceTotal[j].rxBytes, + underlyingIfacesTotal.rxBytes); } tmpEntry.rxPackets = 0; if (underlyingIfacesTotal.rxPackets > 0) { tmpEntry.rxPackets = - totalRxPackets - * perInterfaceTotal[j].rxPackets - / underlyingIfacesTotal.rxPackets; + multiplySafeByRational(totalRxPackets, + perInterfaceTotal[j].rxPackets, + underlyingIfacesTotal.rxPackets); } tmpEntry.txBytes = 0; if (underlyingIfacesTotal.txBytes > 0) { tmpEntry.txBytes = - totalTxBytes - * perInterfaceTotal[j].txBytes - / underlyingIfacesTotal.txBytes; + multiplySafeByRational(totalTxBytes, + perInterfaceTotal[j].txBytes, + underlyingIfacesTotal.txBytes); } tmpEntry.txPackets = 0; if (underlyingIfacesTotal.txPackets > 0) { tmpEntry.txPackets = - totalTxPackets - * perInterfaceTotal[j].txPackets - / underlyingIfacesTotal.txPackets; + multiplySafeByRational(totalTxPackets, + perInterfaceTotal[j].txPackets, + underlyingIfacesTotal.txPackets); } tmpEntry.operations = 0; if (underlyingIfacesTotal.operations > 0) { tmpEntry.operations = - totalOperations - * perInterfaceTotal[j].operations - / underlyingIfacesTotal.operations; + multiplySafeByRational(totalOperations, + perInterfaceTotal[j].operations, + underlyingIfacesTotal.operations); } // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying // interface. Add that data usage to this object. From 35a6e5507e271c28375287d7ed9e87b75700082f Mon Sep 17 00:00:00 2001 From: lesl Date: Thu, 28 Jan 2021 15:58:23 +0800 Subject: [PATCH 642/881] carrier data usage: Use carrier template as default policy The carrier network means any network which linked with sepcific subscriberId (for instances: merged Wifi or mobile). Update default policy to use carrier network template to replace mobile template. No impact for current AOSP user because no any wifi network is merged wifi. (Because the merged wifi network requires to support from the wifi module). Also this change convert all of the old policies which template is TYEP_MOBILE to TYPE_CARRIER to match the default policy. Bug: 176396812 Test: atest -c NetworkPolicyManagerServiceTest Test: atest -c CtsHostsideNetworkTests Test: Manual Test with test code (Force wifi to merged wifi). The data will limit when using merged wifi. And mobile policy also work normally. Merged-In: I33c10f7549e713c52ce9afd5b8c4cce2abbda616 Change-Id: I33c10f7549e713c52ce9afd5b8c4cce2abbda616 --- core/java/android/net/NetworkTemplate.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index fd446cdf5c..249154aa91 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -514,6 +514,10 @@ public class NetworkTemplate implements Parcelable { return mSubscriberIdMatchRule; } + public int getMeteredness() { + return mMetered; + } + /** * Test if given {@link NetworkIdentity} matches this template. */ From 17df73a1b85a128a5f9a9fda780902bc038ed255 Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Wed, 26 May 2021 10:17:46 +0800 Subject: [PATCH 643/881] Make NsdService only start the native daemon when needed and automatically clean it up. Currently, NsdService starts the native mdnsresponder daemon if any NsdManager connect to it, which results in that when any constant service holds the NsdManager connection, the device would always be in the mdns multicast group whatever the connection is not used or not. This is because mdnsresponder will join the multicast group when it starts. To solve this problem, start the native daemon only when needed, and clean it up after the given idle timeout. 1. Start the native daemon when a new request come. 2. If there is no pending request, clean up the daemon after 3 seconds of idle time. Bug: 181810560 Test: atest NsdManagerTest NsdServiceTest Change-Id: I3eb04552f6cf6c0c68c07abffe751bb4d0669215 --- core/java/android/net/nsd/NsdManager.java | 3 + .../java/com/android/server/NsdService.java | 82 ++++++++++++++----- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 64f20b839a..5a25cfc00c 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -199,6 +199,9 @@ public final class NsdManager { /** @hide */ public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20; + /** @hide */ + public static final int DAEMON_CLEANUP = BASE + 21; + /** @hide */ public static final int ENABLE = BASE + 24; /** @hide */ diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index d907505481..38f7cf6bf5 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -61,6 +61,7 @@ public class NsdService extends INsdManager.Stub { private static final String MDNS_TAG = "mDnsConnector"; private static final boolean DBG = true; + private static final long CLEANUP_DELAY_MS = 3000; private final Context mContext; private final NsdSettings mNsdSettings; @@ -77,6 +78,7 @@ public class NsdService extends INsdManager.Stub { private final SparseArray mIdToClientInfoMap= new SparseArray<>(); private final AsyncChannel mReplyChannel = new AsyncChannel(); + private final long mCleanupDelayMs; private static final int INVALID_ID = 0; private int mUniqueId = 1; @@ -92,6 +94,22 @@ public class NsdService extends INsdManager.Stub { return NsdManager.nameOf(what); } + void maybeStartDaemon() { + mDaemon.maybeStart(); + maybeScheduleStop(); + } + + void maybeScheduleStop() { + if (!isAnyRequestActive()) { + cancelStop(); + sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs); + } + } + + void cancelStop() { + this.removeMessages(NsdManager.DAEMON_CLEANUP); + } + /** * Observes the NSD on/off setting, and takes action when changed. */ @@ -151,10 +169,6 @@ public class NsdService extends INsdManager.Stub { cInfo.expungeAllRequests(); mClients.remove(msg.replyTo); } - //Last client - if (mClients.size() == 0) { - mDaemon.stop(); - } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); @@ -180,6 +194,9 @@ public class NsdService extends INsdManager.Stub { replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, NsdManager.FAILURE_INTERNAL_ERROR); break; + case NsdManager.DAEMON_CLEANUP: + mDaemon.maybeStop(); + break; case NsdManager.NATIVE_DAEMON_EVENT: default: Slog.e(TAG, "Unhandled " + msg); @@ -212,16 +229,13 @@ public class NsdService extends INsdManager.Stub { @Override public void enter() { sendNsdStateChangeBroadcast(true); - if (mClients.size() > 0) { - mDaemon.start(); - } } @Override public void exit() { - if (mClients.size() > 0) { - mDaemon.stop(); - } + // TODO: it is incorrect to stop the daemon without expunging all requests + // and sending error callbacks to clients. + maybeScheduleStop(); } private boolean requestLimitReached(ClientInfo clientInfo) { @@ -236,12 +250,15 @@ public class NsdService extends INsdManager.Stub { clientInfo.mClientIds.put(clientId, globalId); clientInfo.mClientRequests.put(clientId, what); mIdToClientInfoMap.put(globalId, clientInfo); + // Remove the cleanup event because here comes a new request. + cancelStop(); } private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { clientInfo.mClientIds.delete(clientId); clientInfo.mClientRequests.delete(clientId); mIdToClientInfoMap.remove(globalId); + maybeScheduleStop(); } @Override @@ -251,14 +268,12 @@ public class NsdService extends INsdManager.Stub { int id; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - //First client - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && - mClients.size() == 0) { - mDaemon.start(); - } return NOT_HANDLED; case AsyncChannel.CMD_CHANNEL_DISCONNECTED: return NOT_HANDLED; + } + + switch (msg.what) { case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); @@ -274,6 +289,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (discoverServices(id, servInfo.getServiceType())) { if (DBG) { @@ -316,6 +332,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (registerService(id, (NsdServiceInfo) msg.obj)) { if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); @@ -357,6 +374,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (resolveService(id, servInfo)) { clientInfo.mResolvedService = new NsdServiceInfo(); @@ -513,6 +531,10 @@ public class NsdService extends INsdManager.Stub { } } + private boolean isAnyRequestActive() { + return mIdToClientInfoMap.size() != 0; + } + private String unescape(String s) { StringBuilder sb = new StringBuilder(s.length()); for (int i = 0; i < s.length(); ++i) { @@ -538,7 +560,9 @@ public class NsdService extends INsdManager.Stub { } @VisibleForTesting - NsdService(Context ctx, NsdSettings settings, Handler handler, DaemonConnectionSupplier fn) { + NsdService(Context ctx, NsdSettings settings, Handler handler, + DaemonConnectionSupplier fn, long cleanupDelayMs) { + mCleanupDelayMs = cleanupDelayMs; mContext = ctx; mNsdSettings = settings; mNsdStateMachine = new NsdStateMachine(TAG, handler); @@ -552,7 +576,8 @@ public class NsdService extends INsdManager.Stub { HandlerThread thread = new HandlerThread(TAG); thread.start(); Handler handler = new Handler(thread.getLooper()); - NsdService service = new NsdService(context, settings, handler, DaemonConnection::new); + NsdService service = new NsdService(context, settings, handler, + DaemonConnection::new, CLEANUP_DELAY_MS); service.mDaemonCallback.awaitConnection(); return service; } @@ -681,12 +706,16 @@ public class NsdService extends INsdManager.Stub { @VisibleForTesting public static class DaemonConnection { final NativeDaemonConnector mNativeConnector; + boolean mIsStarted = false; DaemonConnection(NativeCallbackReceiver callback) { mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null); new Thread(mNativeConnector, MDNS_TAG).start(); } + /** + * Executes the specified cmd on the daemon. + */ public boolean execute(Object... args) { if (DBG) { Slog.d(TAG, "mdnssd " + Arrays.toString(args)); @@ -700,12 +729,26 @@ public class NsdService extends INsdManager.Stub { return true; } - public void start() { + /** + * Starts the daemon if it is not already started. + */ + public void maybeStart() { + if (mIsStarted) { + return; + } execute("start-service"); + mIsStarted = true; } - public void stop() { + /** + * Stops the daemon if it is started. + */ + public void maybeStop() { + if (!mIsStarted) { + return; + } execute("stop-service"); + mIsStarted = false; } } @@ -864,6 +907,7 @@ public class NsdService extends INsdManager.Stub { } mClientIds.clear(); mClientRequests.clear(); + mNsdStateMachine.maybeScheduleStop(); } // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, From 74438ecd5ecf15097810c3eca8d1f18df471f710 Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Tue, 8 Jun 2021 03:04:27 +0800 Subject: [PATCH 644/881] Fix the comments from aosp/1717479. 1. Increase the cleanup delay from 3s to 10s. 2. Fix the comments from aosp/1717479. Bug: 181810560 Test: atest NsdManagerTest NsdServiceTest Change-Id: I71ebdd011574bd96de16a4248b0e15636418e87c --- .../java/com/android/server/NsdService.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 38f7cf6bf5..a9f3a1b63b 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -61,7 +61,7 @@ public class NsdService extends INsdManager.Stub { private static final String MDNS_TAG = "mDnsConnector"; private static final boolean DBG = true; - private static final long CLEANUP_DELAY_MS = 3000; + private static final long CLEANUP_DELAY_MS = 10000; private final Context mContext; private final NsdSettings mNsdSettings; @@ -94,19 +94,25 @@ public class NsdService extends INsdManager.Stub { return NsdManager.nameOf(what); } - void maybeStartDaemon() { + private void maybeStartDaemon() { mDaemon.maybeStart(); maybeScheduleStop(); } - void maybeScheduleStop() { + private boolean isAnyRequestActive() { + return mIdToClientInfoMap.size() != 0; + } + + private void scheduleStop() { + sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs); + } + private void maybeScheduleStop() { if (!isAnyRequestActive()) { - cancelStop(); - sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs); + scheduleStop(); } } - void cancelStop() { + private void cancelStop() { this.removeMessages(NsdManager.DAEMON_CLEANUP); } @@ -164,11 +170,16 @@ public class NsdService extends INsdManager.Stub { if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); break; } + cInfo = mClients.get(msg.replyTo); if (cInfo != null) { cInfo.expungeAllRequests(); mClients.remove(msg.replyTo); } + //Last client + if (mClients.size() == 0) { + scheduleStop(); + } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); @@ -235,7 +246,7 @@ public class NsdService extends INsdManager.Stub { public void exit() { // TODO: it is incorrect to stop the daemon without expunging all requests // and sending error callbacks to clients. - maybeScheduleStop(); + scheduleStop(); } private boolean requestLimitReached(ClientInfo clientInfo) { @@ -271,9 +282,6 @@ public class NsdService extends INsdManager.Stub { return NOT_HANDLED; case AsyncChannel.CMD_CHANNEL_DISCONNECTED: return NOT_HANDLED; - } - - switch (msg.what) { case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); @@ -531,10 +539,6 @@ public class NsdService extends INsdManager.Stub { } } - private boolean isAnyRequestActive() { - return mIdToClientInfoMap.size() != 0; - } - private String unescape(String s) { StringBuilder sb = new StringBuilder(s.length()); for (int i = 0; i < s.length(); ++i) { @@ -907,7 +911,6 @@ public class NsdService extends INsdManager.Stub { } mClientIds.clear(); mClientRequests.clear(); - mNsdStateMachine.maybeScheduleStop(); } // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, From c873a96dcc4535eb1ee6e4720547301235df1423 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Fri, 4 Jun 2021 18:31:42 +0800 Subject: [PATCH 645/881] Fix: query TYPE_WIFI usage with empty string Starting with API level 31, the subscriberId is applicable for the wifi network. Considering applications may use null or an empty string as subscriberId (for instance, cts), frameworks create MATCH_WIFI_WILDCARD NetworkTemplate when querying wifi network with null or an empty string which is the behavior before API level 31. Bug: 188915450 Test: atest -c NetworkStatsManagerTest Change-Id: I084b69903f8ba7a6225b312560752e8508938714 --- .../app/usage/NetworkStatsManager.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index fe99f8532a..8a6c85d548 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -48,6 +48,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.DataUnit; import android.util.Log; @@ -214,6 +215,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -255,6 +260,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -300,6 +309,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -388,6 +401,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -450,6 +467,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -531,6 +552,10 @@ public class NetworkStatsManager { * null} value when registering for the mobile network type to receive * notifications for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param thresholdBytes Threshold in bytes to be notified on. * @param callback The {@link UsageCallback} that the system will call when data usage * has exceeded the specified threshold. @@ -644,7 +669,7 @@ public class NetworkStatsManager { : NetworkTemplate.buildTemplateMobileAll(subscriberId); break; case ConnectivityManager.TYPE_WIFI: - template = subscriberId == null + template = TextUtils.isEmpty(subscriberId) ? NetworkTemplate.buildTemplateWifiWildcard() : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, subscriberId); From 62350e36c8b31fb9b9bdac7d1b51a715ab3e737a Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sat, 12 Jun 2021 00:41:14 +0900 Subject: [PATCH 646/881] Stop using LinkPropertiesParcelableUtil. Its methods are all no-ops. Stop using them. Test: m Bug: 151052811 Change-Id: Iace3ba898bec2940ec3c3323c5bf8a13627d545f --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index aa80e4de2d..28b24f1fb1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,8 +16,6 @@ package com.android.server.ethernet; -import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; - import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -560,7 +558,7 @@ public class EthernetNetworkFactory extends NetworkFactory { if (config.getProxySettings() == ProxySettings.STATIC || config.getProxySettings() == ProxySettings.PAC) { try { - ipClient.setHttpProxy(toStableParcelable(config.getHttpProxy())); + ipClient.setHttpProxy(config.getHttpProxy()); } catch (RemoteException e) { e.rethrowFromSystemServer(); } From e022ea5d80ae6da9d72cf8966150b9f196496dad Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Sun, 13 Jun 2021 16:52:05 +0000 Subject: [PATCH 647/881] Make NsdService only start the native daemon when needed and automatically clean it up. Currently, NsdService starts the native mdnsresponder daemon if any NsdManager connect to it, which results in that when any constant service holds the NsdManager connection, the device would always be in the mdns multicast group whatever the connection is not used or not. This is because mdnsresponder will join the multicast group when it starts. To solve this problem, start the native daemon only when needed, and clean it up after the given idle timeout. 1. Start the native daemon when a new request come. 2. If there is no pending request, clean up the daemon after 3 seconds of idle time. Bug: 181810560 Test: atest NsdManagerTest NsdServiceTest Original-Change: https://android-review.googlesource.com/1717479 Merged-In: I3eb04552f6cf6c0c68c07abffe751bb4d0669215 Change-Id: I3eb04552f6cf6c0c68c07abffe751bb4d0669215 --- core/java/android/net/nsd/NsdManager.java | 3 + .../java/com/android/server/NsdService.java | 82 ++++++++++++++----- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index 64f20b839a..5a25cfc00c 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -199,6 +199,9 @@ public final class NsdManager { /** @hide */ public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20; + /** @hide */ + public static final int DAEMON_CLEANUP = BASE + 21; + /** @hide */ public static final int ENABLE = BASE + 24; /** @hide */ diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index 84f40cb4b8..a481a6a5d3 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -61,6 +61,7 @@ public class NsdService extends INsdManager.Stub { private static final String MDNS_TAG = "mDnsConnector"; private static final boolean DBG = true; + private static final long CLEANUP_DELAY_MS = 3000; private final Context mContext; private final NsdSettings mNsdSettings; @@ -77,6 +78,7 @@ public class NsdService extends INsdManager.Stub { private final SparseArray mIdToClientInfoMap= new SparseArray<>(); private final AsyncChannel mReplyChannel = new AsyncChannel(); + private final long mCleanupDelayMs; private static final int INVALID_ID = 0; private int mUniqueId = 1; @@ -92,6 +94,22 @@ public class NsdService extends INsdManager.Stub { return NsdManager.nameOf(what); } + void maybeStartDaemon() { + mDaemon.maybeStart(); + maybeScheduleStop(); + } + + void maybeScheduleStop() { + if (!isAnyRequestActive()) { + cancelStop(); + sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs); + } + } + + void cancelStop() { + this.removeMessages(NsdManager.DAEMON_CLEANUP); + } + /** * Observes the NSD on/off setting, and takes action when changed. */ @@ -151,10 +169,6 @@ public class NsdService extends INsdManager.Stub { cInfo.expungeAllRequests(); mClients.remove(msg.replyTo); } - //Last client - if (mClients.size() == 0) { - mDaemon.stop(); - } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); @@ -180,6 +194,9 @@ public class NsdService extends INsdManager.Stub { replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, NsdManager.FAILURE_INTERNAL_ERROR); break; + case NsdManager.DAEMON_CLEANUP: + mDaemon.maybeStop(); + break; case NsdManager.NATIVE_DAEMON_EVENT: default: Slog.e(TAG, "Unhandled " + msg); @@ -212,16 +229,13 @@ public class NsdService extends INsdManager.Stub { @Override public void enter() { sendNsdStateChangeBroadcast(true); - if (mClients.size() > 0) { - mDaemon.start(); - } } @Override public void exit() { - if (mClients.size() > 0) { - mDaemon.stop(); - } + // TODO: it is incorrect to stop the daemon without expunging all requests + // and sending error callbacks to clients. + maybeScheduleStop(); } private boolean requestLimitReached(ClientInfo clientInfo) { @@ -236,12 +250,15 @@ public class NsdService extends INsdManager.Stub { clientInfo.mClientIds.put(clientId, globalId); clientInfo.mClientRequests.put(clientId, what); mIdToClientInfoMap.put(globalId, clientInfo); + // Remove the cleanup event because here comes a new request. + cancelStop(); } private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) { clientInfo.mClientIds.delete(clientId); clientInfo.mClientRequests.delete(clientId); mIdToClientInfoMap.remove(globalId); + maybeScheduleStop(); } @Override @@ -251,14 +268,12 @@ public class NsdService extends INsdManager.Stub { int id; switch (msg.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - //First client - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL && - mClients.size() == 0) { - mDaemon.start(); - } return NOT_HANDLED; case AsyncChannel.CMD_CHANNEL_DISCONNECTED: return NOT_HANDLED; + } + + switch (msg.what) { case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); @@ -274,6 +289,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (discoverServices(id, servInfo.getServiceType())) { if (DBG) { @@ -316,6 +332,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (registerService(id, (NsdServiceInfo) msg.obj)) { if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); @@ -357,6 +374,7 @@ public class NsdService extends INsdManager.Stub { break; } + maybeStartDaemon(); id = getUniqueId(); if (resolveService(id, servInfo)) { clientInfo.mResolvedService = new NsdServiceInfo(); @@ -513,6 +531,10 @@ public class NsdService extends INsdManager.Stub { } } + private boolean isAnyRequestActive() { + return mIdToClientInfoMap.size() != 0; + } + private String unescape(String s) { StringBuilder sb = new StringBuilder(s.length()); for (int i = 0; i < s.length(); ++i) { @@ -538,7 +560,9 @@ public class NsdService extends INsdManager.Stub { } @VisibleForTesting - NsdService(Context ctx, NsdSettings settings, Handler handler, DaemonConnectionSupplier fn) { + NsdService(Context ctx, NsdSettings settings, Handler handler, + DaemonConnectionSupplier fn, long cleanupDelayMs) { + mCleanupDelayMs = cleanupDelayMs; mContext = ctx; mNsdSettings = settings; mNsdStateMachine = new NsdStateMachine(TAG, handler); @@ -552,7 +576,8 @@ public class NsdService extends INsdManager.Stub { HandlerThread thread = new HandlerThread(TAG); thread.start(); Handler handler = new Handler(thread.getLooper()); - NsdService service = new NsdService(context, settings, handler, DaemonConnection::new); + NsdService service = new NsdService(context, settings, handler, + DaemonConnection::new, CLEANUP_DELAY_MS); service.mDaemonCallback.awaitConnection(); return service; } @@ -681,12 +706,16 @@ public class NsdService extends INsdManager.Stub { @VisibleForTesting public static class DaemonConnection { final NativeDaemonConnector mNativeConnector; + boolean mIsStarted = false; DaemonConnection(NativeCallbackReceiver callback) { mNativeConnector = new NativeDaemonConnector(callback, "mdns", 10, MDNS_TAG, 25, null); new Thread(mNativeConnector, MDNS_TAG).start(); } + /** + * Executes the specified cmd on the daemon. + */ public boolean execute(Object... args) { if (DBG) { Slog.d(TAG, "mdnssd " + Arrays.toString(args)); @@ -700,12 +729,26 @@ public class NsdService extends INsdManager.Stub { return true; } - public void start() { + /** + * Starts the daemon if it is not already started. + */ + public void maybeStart() { + if (mIsStarted) { + return; + } execute("start-service"); + mIsStarted = true; } - public void stop() { + /** + * Stops the daemon if it is started. + */ + public void maybeStop() { + if (!mIsStarted) { + return; + } execute("stop-service"); + mIsStarted = false; } } @@ -864,6 +907,7 @@ public class NsdService extends INsdManager.Stub { } mClientIds.clear(); mClientRequests.clear(); + mNsdStateMachine.maybeScheduleStop(); } // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, From 6e1e9ef22222853800c06f03aa4b687381fb6b66 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Fri, 4 Jun 2021 18:31:42 +0800 Subject: [PATCH 648/881] Fix: query TYPE_WIFI usage with empty string Starting with API level 31, the subscriberId is applicable for the wifi network. Considering applications may use null or an empty string as subscriberId (for instance, cts), frameworks create MATCH_WIFI_WILDCARD NetworkTemplate when querying wifi network with null or an empty string which is the behavior before API level 31. Bug: 188915450 Test: atest -c NetworkStatsManagerTest Test: atest -c NetworkUsageStatsTest Merged-In: I084b69903f8ba7a6225b312560752e8508938714 Change-Id: I084b69903f8ba7a6225b312560752e8508938714 --- .../app/usage/NetworkStatsManager.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index fe99f8532a..8a6c85d548 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -48,6 +48,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.DataUnit; import android.util.Log; @@ -214,6 +215,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -255,6 +260,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -300,6 +309,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -388,6 +401,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -450,6 +467,10 @@ public class NetworkStatsManager { * null} value when querying for the mobile network type to receive usage * for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param startTime Start of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param endTime End of period. Defined in terms of "Unix time", see @@ -531,6 +552,10 @@ public class NetworkStatsManager { * null} value when registering for the mobile network type to receive * notifications for all mobile networks. For additional details see {@link * TelephonyManager#getSubscriberId()}. + *

Starting with API level 31, calling apps can provide a + * {@code subscriberId} with wifi network type to receive usage for + * wifi networks which is under the given subscription if applicable. + * Otherwise, pass {@code null} when querying all wifi networks. * @param thresholdBytes Threshold in bytes to be notified on. * @param callback The {@link UsageCallback} that the system will call when data usage * has exceeded the specified threshold. @@ -644,7 +669,7 @@ public class NetworkStatsManager { : NetworkTemplate.buildTemplateMobileAll(subscriberId); break; case ConnectivityManager.TYPE_WIFI: - template = subscriberId == null + template = TextUtils.isEmpty(subscriberId) ? NetworkTemplate.buildTemplateWifiWildcard() : NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, subscriberId); From c680ae2b5550f212115aef237d499e34ac7dce52 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 21 Jun 2021 10:34:48 +0000 Subject: [PATCH 649/881] Stop using LinkPropertiesParcelableUtil. Its methods are all no-ops. Stop using them. Test: m Bug: 151052811 Original-Change: https://android-review.googlesource.com/1733473 Merged-In: Iace3ba898bec2940ec3c3323c5bf8a13627d545f Change-Id: Iace3ba898bec2940ec3c3323c5bf8a13627d545f --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index aa80e4de2d..28b24f1fb1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,8 +16,6 @@ package com.android.server.ethernet; -import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; - import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -560,7 +558,7 @@ public class EthernetNetworkFactory extends NetworkFactory { if (config.getProxySettings() == ProxySettings.STATIC || config.getProxySettings() == ProxySettings.PAC) { try { - ipClient.setHttpProxy(toStableParcelable(config.getHttpProxy())); + ipClient.setHttpProxy(config.getHttpProxy()); } catch (RemoteException e) { e.rethrowFromSystemServer(); } From ee32d885c7c7819f630a60d99ea6107547819f36 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 21 Jun 2021 10:34:48 +0000 Subject: [PATCH 650/881] Stop using LinkPropertiesParcelableUtil. Its methods are all no-ops. Stop using them. Test: m Bug: 151052811 Original-Change: https://android-review.googlesource.com/1733473 Merged-In: Iace3ba898bec2940ec3c3323c5bf8a13627d545f Change-Id: Iace3ba898bec2940ec3c3323c5bf8a13627d545f --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index aa80e4de2d..28b24f1fb1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,8 +16,6 @@ package com.android.server.ethernet; -import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; - import static com.android.internal.util.Preconditions.checkNotNull; import android.annotation.NonNull; @@ -560,7 +558,7 @@ public class EthernetNetworkFactory extends NetworkFactory { if (config.getProxySettings() == ProxySettings.STATIC || config.getProxySettings() == ProxySettings.PAC) { try { - ipClient.setHttpProxy(toStableParcelable(config.getHttpProxy())); + ipClient.setHttpProxy(config.getHttpProxy()); } catch (RemoteException e) { e.rethrowFromSystemServer(); } From ac4f1912cfb15e85242c35ce9cfbaa9e3464f5bd Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Wed, 23 Jun 2021 06:29:30 +0000 Subject: [PATCH 651/881] Fix the comments from aosp/1717479. 1. Increase the cleanup delay from 3s to 10s. 2. Fix the comments from aosp/1717479. Bug: 181810560 Test: atest NsdManagerTest NsdServiceTest Original-Change: https://android-review.googlesource.com/1730170 Merged-In: I71ebdd011574bd96de16a4248b0e15636418e87c Change-Id: I71ebdd011574bd96de16a4248b0e15636418e87c --- .../java/com/android/server/NsdService.java | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index a481a6a5d3..f440ee8c4e 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -61,7 +61,7 @@ public class NsdService extends INsdManager.Stub { private static final String MDNS_TAG = "mDnsConnector"; private static final boolean DBG = true; - private static final long CLEANUP_DELAY_MS = 3000; + private static final long CLEANUP_DELAY_MS = 10000; private final Context mContext; private final NsdSettings mNsdSettings; @@ -94,19 +94,25 @@ public class NsdService extends INsdManager.Stub { return NsdManager.nameOf(what); } - void maybeStartDaemon() { + private void maybeStartDaemon() { mDaemon.maybeStart(); maybeScheduleStop(); } - void maybeScheduleStop() { + private boolean isAnyRequestActive() { + return mIdToClientInfoMap.size() != 0; + } + + private void scheduleStop() { + sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs); + } + private void maybeScheduleStop() { if (!isAnyRequestActive()) { - cancelStop(); - sendMessageDelayed(NsdManager.DAEMON_CLEANUP, mCleanupDelayMs); + scheduleStop(); } } - void cancelStop() { + private void cancelStop() { this.removeMessages(NsdManager.DAEMON_CLEANUP); } @@ -164,11 +170,16 @@ public class NsdService extends INsdManager.Stub { if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); break; } + cInfo = mClients.get(msg.replyTo); if (cInfo != null) { cInfo.expungeAllRequests(); mClients.remove(msg.replyTo); } + //Last client + if (mClients.size() == 0) { + scheduleStop(); + } break; case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: AsyncChannel ac = new AsyncChannel(); @@ -235,7 +246,7 @@ public class NsdService extends INsdManager.Stub { public void exit() { // TODO: it is incorrect to stop the daemon without expunging all requests // and sending error callbacks to clients. - maybeScheduleStop(); + scheduleStop(); } private boolean requestLimitReached(ClientInfo clientInfo) { @@ -271,9 +282,6 @@ public class NsdService extends INsdManager.Stub { return NOT_HANDLED; case AsyncChannel.CMD_CHANNEL_DISCONNECTED: return NOT_HANDLED; - } - - switch (msg.what) { case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); @@ -531,10 +539,6 @@ public class NsdService extends INsdManager.Stub { } } - private boolean isAnyRequestActive() { - return mIdToClientInfoMap.size() != 0; - } - private String unescape(String s) { StringBuilder sb = new StringBuilder(s.length()); for (int i = 0; i < s.length(); ++i) { @@ -907,7 +911,6 @@ public class NsdService extends INsdManager.Stub { } mClientIds.clear(); mClientRequests.clear(); - mNsdStateMachine.maybeScheduleStop(); } // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id, From 788a98192260d396417687877b88e9ace8103338 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 24 Jun 2021 14:43:09 -0700 Subject: [PATCH 652/881] Add support for app data accounting for in-kernel dataplanes This change ensures that app data accounting works correctly within the confines of in-kernel dataplanes, as used by platform VPNs and the VCN. Notably, the VCN MUST NOT specify the IMSI, as that would lead to double counting of the interface statistics. Bug: 175853498 Bug: 190620024 Test: atest NetworkStatsTest FrameworksVcnTests Change-Id: I768907cd3dd2028c7040cddd81fc71a5ce69bbdb --- core/java/android/net/NetworkStats.java | 42 ++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 6ccbab7ed8..288b06ee52 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -24,6 +24,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.os.Process; import android.os.SystemClock; import android.util.SparseBooleanArray; @@ -1487,8 +1488,31 @@ public final class NetworkStats implements Parcelable { continue; } - if (recycle.uid == tunUid) { - // Add up traffic through tunUid's underlying interfaces. + if (tunUid == Process.SYSTEM_UID) { + // Kernel-based VPN or VCN, traffic sent by apps on the VPN/VCN network + // + // Since the data is not UID-accounted on underlying networks, just use VPN/VCN + // network usage as ground truth. Encrypted traffic on the underlying networks will + // never be processed here because encrypted traffic on the underlying interfaces + // is not present in UID stats, and this method is only called on UID stats. + if (tunIface.equals(recycle.iface)) { + tunIfaceTotal.add(recycle); + underlyingIfacesTotal.add(recycle); + + // In steady state, there should always be one network, but edge cases may + // result in the network being null (network lost), and thus no underlying + // ifaces is possible. + if (perInterfaceTotal.length > 0) { + // While platform VPNs and VCNs have exactly one underlying network, that + // network may have multiple interfaces (eg for 464xlat). This layer does + // not have the required information to identify which of the interfaces + // were used. Select "any" of the interfaces. Since overhead is already + // lost, this number is an approximation anyways. + perInterfaceTotal[0].add(recycle); + } + } + } else if (recycle.uid == tunUid) { + // VpnService VPN, traffic sent by the VPN app over underlying networks for (int j = 0; j < underlyingIfaces.size(); j++) { if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) { perInterfaceTotal[j].add(recycle); @@ -1497,7 +1521,7 @@ public final class NetworkStats implements Parcelable { } } } else if (tunIface.equals(recycle.iface)) { - // Add up all tunIface traffic excluding traffic from the vpn app itself. + // VpnService VPN; traffic sent by apps on the VPN network tunIfaceTotal.add(recycle); } } @@ -1532,9 +1556,13 @@ public final class NetworkStats implements Parcelable { // Consider only entries that go onto the VPN interface. continue; } - if (uid[i] == tunUid) { + + if (uid[i] == tunUid && tunUid != Process.SYSTEM_UID) { // Exclude VPN app from the redistribution, as it can choose to create packet // streams by writing to itself. + // + // However, for platform VPNs, do not exclude the system's usage of the VPN network, + // since it is never local-only, and never double counted continue; } tmpEntry.uid = uid[i]; @@ -1641,6 +1669,12 @@ public final class NetworkStats implements Parcelable { int tunUid, @NonNull List underlyingIfaces, @NonNull Entry[] moved) { + if (tunUid == Process.SYSTEM_UID) { + // No traffic recorded on a per-UID basis for in-kernel VPN/VCNs over underlying + // networks; thus no traffic to deduct. + return; + } + for (int i = 0; i < underlyingIfaces.size(); i++) { moved[i].uid = tunUid; // Add debug info From 9f97237115caa29539ef2d2d2466bbce8fb866a5 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Fri, 2 Jul 2021 19:12:24 +0000 Subject: [PATCH 653/881] Add support for app data accounting for in-kernel dataplanes This change ensures that app data accounting works correctly within the confines of in-kernel dataplanes, as used by platform VPNs and the VCN. Notably, the VCN MUST NOT specify the IMSI, as that would lead to double counting of the interface statistics. Bug: 175853498 Bug: 190620024 Test: atest NetworkStatsTest FrameworksVcnTests Original-Change: https://android-review.googlesource.com/1749070 Merged-In: I768907cd3dd2028c7040cddd81fc71a5ce69bbdb Change-Id: I768907cd3dd2028c7040cddd81fc71a5ce69bbdb --- core/java/android/net/NetworkStats.java | 42 ++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 6ccbab7ed8..288b06ee52 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -24,6 +24,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.os.Process; import android.os.SystemClock; import android.util.SparseBooleanArray; @@ -1487,8 +1488,31 @@ public final class NetworkStats implements Parcelable { continue; } - if (recycle.uid == tunUid) { - // Add up traffic through tunUid's underlying interfaces. + if (tunUid == Process.SYSTEM_UID) { + // Kernel-based VPN or VCN, traffic sent by apps on the VPN/VCN network + // + // Since the data is not UID-accounted on underlying networks, just use VPN/VCN + // network usage as ground truth. Encrypted traffic on the underlying networks will + // never be processed here because encrypted traffic on the underlying interfaces + // is not present in UID stats, and this method is only called on UID stats. + if (tunIface.equals(recycle.iface)) { + tunIfaceTotal.add(recycle); + underlyingIfacesTotal.add(recycle); + + // In steady state, there should always be one network, but edge cases may + // result in the network being null (network lost), and thus no underlying + // ifaces is possible. + if (perInterfaceTotal.length > 0) { + // While platform VPNs and VCNs have exactly one underlying network, that + // network may have multiple interfaces (eg for 464xlat). This layer does + // not have the required information to identify which of the interfaces + // were used. Select "any" of the interfaces. Since overhead is already + // lost, this number is an approximation anyways. + perInterfaceTotal[0].add(recycle); + } + } + } else if (recycle.uid == tunUid) { + // VpnService VPN, traffic sent by the VPN app over underlying networks for (int j = 0; j < underlyingIfaces.size(); j++) { if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) { perInterfaceTotal[j].add(recycle); @@ -1497,7 +1521,7 @@ public final class NetworkStats implements Parcelable { } } } else if (tunIface.equals(recycle.iface)) { - // Add up all tunIface traffic excluding traffic from the vpn app itself. + // VpnService VPN; traffic sent by apps on the VPN network tunIfaceTotal.add(recycle); } } @@ -1532,9 +1556,13 @@ public final class NetworkStats implements Parcelable { // Consider only entries that go onto the VPN interface. continue; } - if (uid[i] == tunUid) { + + if (uid[i] == tunUid && tunUid != Process.SYSTEM_UID) { // Exclude VPN app from the redistribution, as it can choose to create packet // streams by writing to itself. + // + // However, for platform VPNs, do not exclude the system's usage of the VPN network, + // since it is never local-only, and never double counted continue; } tmpEntry.uid = uid[i]; @@ -1641,6 +1669,12 @@ public final class NetworkStats implements Parcelable { int tunUid, @NonNull List underlyingIfaces, @NonNull Entry[] moved) { + if (tunUid == Process.SYSTEM_UID) { + // No traffic recorded on a per-UID basis for in-kernel VPN/VCNs over underlying + // networks; thus no traffic to deduct. + return; + } + for (int i = 0; i < underlyingIfaces.size(); i++) { moved[i].uid = tunUid; // Add debug info From 7c7697890974e1a9041883bfe561d9b82c701f23 Mon Sep 17 00:00:00 2001 From: paulhu Date: Fri, 9 Apr 2021 15:47:36 +0800 Subject: [PATCH 654/881] Rename FIRST_SDK_INT to DEVICE_INITIAL_SDK_INT As API review feedback, rename Build#VERSION#FIRST_SDK_INT to Build#VERSION#DEVICE_INITIAL_SDK_INT. As well as update all usage in frameworks and tests. Bug: 184735771 Test: m Merged-In: I72660959cb4e638a8e80fcf2f4e96ea172969f44 (cherry-pick with minor conflicts) Change-Id: I72660959cb4e638a8e80fcf2f4e96ea172969f44 --- core/java/android/net/IpSecAlgorithm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 8f1e2defd2..7ef5bac092 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -354,7 +354,7 @@ public final class IpSecAlgorithm implements Parcelable { } for (Entry entry : ALGO_TO_REQUIRED_FIRST_SDK.entrySet()) { - if (Build.VERSION.FIRST_SDK_INT >= entry.getValue()) { + if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= entry.getValue()) { enabledAlgos.add(entry.getKey()); } } From 716683f9582da21b8a2ecad0faef931d61ad3613 Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Mon, 12 Jul 2021 21:15:10 +0800 Subject: [PATCH 655/881] Keep the native mdns daemon alive for pre-S application Roll back the behavior changes by checking the target SDK to ensure that there are no compatibility issues with the pre-S application. If the target SDK of the application Date: Mon, 12 Jul 2021 21:15:10 +0800 Subject: [PATCH 656/881] Keep the native mdns daemon alive for pre-S application Roll back the behavior changes by checking the target SDK to ensure that there are no compatibility issues with the pre-S application. If the target SDK of the application Date: Wed, 14 Jul 2021 06:44:37 +0000 Subject: [PATCH 657/881] Fix mMobileIfaces is not protected by lock Currently, mMobileIfaces is accessed from multiple threads, and should be protected from concurrent accessing. However, since the variable could be accessed frequently, holding the mStatsLock would make this be blocked by network stats I/O operations. Thus, protect the variable by making it volatile. Test: Wifi on/off stress test Bug: 192758557 Change-Id: Ie7694a63f5203ee7c83830ca13d97219b7949fd7 --- .../com/android/server/net/NetworkStatsService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4ee867b7d0..f571b35f8c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -289,8 +289,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private String mActiveIface; /** Set of any ifaces associated with mobile networks since boot. */ - @GuardedBy("mStatsLock") - private String[] mMobileIfaces = new String[0]; + private volatile String[] mMobileIfaces = new String[0]; /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */ @GuardedBy("mStatsLock") @@ -935,7 +934,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public String[] getMobileIfaces() { - return mMobileIfaces; + return mMobileIfaces.clone(); } @Override @@ -1084,7 +1083,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public long getIfaceStats(String iface, int type) { + public long getIfaceStats(@NonNull String iface, int type) { + Objects.requireNonNull(iface); long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); if (nativeIfaceStats == -1) { return nativeIfaceStats; @@ -1382,7 +1382,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]); + mMobileIfaces = mobileIfaces.toArray(new String[0]); } private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { From f6f106653235f4c3e3dfdef737893e84ae7fa6e4 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 26 Jul 2021 09:16:59 +0000 Subject: [PATCH 658/881] Add debug log for tracking NPE of mMobileIfaces Test: TH Bug: 192758557 Change-Id: Ib048c18b1c64627de5a9d2b04d10e084a014ff64 --- .../com/android/server/net/NetworkStatsService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index f571b35f8c..097b0711ef 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -934,6 +934,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public String[] getMobileIfaces() { + // TODO (b/192758557): Remove debug log. + if (ArrayUtils.contains(mMobileIfaces, null)) { + throw new NullPointerException( + "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); + } return mMobileIfaces.clone(); } @@ -1383,6 +1388,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } mMobileIfaces = mobileIfaces.toArray(new String[0]); + // TODO (b/192758557): Remove debug log. + if (ArrayUtils.contains(mMobileIfaces, null)) { + throw new NullPointerException( + "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); + } } private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { From 4a60d5336958e6fb9e304dbe471cd38e9c33a901 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 4 Nov 2020 17:04:21 +0100 Subject: [PATCH 659/881] Add Tests for EthernetNetworkFactory Test: atest EthernetNetworkFactoryTest Bug: 191635995 Change-Id: I1c07bb6d30706c4e13002eb402fadfecb97b36d1 --- .../server/ethernet/EthernetNetworkAgent.java | 65 +++ .../ethernet/EthernetNetworkFactory.java | 72 +++- tests/ethernet/Android.bp | 4 + tests/ethernet/AndroidManifest.xml | 2 +- .../ethernet/EthernetNetworkFactoryTest.java | 395 ++++++++++++++++++ 5 files changed, 517 insertions(+), 21 deletions(-) create mode 100644 service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java create mode 100644 tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java b/service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java new file mode 100644 index 0000000000..5598fc6a11 --- /dev/null +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.ethernet; + +import android.content.Context; +import android.net.LinkProperties; +import android.net.NetworkAgent; +import android.net.NetworkAgentConfig; +import android.net.NetworkCapabilities; +import android.net.NetworkProvider; +import android.os.Looper; +import android.annotation.NonNull; +import android.annotation.Nullable; + +public class EthernetNetworkAgent extends NetworkAgent { + + private static final String TAG = "EthernetNetworkAgent"; + + public interface Callbacks { + void onNetworkUnwanted(); + } + + private final Callbacks mCallbacks; + + EthernetNetworkAgent( + @NonNull Context context, + @NonNull Looper looper, + @NonNull NetworkCapabilities nc, + @NonNull LinkProperties lp, + int networkScore, + @NonNull NetworkAgentConfig config, + @Nullable NetworkProvider provider, + @NonNull Callbacks cb) { + super(context, looper, TAG, nc, lp, networkScore, config, provider); + mCallbacks = cb; + } + + @Override + public void onNetworkUnwanted() { + mCallbacks.onNetworkUnwanted(); + } + + // sendLinkProperties is final in NetworkAgent, so it cannot be mocked. + public void sendLinkPropertiesImpl(LinkProperties lp) { + sendLinkProperties(lp); + } + + public Callbacks getCallbacks() { + return mCallbacks; + } +} diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 28b24f1fb1..f4de23d7d3 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -27,10 +27,10 @@ import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkProperties; -import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; +import android.net.NetworkProvider; import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.ip.IIpClient; @@ -40,12 +40,14 @@ import android.net.shared.ProvisioningConfiguration; import android.net.util.InterfaceParams; import android.os.ConditionVariable; import android.os.Handler; +import android.os.Looper; import android.os.RemoteException; import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.Log; import android.util.SparseArray; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; @@ -69,6 +71,25 @@ public class EthernetNetworkFactory extends NetworkFactory { new ConcurrentHashMap<>(); private final Handler mHandler; private final Context mContext; + final Dependencies mDeps; + + public static class Dependencies { + public void makeIpClient(Context context, String iface, IpClientCallbacks callbacks) { + IpClientUtil.makeIpClient(context, iface, callbacks); + } + + public EthernetNetworkAgent makeEthernetNetworkAgent(Context context, Looper looper, + NetworkCapabilities nc, LinkProperties lp, int networkScore, + NetworkAgentConfig config, NetworkProvider provider, + EthernetNetworkAgent.Callbacks cb) { + return new EthernetNetworkAgent(context, looper, nc, lp, networkScore, config, provider, + cb); + } + + public InterfaceParams getNetworkInterfaceByName(String name) { + return InterfaceParams.getByName(name); + } + } public static class ConfigurationException extends AndroidRuntimeException { public ConfigurationException(String msg) { @@ -77,10 +98,17 @@ public class EthernetNetworkFactory extends NetworkFactory { } public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) { + this(handler, context, filter, new Dependencies()); + } + + @VisibleForTesting + EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter, + Dependencies deps) { super(handler.getLooper(), context, NETWORK_TYPE, filter); mHandler = handler; mContext = context; + mDeps = deps; setScoreFilter(NETWORK_SCORE); } @@ -149,7 +177,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } NetworkInterfaceState iface = new NetworkInterfaceState( - ifaceName, hwAddress, mHandler, mContext, capabilities, this); + ifaceName, hwAddress, mHandler, mContext, capabilities, this, mDeps); iface.setIpConfig(ipConfiguration); mTrackingInterfaces.put(ifaceName, iface); @@ -251,6 +279,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private final Handler mHandler; private final Context mContext; private final NetworkFactory mNetworkFactory; + private final Dependencies mDeps; private final int mLegacyType; private static String sTcpBufferSizes = null; // Lazy initialized. @@ -260,7 +289,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private volatile @Nullable IIpClient mIpClient; private @Nullable IpClientCallbacksImpl mIpClientCallback; - private @Nullable NetworkAgent mNetworkAgent; + private @Nullable EthernetNetworkAgent mNetworkAgent; private @Nullable IpConfiguration mIpConfig; /** @@ -360,12 +389,14 @@ public class EthernetNetworkFactory extends NetworkFactory { } NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, - @NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory) { + @NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory, + Dependencies deps) { name = ifaceName; mCapabilities = checkNotNull(capabilities); mHandler = handler; mContext = context; mNetworkFactory = networkFactory; + mDeps = deps; int legacyType = ConnectivityManager.TYPE_NONE; int[] transportTypes = mCapabilities.getTransportTypes(); @@ -451,7 +482,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } mIpClientCallback = new IpClientCallbacksImpl(); - IpClientUtil.makeIpClient(mContext, name, mIpClientCallback); + mDeps.makeIpClient(mContext, name, mIpClientCallback); mIpClientCallback.awaitIpClientStart(); if (sTcpBufferSizes == null) { sTcpBufferSizes = mContext.getResources().getString( @@ -474,18 +505,19 @@ public class EthernetNetworkFactory extends NetworkFactory { .setLegacyTypeName(NETWORK_TYPE) .setLegacyExtraInfo(mHwAddress) .build(); - mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(), - NETWORK_TYPE, mCapabilities, mLinkProperties, - getNetworkScore(), config, mNetworkFactory.getProvider()) { - public void unwanted() { - if (this == mNetworkAgent) { - stop(); - } else if (mNetworkAgent != null) { - Log.d(TAG, "Ignoring unwanted as we have a more modern " + - "instance"); - } // Otherwise, we've already called stop. - } - }; + mNetworkAgent = mDeps.makeEthernetNetworkAgent(mContext, mHandler.getLooper(), + mCapabilities, mLinkProperties, getNetworkScore(), config, + mNetworkFactory.getProvider(), new EthernetNetworkAgent.Callbacks() { + @Override + public void onNetworkUnwanted() { + if (this == mNetworkAgent.getCallbacks()) { + stop(); + } else if (mNetworkAgent != null) { + Log.d(TAG, "Ignoring unwanted as we have a more modern " + + "instance"); + } // Otherwise, we've already called stop. + } + }); mNetworkAgent.register(); mNetworkAgent.markConnected(); } @@ -496,7 +528,7 @@ public class EthernetNetworkFactory extends NetworkFactory { stop(); // If the interface has disappeared provisioning will fail over and over again, so // there is no point in starting again - if (null != InterfaceParams.getByName(name)) { + if (null != mDeps.getNetworkInterfaceByName(name)) { start(); } } @@ -504,7 +536,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void updateLinkProperties(LinkProperties linkProperties) { mLinkProperties = linkProperties; if (mNetworkAgent != null) { - mNetworkAgent.sendLinkProperties(linkProperties); + mNetworkAgent.sendLinkPropertiesImpl(linkProperties); } } @@ -545,7 +577,7 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkProperties); } mNetworkAgent.sendNetworkCapabilities(mCapabilities); - mNetworkAgent.sendLinkProperties(mLinkProperties); + mNetworkAgent.sendLinkPropertiesImpl(mLinkProperties); // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now // since the agent isn't updated frequently. Consider caching the score in the future if diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp index 4b2d270769..1bc9352f9b 100644 --- a/tests/ethernet/Android.bp +++ b/tests/ethernet/Android.bp @@ -28,10 +28,14 @@ android_test { libs: [ "android.test.runner", "android.test.base", + "android.test.mock", ], static_libs: [ "androidx.test.rules", "ethernet-service", + "frameworks-base-testutils", + "mockito-target-minus-junit4", + "services.net", ], } diff --git a/tests/ethernet/AndroidManifest.xml b/tests/ethernet/AndroidManifest.xml index 302bb6c9a1..cd875b0209 100644 --- a/tests/ethernet/AndroidManifest.xml +++ b/tests/ethernet/AndroidManifest.xml @@ -18,7 +18,7 @@ - + diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java new file mode 100644 index 0000000000..cc03ff2817 --- /dev/null +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.ethernet; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.test.MockAnswerUtil.AnswerWithArguments; +import android.content.Context; +import android.content.res.Resources; +import android.net.EthernetNetworkSpecifier; +import android.net.IpConfiguration; +import android.net.LinkProperties; +import android.net.NetworkAgentConfig; +import android.net.NetworkCapabilities; +import android.net.NetworkProvider; +import android.net.NetworkRequest; +import android.net.ip.IIpClient; +import android.net.ip.IpClientCallbacks; +import android.net.util.InterfaceParams; +import android.os.Handler; +import android.os.Looper; +import android.os.test.TestLooper; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.R; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class EthernetNetworkFactoryTest { + private TestLooper mLooper = new TestLooper(); + private Handler mHandler; + private EthernetNetworkFactory mNetFactory = null; + private IpClientCallbacks mIpClientCallbacks; + private int mNetworkRequestCount = 0; + @Mock private Context mContext; + @Mock private Resources mResources; + @Mock private EthernetNetworkFactory.Dependencies mDeps; + @Mock private IIpClient mIpClient; + @Mock private EthernetNetworkAgent mNetworkAgent; + @Mock private InterfaceParams mInterfaceParams; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mHandler = new Handler(mLooper.getLooper()); + mNetworkRequestCount = 0; + + mNetFactory = new EthernetNetworkFactory(mHandler, mContext, createDefaultFilterCaps(), + mDeps); + + setupNetworkAgentMock(); + setupIpClientMock(); + setupContext(); + } + + private void setupNetworkAgentMock() { + when(mDeps.makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), + any())).thenAnswer(new AnswerWithArguments() { + public EthernetNetworkAgent answer( + Context context, + Looper looper, + NetworkCapabilities nc, + LinkProperties lp, + int networkScore, + NetworkAgentConfig config, + NetworkProvider provider, + EthernetNetworkAgent.Callbacks cb) { + when(mNetworkAgent.getCallbacks()).thenReturn(cb); + return mNetworkAgent; + } + } + ); + } + + private void setupIpClientMock() throws Exception { + doAnswer(inv -> { + // these tests only support one concurrent IpClient, so make sure we do not accidentally + // create a mess. + assertNull("An IpClient has already been created.", mIpClientCallbacks); + + mIpClientCallbacks = inv.getArgument(2); + mIpClientCallbacks.onIpClientCreated(mIpClient); + mLooper.dispatchAll(); + return null; + }).when(mDeps).makeIpClient(any(Context.class), anyString(), any()); + + doAnswer(inv -> { + mIpClientCallbacks.onQuit(); + mLooper.dispatchAll(); + mIpClientCallbacks = null; + return null; + }).when(mIpClient).shutdown(); + } + + private void setupContext() { + when(mContext.getResources()).thenReturn(mResources); + when(mResources.getString(R.string.config_ethernet_tcp_buffers)).thenReturn( + "524288,1048576,3145728,524288,1048576,2097152"); + } + + @After + public void tearDown() { + // looper is shared with the network agents, so there may still be messages to dispatch on + // tear down. + mLooper.dispatchAll(); + } + + private NetworkCapabilities createDefaultFilterCaps() { + return NetworkCapabilities.Builder.withoutDefaultCapabilities() + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .build(); + } + + private NetworkCapabilities.Builder createInterfaceCapsBuilder() { + return new NetworkCapabilities.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); + } + + private NetworkRequest.Builder createDefaultRequestBuilder() { + return new NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + } + + private NetworkRequest createDefaultRequest() { + return createDefaultRequestBuilder().build(); + } + + private IpConfiguration createDefaultIpConfig() { + IpConfiguration ipConfig = new IpConfiguration(); + ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP); + ipConfig.setProxySettings(IpConfiguration.ProxySettings.NONE); + return ipConfig; + } + + // creates an interface with provisioning in progress (since updating the interface link state + // automatically starts the provisioning process) + private void createInterfaceUndergoingProvisioning(String iface) throws Exception { + mNetFactory.addInterface(iface, iface, createInterfaceCapsBuilder().build(), + createDefaultIpConfig()); + assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); + verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); + verify(mIpClient).startProvisioning(any()); + clearInvocations(mDeps); + clearInvocations(mIpClient); + } + + // creates a provisioned interface + private void createProvisionedInterface(String iface) throws Exception { + createInterfaceUndergoingProvisioning(iface); + mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); + mLooper.dispatchAll(); + // provisioning succeeded, verify that the network agent is created, registered, and marked + // as connected. + verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), + any()); + verify(mNetworkAgent).register(); + verify(mNetworkAgent).markConnected(); + clearInvocations(mDeps); + clearInvocations(mNetworkAgent); + } + + // creates an unprovisioned interface + private void createUnprovisionedInterface(String iface) throws Exception { + // the only way to create an unprovisioned interface is by calling needNetworkFor + // followed by releaseNetworkFor which will stop the NetworkAgent and IpClient. When + // EthernetNetworkFactory#updateInterfaceLinkState(iface, true) is called, the interface + // is automatically provisioned even if nobody has ever called needNetworkFor + createProvisionedInterface(iface); + + // Interface is already provisioned, so startProvisioning / register should not be called + // again + mNetFactory.needNetworkFor(createDefaultRequest()); + verify(mIpClient, never()).startProvisioning(any()); + verify(mNetworkAgent, never()).register(); + + mNetFactory.releaseNetworkFor(createDefaultRequest()); + verify(mIpClient).shutdown(); + verify(mNetworkAgent).unregister(); + + clearInvocations(mIpClient); + clearInvocations(mNetworkAgent); + } + + @Test + public void testAcceptRequest() throws Exception { + createInterfaceUndergoingProvisioning("eth0"); + assertTrue(mNetFactory.acceptRequest(createDefaultRequest())); + + NetworkRequest wifiRequest = createDefaultRequestBuilder() + .removeTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(); + assertFalse(mNetFactory.acceptRequest(wifiRequest)); + } + + @Test + public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception { + String iface = "eth0"; + createInterfaceUndergoingProvisioning(iface); + // verify that the IpClient gets shut down when interface state changes to down. + assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); + verify(mIpClient).shutdown(); + } + + @Test + public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception { + String iface = "eth0"; + createProvisionedInterface(iface); + assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); + verify(mIpClient).shutdown(); + verify(mNetworkAgent).unregister(); + } + + @Test + public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception { + String iface = "eth0"; + createUnprovisionedInterface(iface); + assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); + // There should not be an active IPClient or NetworkAgent. + verify(mDeps, never()).makeIpClient(any(), any(), any()); + verify(mDeps, never()).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), + any(), any()); + } + + @Test + public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception { + // if interface was never added, link state cannot be updated. + assertFalse(mNetFactory.updateInterfaceLinkState("eth1", true)); + verify(mDeps, never()).makeIpClient(any(), any(), any()); + } + + @Test + public void testNeedNetworkForOnProvisionedInterface() throws Exception { + createProvisionedInterface("eth0"); + mNetFactory.needNetworkFor(createDefaultRequest()); + verify(mIpClient, never()).startProvisioning(any()); + } + + @Test + public void testNeedNetworkForOnUnprovisionedInterface() throws Exception { + createUnprovisionedInterface("eth0"); + mNetFactory.needNetworkFor(createDefaultRequest()); + verify(mIpClient).startProvisioning(any()); + + mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); + mLooper.dispatchAll(); + verify(mNetworkAgent).register(); + verify(mNetworkAgent).markConnected(); + } + + @Test + public void testNeedNetworkForOnInterfaceUndergoingProvisioning() throws Exception { + createInterfaceUndergoingProvisioning("eth0"); + mNetFactory.needNetworkFor(createDefaultRequest()); + verify(mIpClient, never()).startProvisioning(any()); + + mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); + mLooper.dispatchAll(); + verify(mNetworkAgent).register(); + verify(mNetworkAgent).markConnected(); + } + + @Test + public void testProvisioningLoss() throws Exception { + String iface = "eth0"; + when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams); + createProvisionedInterface(iface); + + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + verify(mIpClient).shutdown(); + verify(mNetworkAgent).unregister(); + // provisioning loss should trigger a retry, since the interface is still there + verify(mIpClient).startProvisioning(any()); + } + + @Test + public void testProvisioningLossForDisappearedInterface() throws Exception { + String iface = "eth0"; + // mocked method returns null by default, but just to be explicit in the test: + when(mDeps.getNetworkInterfaceByName(eq(iface))).thenReturn(null); + + createProvisionedInterface(iface); + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + verify(mIpClient).shutdown(); + verify(mNetworkAgent).unregister(); + // the interface disappeared and getNetworkInterfaceByName returns null, we should not retry + verify(mIpClient, never()).startProvisioning(any()); + } + + @Test + public void testIpClientIsNotStartedWhenLinkIsDown() throws Exception { + String iface = "eth0"; + createUnprovisionedInterface(iface); + mNetFactory.updateInterfaceLinkState(iface, false); + + mNetFactory.needNetworkFor(createDefaultRequest()); + + NetworkRequest specificNetRequest = new NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .setNetworkSpecifier(new EthernetNetworkSpecifier(iface)) + .build(); + mNetFactory.needNetworkFor(specificNetRequest); + + // TODO(b/155707957): BUG: IPClient should not be started when the interface link state + // is down. + verify(mDeps).makeIpClient(any(), any(), any()); + } + + @Test + public void testLinkPropertiesChanged() throws Exception { + createProvisionedInterface("eth0"); + + LinkProperties lp = new LinkProperties(); + mIpClientCallbacks.onLinkPropertiesChange(lp); + mLooper.dispatchAll(); + verify(mNetworkAgent).sendLinkPropertiesImpl(same(lp)); + } + + @Test + public void testNetworkUnwanted() throws Exception { + createProvisionedInterface("eth0"); + + mNetworkAgent.getCallbacks().onNetworkUnwanted(); + mLooper.dispatchAll(); + verify(mIpClient).shutdown(); + verify(mNetworkAgent).unregister(); + } + + @Test + public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception { + String iface = "eth0"; + // ensures provisioning is restarted after provisioning loss + when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams); + createProvisionedInterface(iface); + + EthernetNetworkAgent.Callbacks oldCbs = mNetworkAgent.getCallbacks(); + // replace network agent in EthernetNetworkFactory + // Loss of provisioning will restart the ip client and network agent. + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + verify(mDeps).makeIpClient(any(), any(), any()); + + mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); + mLooper.dispatchAll(); + verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), + any()); + + // verify that unwanted is ignored + clearInvocations(mIpClient); + clearInvocations(mNetworkAgent); + oldCbs.onNetworkUnwanted(); + verify(mIpClient, never()).shutdown(); + verify(mNetworkAgent, never()).unregister(); + } +} From 0ba7e4cc58621c9e2e897e9ae6e0ae46ed205f85 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Tue, 1 Jun 2021 09:51:48 +0200 Subject: [PATCH 660/881] Remove Unused Code From EthernetNetworkFactory Test: atest EthernetNetworkFactoryTest Change-Id: Ibe0190b3108dca644da2d67bd107954cb26f41ce --- .../ethernet/EthernetNetworkFactory.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index f4de23d7d3..32dbd7e0b6 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -423,10 +423,6 @@ public class EthernetNetworkFactory extends NetworkFactory { } } - boolean satisfied(NetworkCapabilities requestedCapabilities) { - return requestedCapabilities.satisfiedByNetworkCapabilities(mCapabilities); - } - boolean isRestricted() { return !mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } @@ -569,22 +565,6 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkProperties.clear(); } - private void updateAgent() { - if (mNetworkAgent == null) return; - if (DBG) { - Log.i(TAG, "Updating mNetworkAgent with: " + - mCapabilities + ", " + - mLinkProperties); - } - mNetworkAgent.sendNetworkCapabilities(mCapabilities); - mNetworkAgent.sendLinkPropertiesImpl(mLinkProperties); - - // As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now - // since the agent isn't updated frequently. Consider caching the score in the future if - // agent updating is required more often - mNetworkAgent.sendNetworkScore(getNetworkScore()); - } - private static void provisionIpClient(IIpClient ipClient, IpConfiguration config, String tcpBufferSizes) { if (config.getProxySettings() == ProxySettings.STATIC || From 406fb650d849430b2f38e481262f96f1b2df5483 Mon Sep 17 00:00:00 2001 From: Milim Lee Date: Wed, 28 Apr 2021 13:56:11 +0900 Subject: [PATCH 661/881] Set EthernetNetworkSpecifier on each ethernet network for multi-ethernet Bug: 175199512 Test: Build and test multi-ethernet Change-Id: I6ec50b42bee89520f6f27d40e0d2b0d774b8e2e5 --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index aa80e4de2d..2ddc14eb0c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -146,6 +146,10 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } + capabilities = new NetworkCapabilities.Builder(capabilities) + .setNetworkSpecifier(new EthernetNetworkSpecifier(ifaceName)) + .build(); + if (DBG) { Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities); } From fe1b6f90d7b8fa1bfe9055c67e47e32f87173c97 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 30 Jul 2021 02:31:26 +0000 Subject: [PATCH 662/881] Fix mMobileIfaces is not protected by lock Currently, mMobileIfaces is accessed from multiple threads, and should be protected from concurrent accessing. However, since the variable could be accessed frequently, holding the mStatsLock would make this be blocked by network stats I/O operations. Thus, protect the variable by making it volatile. Test: Wifi on/off stress test Bug: 192758557 Original-Change: https://android-review.googlesource.com/1765686 Merged-In: Ie7694a63f5203ee7c83830ca13d97219b7949fd7 Change-Id: Ie7694a63f5203ee7c83830ca13d97219b7949fd7 --- .../server/net/NetworkStatsService.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 4ee867b7d0..097b0711ef 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -289,8 +289,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private String mActiveIface; /** Set of any ifaces associated with mobile networks since boot. */ - @GuardedBy("mStatsLock") - private String[] mMobileIfaces = new String[0]; + private volatile String[] mMobileIfaces = new String[0]; /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */ @GuardedBy("mStatsLock") @@ -935,7 +934,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public String[] getMobileIfaces() { - return mMobileIfaces; + // TODO (b/192758557): Remove debug log. + if (ArrayUtils.contains(mMobileIfaces, null)) { + throw new NullPointerException( + "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); + } + return mMobileIfaces.clone(); } @Override @@ -1084,7 +1088,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public long getIfaceStats(String iface, int type) { + public long getIfaceStats(@NonNull String iface, int type) { + Objects.requireNonNull(iface); long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); if (nativeIfaceStats == -1) { return nativeIfaceStats; @@ -1382,7 +1387,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]); + mMobileIfaces = mobileIfaces.toArray(new String[0]); + // TODO (b/192758557): Remove debug log. + if (ArrayUtils.contains(mMobileIfaces, null)) { + throw new NullPointerException( + "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); + } } private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { From 10f9bde2395cd89d22310bc8ea16a73857999a4e Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 30 Jul 2021 02:31:26 +0000 Subject: [PATCH 663/881] Add debug log for tracking NPE of mMobileIfaces Test: TH Bug: 192758557 Original-Change: https://android-review.googlesource.com/1777887 Merged-In: Ib048c18b1c64627de5a9d2b04d10e084a014ff64 Change-Id: Ib048c18b1c64627de5a9d2b04d10e084a014ff64 From 2571bf4645c430510a7c93642ef822fa081117d6 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 12 Aug 2021 17:16:51 +0000 Subject: [PATCH 664/881] Revert "Set EthernetNetworkSpecifier on each ethernet network for multi-ethernet" This reverts commit 406fb650d849430b2f38e481262f96f1b2df5483. Reason for revert: b/196387077 Change-Id: I8e27ce915b6069b642c614a018aa5e1788ae07af --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 2ddc14eb0c..aa80e4de2d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -146,10 +146,6 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } - capabilities = new NetworkCapabilities.Builder(capabilities) - .setNetworkSpecifier(new EthernetNetworkSpecifier(ifaceName)) - .build(); - if (DBG) { Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities); } From 073b2d93e0b1e1106d9d2f1bb9361f0717bcb6b4 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Fri, 20 Aug 2021 10:42:52 +0800 Subject: [PATCH 665/881] Add null check for the taken callback The requestTetheredInterface() and releaseTetheredInterface() in EthernetManager is annotated as @NonNull. Basically, the taken callback parameter to the service implementation should also be @NonNull. However, it still possible to use native commands to call the method in the aidl. If a null callback is taken, it may cause unexpected results and cause crashes. Add a null check and throw NPE as a warning. Bug: 190058445 Test: adb commands Change-Id: I18fd63aba3f7326597fc3a8c93ba8c9097bf7348 --- .../src/com/android/server/ethernet/EthernetServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 3fc6aab758..6b0ce32644 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -35,6 +35,7 @@ import com.android.internal.util.IndentingPrintWriter; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -172,6 +173,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void requestTetheredInterface(ITetheredInterfaceCallback callback) { + Objects.requireNonNull(callback, "callback must not be null"); NetworkStack.checkNetworkStackPermissionOr(mContext, android.Manifest.permission.NETWORK_SETTINGS); mTracker.requestTetheredInterface(callback); @@ -179,6 +181,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { + Objects.requireNonNull(callback, "callback must not be null"); NetworkStack.checkNetworkStackPermissionOr(mContext, android.Manifest.permission.NETWORK_SETTINGS); mTracker.releaseTetheredInterface(callback); From 32954f255554c7a0cc7cc71c279623f0f54cece9 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Fri, 20 Aug 2021 07:56:26 +0200 Subject: [PATCH 666/881] prevent nullptr dereference when calling unwanted When the EthernetNetworkAgent has already been stopped, a call to unwanted will cause a crash due to a nullptr derefernce. Bug: 197279734 Test: atest EthernetNetworkFactoryTest Change-Id: Ice39c603bdd3e3139aa8ece7fb897bf7b567e74b --- .../android/server/ethernet/EthernetNetworkFactory.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 32dbd7e0b6..cd086e721f 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -506,12 +506,15 @@ public class EthernetNetworkFactory extends NetworkFactory { mNetworkFactory.getProvider(), new EthernetNetworkAgent.Callbacks() { @Override public void onNetworkUnwanted() { + // if mNetworkAgent is null, we have already called stop. + if (mNetworkAgent == null) return; + if (this == mNetworkAgent.getCallbacks()) { stop(); - } else if (mNetworkAgent != null) { + } else { Log.d(TAG, "Ignoring unwanted as we have a more modern " + "instance"); - } // Otherwise, we've already called stop. + } } }); mNetworkAgent.register(); From 162b047e746e31a74a1944aed9ab52f9f807fb3e Mon Sep 17 00:00:00 2001 From: Tyler Wear Date: Thu, 26 Aug 2021 10:06:28 -0700 Subject: [PATCH 667/881] NetworkStats: Avoid Division By 0 RawBytes should always be at least 1 to avoid division by 0 and ArithmeticException resulting in Settings crash. Bug: 197292638 Change-Id: I4e5ac9da7adf707d7f991483555ab5c6d0cc3245 --- .../java/com/android/server/net/NetworkStatsCollection.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 6aefe41891..a090c1aab6 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -285,7 +285,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W combined.getValues(augmentStart, augmentEnd, entry); } - final long rawBytes = entry.rxBytes + entry.txBytes; + final long rawBytes = (entry.rxBytes + entry.txBytes) == 0 ? 1 : + (entry.rxBytes + entry.txBytes); final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes; final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes; final long targetBytes = augmentPlan.getDataUsageBytes(); From 5a5866cd0b5b2b4fd08166b60d2a5e572ef619cb Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 1 Sep 2021 07:36:14 +0000 Subject: [PATCH 668/881] NetworkStats: Avoid Division By 0 RawBytes should always be at least 1 to avoid division by 0 and ArithmeticException resulting in Settings crash. Bug: 197292638 Change-Id: I4e5ac9da7adf707d7f991483555ab5c6d0cc3245 Merged-In: I4e5ac9da7adf707d7f991483555ab5c6d0cc3245 (cherry picked from commit 93581a034784f7473798e836f52c890a265dfc8b) --- .../java/com/android/server/net/NetworkStatsCollection.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 557fa89444..df372b1459 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -290,7 +290,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W combined.getValues(augmentStart, augmentEnd, entry); } - final long rawBytes = entry.rxBytes + entry.txBytes; + final long rawBytes = (entry.rxBytes + entry.txBytes) == 0 ? 1 : + (entry.rxBytes + entry.txBytes); final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes; final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes; final long targetBytes = augmentPlan.getDataUsageBytes(); From 22694711c785a4c177ef603fe5777f435303a0c5 Mon Sep 17 00:00:00 2001 From: paulhu Date: Wed, 15 Sep 2021 16:53:45 +0800 Subject: [PATCH 669/881] Stop using NetworkStack#checkNetworkStackPermission* Replace them with PermissionUtils.enforceNetworkStackPermission* since those methods are deprecated. Bug: 177187957 Test: atest EthernetServiceTests Change-Id: Ifde4a8898439b86e6cc49b7469787bc5e4a91835 --- .../android/server/ethernet/EthernetServiceImpl.java | 11 +++++------ .../com/android/server/ethernet/EthernetTracker.java | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 6b0ce32644..0d4074ea1a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -22,16 +22,15 @@ import android.net.IEthernetManager; import android.net.IEthernetServiceListener; import android.net.ITetheredInterfaceCallback; import android.net.IpConfiguration; -import android.net.NetworkStack; import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.RemoteException; -import android.provider.Settings; import android.util.Log; import android.util.PrintWriterPrinter; import com.android.internal.util.IndentingPrintWriter; +import com.android.net.module.util.PermissionUtils; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -115,7 +114,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Log.w(TAG, "System isn't ready enough to change ethernet configuration"); } - NetworkStack.checkNetworkStackPermission(mContext); + PermissionUtils.enforceNetworkStackPermission(mContext); if (mTracker.isRestrictedInterface(iface)) { enforceUseRestrictedNetworksPermission(); @@ -166,7 +165,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void setIncludeTestInterfaces(boolean include) { - NetworkStack.checkNetworkStackPermissionOr(mContext, + PermissionUtils.enforceNetworkStackPermissionOr(mContext, android.Manifest.permission.NETWORK_SETTINGS); mTracker.setIncludeTestInterfaces(include); } @@ -174,7 +173,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void requestTetheredInterface(ITetheredInterfaceCallback callback) { Objects.requireNonNull(callback, "callback must not be null"); - NetworkStack.checkNetworkStackPermissionOr(mContext, + PermissionUtils.enforceNetworkStackPermissionOr(mContext, android.Manifest.permission.NETWORK_SETTINGS); mTracker.requestTetheredInterface(callback); } @@ -182,7 +181,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void releaseTetheredInterface(ITetheredInterfaceCallback callback) { Objects.requireNonNull(callback, "callback must not be null"); - NetworkStack.checkNetworkStackPermissionOr(mContext, + PermissionUtils.enforceNetworkStackPermissionOr(mContext, android.Manifest.permission.NETWORK_SETTINGS); mTracker.releaseTetheredInterface(callback); } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index b2b60fcb83..d79c7a9dfd 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -29,7 +29,6 @@ import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; import android.net.NetworkCapabilities; -import android.net.NetworkStack; import android.net.StaticIpConfiguration; import android.os.Handler; import android.os.IBinder; @@ -45,6 +44,7 @@ import android.net.util.NetdService; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.net.module.util.NetdUtils; +import com.android.net.module.util.PermissionUtils; import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; @@ -287,7 +287,7 @@ final class EthernetTracker { InterfaceConfiguration config = null; // Bring up the interface so we get link status indications. try { - NetworkStack.checkNetworkStackPermission(mContext); + PermissionUtils.enforceNetworkStackPermission(mContext); NetdUtils.setInterfaceUp(mNetd, iface); config = mNMService.getInterfaceConfig(iface); } catch (RemoteException | IllegalStateException e) { From da213c052e7b210f83891b36aa748cd7e72f96f0 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 10 Sep 2021 03:20:50 +0800 Subject: [PATCH 670/881] Remove forceAllNetworkTypes from test A test should test the actual behavior as much as possible. However, if the flag is true, matchesMobile/matchesMobileWildcard will always return true regardless of the network type and metered. Thus, remove this flag would be closer to the actual behavior. Bug: 183776809 Test: atest FrameworksNetTests Change-Id: I0907a08ca1dd8a14a738db4057ea5ff6a0cd925a --- core/java/android/net/NetworkTemplate.java | 23 ++-------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 68917a8288..08f75df5d8 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -47,7 +47,6 @@ import android.text.TextUtils; import android.util.BackupUtils; import android.util.Log; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; @@ -151,24 +150,6 @@ public class NetworkTemplate implements Parcelable { } } - private static boolean sForceAllNetworkTypes = false; - - /** - * Results in matching against all mobile network types. - * - *

See {@link #matchesMobile} and {@link matchesMobileWildcard}. - */ - @VisibleForTesting - public static void forceAllNetworkTypes() { - sForceAllNetworkTypes = true; - } - - /** Resets the affect of {@link #forceAllNetworkTypes}. */ - @VisibleForTesting - public static void resetForceAllNetworkTypes() { - sForceAllNetworkTypes = false; - } - /** * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with * the given IMSI. @@ -611,7 +592,7 @@ public class NetworkTemplate implements Parcelable { // Only metered mobile network would be matched regardless of metered filter. // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. // TODO: Respect metered filter and remove mMetered condition. - return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) + return (ident.mType == TYPE_MOBILE && ident.mMetered) && !ArrayUtils.isEmpty(mMatchSubscriberIds) && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) && matchesCollapsedRatType(ident); @@ -726,7 +707,7 @@ public class NetworkTemplate implements Parcelable { if (ident.mType == TYPE_WIMAX) { return true; } else { - return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) + return (ident.mType == TYPE_MOBILE && ident.mMetered) && matchesCollapsedRatType(ident); } } From 81614d90b02392e08a017ec609fa7b415bc49d22 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 10 Sep 2021 03:20:50 +0800 Subject: [PATCH 671/881] Remove forceAllNetworkTypes from test A test should test the actual behavior as much as possible. However, if the flag is true, matchesMobile/matchesMobileWildcard will always return true regardless of the network type and metered. Thus, remove this flag would be closer to the actual behavior. Bug: 183776809 Test: atest FrameworksNetTests Change-Id: I0907a08ca1dd8a14a738db4057ea5ff6a0cd925a Merged-In: I0907a08ca1dd8a14a738db4057ea5ff6a0cd925a --- core/java/android/net/NetworkTemplate.java | 23 ++-------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 249154aa91..e6b5081e39 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -47,7 +47,6 @@ import android.text.TextUtils; import android.util.BackupUtils; import android.util.Log; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; @@ -151,24 +150,6 @@ public class NetworkTemplate implements Parcelable { } } - private static boolean sForceAllNetworkTypes = false; - - /** - * Results in matching against all mobile network types. - * - *

See {@link #matchesMobile} and {@link matchesMobileWildcard}. - */ - @VisibleForTesting - public static void forceAllNetworkTypes() { - sForceAllNetworkTypes = true; - } - - /** Resets the affect of {@link #forceAllNetworkTypes}. */ - @VisibleForTesting - public static void resetForceAllNetworkTypes() { - sForceAllNetworkTypes = false; - } - /** * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with * the given IMSI. @@ -611,7 +592,7 @@ public class NetworkTemplate implements Parcelable { // Only metered mobile network would be matched regardless of metered filter. // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. // TODO: Respect metered filter and remove mMetered condition. - return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) + return (ident.mType == TYPE_MOBILE && ident.mMetered) && !ArrayUtils.isEmpty(mMatchSubscriberIds) && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) && matchesCollapsedRatType(ident); @@ -726,7 +707,7 @@ public class NetworkTemplate implements Parcelable { if (ident.mType == TYPE_WIMAX) { return true; } else { - return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered)) + return (ident.mType == TYPE_MOBILE && ident.mMetered) && matchesCollapsedRatType(ident); } } From e844dbe999dc4bbf0a10046fe00c7793565a6b2c Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 26 Jul 2021 19:49:10 +0800 Subject: [PATCH 672/881] Respect metered filter in matchesMobile* In old design, only metered mobile network would be matched, which means that only metered stats could be read if callers query the mobile stats. Currently, the caller in NetworkPolicyManagerService was updated to use the NetworkTemplate constructor with metered parameter in aosp/1563312 which means that the template will be created by a given meteredness. Thus, the hardcode metered can be removed. Remove the metered check from matches method will cause a different behavior. Therefore, to keep the original behavior, if the match rule is MATCH_MOBILE or MATCH_MOBILE_WILDCARD, it should pass METERED_YES to the constructor to build a metered template. Also, if a caller creates a template by calling the constructor with metered as a parameter, the behavior will also be changed. Therefore, if the caller expects to get metered stats then it should change to pass METERED_YES. If the caller expects to get both metered and unmetered stats then it should remain METERED_ALL and it would be a bug that been fixed by this patch. Bug: 183776809 Bug: 202092687 Test: atest FrameworksNetTests:NetworkStatsServiceTest manually test by generating traffic and check the data counts from "adb shell dumpsys netstats --uid" almost equal to the result from "adb shell cmd stats pull-source 10082" Change-Id: I66dd51b020f6d895cd002acc05bef6b6315cd447 --- core/java/android/net/NetworkTemplate.java | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index e6b5081e39..9efafe41f4 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -168,11 +168,11 @@ public class NetworkTemplate implements Parcelable { @NetworkType int ratType) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } @@ -305,6 +305,7 @@ public class NetworkTemplate implements Parcelable { } } + // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S) @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); @@ -312,9 +313,14 @@ public class NetworkTemplate implements Parcelable { public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { - this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_EXACT); + // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates + // to metered networks. It is now possible to match mobile with any meteredness, but + // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this + //constructor passes METERED_YES for these types. + this(matchRule, subscriberId, matchSubscriberIds, networkId, + (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES + : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, + OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } // TODO: Remove it after updating all of the caller. @@ -589,11 +595,7 @@ public class NetworkTemplate implements Parcelable { // TODO: consider matching against WiMAX subscriber identity return true; } else { - // Only metered mobile network would be matched regardless of metered filter. - // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. - // TODO: Respect metered filter and remove mMetered condition. - return (ident.mType == TYPE_MOBILE && ident.mMetered) - && !ArrayUtils.isEmpty(mMatchSubscriberIds) + return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds) && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) && matchesCollapsedRatType(ident); } @@ -707,8 +709,7 @@ public class NetworkTemplate implements Parcelable { if (ident.mType == TYPE_WIMAX) { return true; } else { - return (ident.mType == TYPE_MOBILE && ident.mMetered) - && matchesCollapsedRatType(ident); + return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident); } } From 0771c88ba9181769ac5b69d6bd74313b557fc7d5 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 27 Jul 2021 17:02:52 +0800 Subject: [PATCH 673/881] Have buildTemplateMobileWithRatType take metered parameter To support unmetered 5g, have buildTemplateMobileWithRatType take metered parameter to build a template which could be used to filter an unmetered network. Bug: 183776809 Test: atest FrameworksNetTests:NetworkStatsServiceTest Change-Id: Ia310d90eceeb572a35ce9518de02b198cae16705 --- core/java/android/net/NetworkTemplate.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 9efafe41f4..fee2e2b274 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -160,19 +160,19 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match cellular networks with the given IMSI and {@code ratType}. - * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering. - * See {@code TelephonyManager.NETWORK_TYPE_*}. + * Template to match cellular networks with the given IMSI, {@code ratType} and + * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when + * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}. */ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, - @NetworkType int ratType) { + @NetworkType int ratType, int metered) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, - METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, - METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } From 88c9babd371c203cbeddca3e51f4072cf1732cc8 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 26 Jul 2021 19:49:10 +0800 Subject: [PATCH 674/881] Respect metered filter in matchesMobile* In old design, only metered mobile network would be matched, which means that only metered stats could be read if callers query the mobile stats. Currently, the caller in NetworkPolicyManagerService was updated to use the NetworkTemplate constructor with metered parameter in aosp/1563312 which means that the template will be created by a given meteredness. Thus, the hardcode metered can be removed. Remove the metered check from matches method will cause a different behavior. Therefore, to keep the original behavior, if the match rule is MATCH_MOBILE or MATCH_MOBILE_WILDCARD, it should pass METERED_YES to the constructor to build a metered template. Also, if a caller creates a template by calling the constructor with metered as a parameter, the behavior will also be changed. Therefore, if the caller expects to get metered stats then it should change to pass METERED_YES. If the caller expects to get both metered and unmetered stats then it should remain METERED_ALL and it would be a bug that been fixed by this patch. Bug: 183776809 Bug: 202092687 Test: atest FrameworksNetTests:NetworkStatsServiceTest manually test by generating traffic and check the data counts from "adb shell dumpsys netstats --uid" almost equal to the result from "adb shell cmd stats pull-source 10082" Change-Id: I66dd51b020f6d895cd002acc05bef6b6315cd447 Merged-In: I66dd51b020f6d895cd002acc05bef6b6315cd447 --- core/java/android/net/NetworkTemplate.java | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 08f75df5d8..73c26277ff 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -168,11 +168,11 @@ public class NetworkTemplate implements Parcelable { @NetworkType int ratType) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, - METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } @@ -305,6 +305,7 @@ public class NetworkTemplate implements Parcelable { } } + // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S) @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); @@ -312,9 +313,14 @@ public class NetworkTemplate implements Parcelable { public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { - this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_EXACT); + // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates + // to metered networks. It is now possible to match mobile with any meteredness, but + // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this + //constructor passes METERED_YES for these types. + this(matchRule, subscriberId, matchSubscriberIds, networkId, + (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES + : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, + OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } // TODO: Remove it after updating all of the caller. @@ -589,11 +595,7 @@ public class NetworkTemplate implements Parcelable { // TODO: consider matching against WiMAX subscriber identity return true; } else { - // Only metered mobile network would be matched regardless of metered filter. - // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650. - // TODO: Respect metered filter and remove mMetered condition. - return (ident.mType == TYPE_MOBILE && ident.mMetered) - && !ArrayUtils.isEmpty(mMatchSubscriberIds) + return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds) && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) && matchesCollapsedRatType(ident); } @@ -707,8 +709,7 @@ public class NetworkTemplate implements Parcelable { if (ident.mType == TYPE_WIMAX) { return true; } else { - return (ident.mType == TYPE_MOBILE && ident.mMetered) - && matchesCollapsedRatType(ident); + return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident); } } From faf2c9e5d62b81cd68bfa5aab9beabe1223275f7 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 27 Jul 2021 17:02:52 +0800 Subject: [PATCH 675/881] Have buildTemplateMobileWithRatType take metered parameter To support unmetered 5g, have buildTemplateMobileWithRatType take metered parameter to build a template which could be used to filter an unmetered network. Bug: 183776809 Test: atest FrameworksNetTests:NetworkStatsServiceTest Change-Id: Ia310d90eceeb572a35ce9518de02b198cae16705 Merged-In: Ia310d90eceeb572a35ce9518de02b198cae16705 --- core/java/android/net/NetworkTemplate.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 73c26277ff..74506dae32 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -160,19 +160,19 @@ public class NetworkTemplate implements Parcelable { } /** - * Template to match cellular networks with the given IMSI and {@code ratType}. - * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering. - * See {@code TelephonyManager.NETWORK_TYPE_*}. + * Template to match cellular networks with the given IMSI, {@code ratType} and + * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when + * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}. */ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, - @NetworkType int ratType) { + @NetworkType int ratType, int metered) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, - METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, - METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } From 0aed3102daff90df6895856fea3511f05bb64057 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 4 May 2021 02:58:04 +0800 Subject: [PATCH 676/881] Adapt NET_CAPABILITY_TEMPORARILY_NOT_METERED in NetworkIdentity NET_CAPABILITY_TEMPORARILY_NOT_METERED is a capability indicates networks are generally metered, but are currently unmetered. NetworkIdentity currently did not consider it which will cause Settings shows high data usage. To exclude unmetered 5g from the metered usage, NetworkIdentity should consider a network with NET_CAPABILITY_TEMPORARILY_NOT_METERED capabilities as not metered. Bug: 183776809 Test: FrameworksNetTests:NetworkIdentityTest Change-Id: Iadbc082b52f16708207e8aecf0904356bc0898ab --- core/java/android/net/NetworkIdentity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 1d07a0330b..eb8f43e3d0 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -220,8 +220,10 @@ public class NetworkIdentity implements Comparable { String networkId = null; boolean roaming = !snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - boolean metered = !snapshot.getNetworkCapabilities().hasCapability( - NetworkCapabilities.NET_CAPABILITY_NOT_METERED); + boolean metered = !(snapshot.getNetworkCapabilities().hasCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_METERED) + || snapshot.getNetworkCapabilities().hasCapability( + NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)); final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities()); From 927a6a7fdcc97d53859da225f07e7807aa4709ae Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 26 Oct 2021 09:00:50 +0000 Subject: [PATCH 677/881] Replace @hide APIs in IpSecService - Replace Slog with Log - Replace Binder.withCleanCallingIdentity with BinderUtils.withCleanCallingIdentity Bug: 204153604 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: I63083b3a4e50afe5154b4e8585d0eee46da819c6 --- services/core/java/com/android/server/IpSecService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java index d6ee95131e..aeb814327e 100644 --- a/services/core/java/com/android/server/IpSecService.java +++ b/services/core/java/com/android/server/IpSecService.java @@ -58,13 +58,13 @@ import android.system.OsConstants; import android.text.TextUtils; import android.util.Log; import android.util.Range; -import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; +import com.android.net.module.util.BinderUtils; import com.android.net.module.util.NetdUtils; import com.android.net.module.util.PermissionUtils; @@ -1056,9 +1056,9 @@ public class IpSecService extends IIpSecService.Stub { public void systemReady() { if (isNetdAlive()) { - Slog.d(TAG, "IpSecService is ready"); + Log.d(TAG, "IpSecService is ready"); } else { - Slog.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!"); + Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!"); } } @@ -1332,7 +1332,7 @@ public class IpSecService extends IIpSecService.Stub { final INetd netd = mSrvConfig.getNetdInstance(); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); - Binder.withCleanCallingIdentity(() -> { + BinderUtils.withCleanCallingIdentity(() -> { NetdUtils.setInterfaceUp(netd, intfName); }); From 1e1cd496f694a7c26d2e38b6d6f0006d9250b469 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Wed, 3 Nov 2021 19:57:54 +0800 Subject: [PATCH 678/881] Fix normalize doesn't work on carrier template From android 12, the subscriberId is being used for different network types. For instances: The TYPE_WIFI with subscriberId means that it is a merged wifi network. The TYPE_CARRIER means that the network associate to specific carrier network (subscriberId). So remove the check "isMatchRuleMobile" and only check whether subscriberId is being used in NetworkTemplate or not. Bug: 194939211 Test: atest -c NetworkTemplateTest Change-Id: I80c9f887cf8b4714716d657da92ed273a532ce27 --- core/java/android/net/NetworkTemplate.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 74506dae32..ee24084e63 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -777,8 +777,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. *

@@ -793,8 +793,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * @@ -806,7 +806,12 @@ public class NetworkTemplate implements Parcelable { * A, but also matches B. */ public static NetworkTemplate normalize(NetworkTemplate template, List mergedList) { - if (!template.isMatchRuleMobile()) return template; + // Now there are several types of network which uses SubscriberId to store network + // information. For instances: + // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network. + // The TYPE_CARRIER means that the network associate to specific carrier network. + + if (template.mSubscriberId == null) return template; for (String[] merged : mergedList) { if (ArrayUtils.contains(merged, template.mSubscriberId)) { From 3d30b93d609a5889a6c8966e04181c71fc589855 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 9 Sep 2021 17:39:05 +0900 Subject: [PATCH 679/881] Remove AsyncChannel usage in NsdManager Replace AsyncChannel with two AIDL interfaces: INsdManagerCallback and INsdServiceConnector. This will be helpful to move NsdManager into a module, avoiding the dependency on the hidden AsyncChannel utility. Bug: 190249673 Test: atest FrameworksNetTests CtsNetTestCases:NsdManagerTest Change-Id: Id9e8feb95cbb5ba16f00893f6c3f37fced3358c1 --- core/java/android/net/nsd/INsdManager.aidl | 13 +- .../android/net/nsd/INsdManagerCallback.aidl | 39 ++ .../android/net/nsd/INsdServiceConnector.aidl | 35 ++ core/java/android/net/nsd/NsdManager.java | 215 +++++---- core/java/android/net/nsd/NsdServiceInfo.aidl | 19 + .../java/com/android/server/NsdService.java | 443 +++++++++++------- 6 files changed, 509 insertions(+), 255 deletions(-) create mode 100644 core/java/android/net/nsd/INsdManagerCallback.aidl create mode 100644 core/java/android/net/nsd/INsdServiceConnector.aidl create mode 100644 core/java/android/net/nsd/NsdServiceInfo.aidl diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl index e9e8935a19..89e9cdbd44 100644 --- a/core/java/android/net/nsd/INsdManager.aidl +++ b/core/java/android/net/nsd/INsdManager.aidl @@ -1,5 +1,5 @@ /** - * Copyright (c) 2012, The Android Open Source Project + * Copyright (c) 2021, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,16 +16,15 @@ package android.net.nsd; +import android.net.nsd.INsdManagerCallback; +import android.net.nsd.INsdServiceConnector; import android.os.Messenger; /** - * Interface that NsdService implements + * Interface that NsdService implements to connect NsdManager clients. * * {@hide} */ -interface INsdManager -{ - @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) - Messenger getMessenger(); - void setEnabled(boolean enable); +interface INsdManager { + INsdServiceConnector connect(INsdManagerCallback cb); } diff --git a/core/java/android/net/nsd/INsdManagerCallback.aidl b/core/java/android/net/nsd/INsdManagerCallback.aidl new file mode 100644 index 0000000000..1a262ec0e9 --- /dev/null +++ b/core/java/android/net/nsd/INsdManagerCallback.aidl @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.nsd; + +import android.os.Messenger; +import android.net.nsd.NsdServiceInfo; + +/** + * Callbacks from NsdService to NsdManager + * @hide + */ +oneway interface INsdManagerCallback { + void onDiscoverServicesStarted(int listenerKey, in NsdServiceInfo info); + void onDiscoverServicesFailed(int listenerKey, int error); + void onServiceFound(int listenerKey, in NsdServiceInfo info); + void onServiceLost(int listenerKey, in NsdServiceInfo info); + void onStopDiscoveryFailed(int listenerKey, int error); + void onStopDiscoverySucceeded(int listenerKey); + void onRegisterServiceFailed(int listenerKey, int error); + void onRegisterServiceSucceeded(int listenerKey, in NsdServiceInfo info); + void onUnregisterServiceFailed(int listenerKey, int error); + void onUnregisterServiceSucceeded(int listenerKey); + void onResolveServiceFailed(int listenerKey, int error); + void onResolveServiceSucceeded(int listenerKey, in NsdServiceInfo info); +} diff --git a/core/java/android/net/nsd/INsdServiceConnector.aidl b/core/java/android/net/nsd/INsdServiceConnector.aidl new file mode 100644 index 0000000000..b06ae55b15 --- /dev/null +++ b/core/java/android/net/nsd/INsdServiceConnector.aidl @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.nsd; + +import android.net.nsd.INsdManagerCallback; +import android.net.nsd.NsdServiceInfo; +import android.os.Messenger; + +/** + * Interface that NsdService implements for each NsdManager client. + * + * {@hide} + */ +interface INsdServiceConnector { + void registerService(int listenerKey, in NsdServiceInfo serviceInfo); + void unregisterService(int listenerKey); + void discoverServices(int listenerKey, in NsdServiceInfo serviceInfo); + void stopDiscovery(int listenerKey); + void resolveService(int listenerKey, in NsdServiceInfo serviceInfo); + void startDaemon(); +} \ No newline at end of file diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java index ae8d010194..6c597e26e0 100644 --- a/core/java/android/net/nsd/NsdManager.java +++ b/core/java/android/net/nsd/NsdManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Android Open Source Project + * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,17 +31,13 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; -import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; -import java.util.concurrent.CountDownLatch; - /** * The Network Service Discovery Manager class provides the API to discover services * on a network. As an example, if device A and device B are connected over a Wi-Fi @@ -234,6 +230,11 @@ public final class NsdManager { /** @hide */ public static final int NATIVE_DAEMON_EVENT = BASE + 26; + /** @hide */ + public static final int REGISTER_CLIENT = BASE + 27; + /** @hide */ + public static final int UNREGISTER_CLIENT = BASE + 28; + /** Dns based service discovery protocol */ public static final int PROTOCOL_DNS_SD = 0x0001; @@ -274,7 +275,7 @@ public final class NsdManager { private static final int FIRST_LISTENER_KEY = 1; - private final INsdManager mService; + private final INsdServiceConnector mService; private final Context mContext; private int mListenerKey = FIRST_LISTENER_KEY; @@ -282,9 +283,7 @@ public final class NsdManager { private final SparseArray mServiceMap = new SparseArray<>(); private final Object mMapLock = new Object(); - private final AsyncChannel mAsyncChannel = new AsyncChannel(); - private ServiceHandler mHandler; - private final CountDownLatch mConnected = new CountDownLatch(1); + private final ServiceHandler mHandler; /** * Create a new Nsd instance. Applications use @@ -295,18 +294,108 @@ public final class NsdManager { * is a system private class. */ public NsdManager(Context context, INsdManager service) { - mService = service; mContext = context; - init(); + + HandlerThread t = new HandlerThread("NsdManager"); + t.start(); + mHandler = new ServiceHandler(t.getLooper()); + + try { + mService = service.connect(new NsdCallbackImpl(mHandler)); + } catch (RemoteException e) { + throw new RuntimeException("Failed to connect to NsdService"); + } + + // Only proactively start the daemon if the target SDK < S, otherwise the internal service + // would automatically start/stop the native daemon as needed. + if (!CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) { + try { + mService.startDaemon(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to proactively start daemon"); + // Continue: the daemon can still be started on-demand later + } + } } - /** - * @hide - */ - @VisibleForTesting - public void disconnect() { - mAsyncChannel.disconnect(); - mHandler.getLooper().quitSafely(); + private static class NsdCallbackImpl extends INsdManagerCallback.Stub { + private final Handler mServHandler; + + NsdCallbackImpl(Handler serviceHandler) { + mServHandler = serviceHandler; + } + + private void sendInfo(int message, int listenerKey, NsdServiceInfo info) { + mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey, info)); + } + + private void sendError(int message, int listenerKey, int error) { + mServHandler.sendMessage(mServHandler.obtainMessage(message, error, listenerKey)); + } + + private void sendNoArg(int message, int listenerKey) { + mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey)); + } + + @Override + public void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) { + sendInfo(DISCOVER_SERVICES_STARTED, listenerKey, info); + } + + @Override + public void onDiscoverServicesFailed(int listenerKey, int error) { + sendError(DISCOVER_SERVICES_FAILED, listenerKey, error); + } + + @Override + public void onServiceFound(int listenerKey, NsdServiceInfo info) { + sendInfo(SERVICE_FOUND, listenerKey, info); + } + + @Override + public void onServiceLost(int listenerKey, NsdServiceInfo info) { + sendInfo(SERVICE_LOST, listenerKey, info); + } + + @Override + public void onStopDiscoveryFailed(int listenerKey, int error) { + sendError(STOP_DISCOVERY_FAILED, listenerKey, error); + } + + @Override + public void onStopDiscoverySucceeded(int listenerKey) { + sendNoArg(STOP_DISCOVERY_SUCCEEDED, listenerKey); + } + + @Override + public void onRegisterServiceFailed(int listenerKey, int error) { + sendError(REGISTER_SERVICE_FAILED, listenerKey, error); + } + + @Override + public void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) { + sendInfo(REGISTER_SERVICE_SUCCEEDED, listenerKey, info); + } + + @Override + public void onUnregisterServiceFailed(int listenerKey, int error) { + sendError(UNREGISTER_SERVICE_FAILED, listenerKey, error); + } + + @Override + public void onUnregisterServiceSucceeded(int listenerKey) { + sendNoArg(UNREGISTER_SERVICE_SUCCEEDED, listenerKey); + } + + @Override + public void onResolveServiceFailed(int listenerKey, int error) { + sendError(RESOLVE_SERVICE_FAILED, listenerKey, error); + } + + @Override + public void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) { + sendInfo(RESOLVE_SERVICE_SUCCEEDED, listenerKey, info); + } } /** @@ -376,19 +465,6 @@ public final class NsdManager { public void handleMessage(Message message) { final int what = message.what; final int key = message.arg2; - switch (what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); - return; - case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: - mConnected.countDown(); - return; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - Log.e(TAG, "Channel lost"); - return; - default: - break; - } final Object listener; final NsdServiceInfo ns; synchronized (mMapLock) { @@ -503,36 +579,6 @@ public final class NsdManager { return s.getServiceType(); } - /** - * Initialize AsyncChannel - */ - private void init() { - final Messenger messenger = getMessenger(); - if (messenger == null) { - fatal("Failed to obtain service Messenger"); - } - HandlerThread t = new HandlerThread("NsdManager"); - t.start(); - mHandler = new ServiceHandler(t.getLooper()); - mAsyncChannel.connect(mContext, mHandler, messenger); - try { - mConnected.await(); - } catch (InterruptedException e) { - fatal("Interrupted wait at init"); - } - if (CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) { - return; - } - // Only proactively start the daemon if the target SDK < S, otherwise the internal service - // would automatically start/stop the native daemon as needed. - mAsyncChannel.sendMessage(DAEMON_STARTUP); - } - - private static void fatal(String msg) { - Log.e(TAG, msg); - throw new RuntimeException(msg); - } - /** * Register a service to be discovered by other services. * @@ -556,7 +602,11 @@ public final class NsdManager { checkServiceInfo(serviceInfo); checkProtocol(protocolType); int key = putListener(listener, serviceInfo); - mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo); + try { + mService.registerService(key, serviceInfo); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -574,7 +624,11 @@ public final class NsdManager { */ public void unregisterService(RegistrationListener listener) { int id = getListenerKey(listener); - mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id); + try { + mService.unregisterService(id); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -613,7 +667,11 @@ public final class NsdManager { s.setServiceType(serviceType); int key = putListener(listener, s); - mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s); + try { + mService.discoverServices(key, s); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -634,7 +692,11 @@ public final class NsdManager { */ public void stopServiceDiscovery(DiscoveryListener listener) { int id = getListenerKey(listener); - mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id); + try { + mService.stopDiscovery(id); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } } /** @@ -649,29 +711,10 @@ public final class NsdManager { public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { checkServiceInfo(serviceInfo); int key = putListener(listener, serviceInfo); - mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo); - } - - /** Internal use only @hide */ - public void setEnabled(boolean enabled) { try { - mService.setEnabled(enabled); + mService.resolveService(key, serviceInfo); } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Get a reference to NsdService handler. This is used to establish - * an AsyncChannel communication with the service - * - * @return Messenger pointing to the NsdService handler - */ - private Messenger getMessenger() { - try { - return mService.getMessenger(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + e.rethrowFromSystemServer(); } } diff --git a/core/java/android/net/nsd/NsdServiceInfo.aidl b/core/java/android/net/nsd/NsdServiceInfo.aidl new file mode 100644 index 0000000000..657bdd1e87 --- /dev/null +++ b/core/java/android/net/nsd/NsdServiceInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.nsd; + +@JavaOnlyStableParcelable parcelable NsdServiceInfo; \ No newline at end of file diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java index c9608a5517..3e0208411c 100644 --- a/services/core/java/com/android/server/NsdService.java +++ b/services/core/java/com/android/server/NsdService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,24 +20,27 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; -import android.net.NetworkStack; import android.net.Uri; import android.net.nsd.INsdManager; +import android.net.nsd.INsdManagerCallback; +import android.net.nsd.INsdServiceConnector; import android.net.nsd.NsdManager; import android.net.nsd.NsdServiceInfo; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.os.Message; -import android.os.Messenger; +import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.Base64; +import android.util.Log; +import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; @@ -72,12 +75,11 @@ public class NsdService extends INsdManager.Stub { /** * Clients receiving asynchronous messages */ - private final HashMap mClients = new HashMap<>(); + private final HashMap mClients = new HashMap<>(); /* A map from unique id to client info */ private final SparseArray mIdToClientInfoMap= new SparseArray<>(); - private final AsyncChannel mReplyChannel = new AsyncChannel(); private final long mCleanupDelayMs; private static final int INVALID_ID = 0; @@ -149,65 +151,66 @@ public class NsdService extends INsdManager.Stub { class DefaultState extends State { @Override public boolean processMessage(Message msg) { - ClientInfo cInfo = null; + final ClientInfo cInfo; + final int clientId = msg.arg2; switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { - AsyncChannel c = (AsyncChannel) msg.obj; - if (DBG) Slog.d(TAG, "New client listening to asynchronous messages"); - c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED); - cInfo = new ClientInfo(c, msg.replyTo); - mClients.put(msg.replyTo, cInfo); - } else { - Slog.e(TAG, "Client connection failure, error=" + msg.arg1); + case NsdManager.REGISTER_CLIENT: + final Pair arg = + (Pair) msg.obj; + final INsdManagerCallback cb = arg.second; + try { + cb.asBinder().linkToDeath(arg.first, 0); + cInfo = new ClientInfo(cb); + mClients.put(arg.first, cInfo); + } catch (RemoteException e) { + Log.w(TAG, "Client " + clientId + " has already died"); } break; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - switch (msg.arg1) { - case AsyncChannel.STATUS_SEND_UNSUCCESSFUL: - Slog.e(TAG, "Send failed, client connection lost"); - break; - case AsyncChannel.STATUS_REMOTE_DISCONNECTION: - if (DBG) Slog.d(TAG, "Client disconnected"); - break; - default: - if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); - break; - } - - cInfo = mClients.get(msg.replyTo); + case NsdManager.UNREGISTER_CLIENT: + final NsdServiceConnector connector = (NsdServiceConnector) msg.obj; + cInfo = mClients.remove(connector); if (cInfo != null) { cInfo.expungeAllRequests(); - mClients.remove(msg.replyTo); if (cInfo.isLegacy()) { mLegacyClientCount -= 1; } } maybeScheduleStop(); break; - case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: - AsyncChannel ac = new AsyncChannel(); - ac.connect(mContext, getHandler(), msg.replyTo); - break; case NsdManager.DISCOVER_SERVICES: - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onDiscoverServicesFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.STOP_DISCOVERY: - replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onStopDiscoveryFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.REGISTER_SERVICE: - replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.UNREGISTER_SERVICE: - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onUnregisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.RESOLVE_SERVICE: - replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + cInfo = getClientInfoForReply(msg); + if (cInfo != null) { + cInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); + } break; case NsdManager.DAEMON_CLEANUP: mDaemon.maybeStop(); @@ -215,7 +218,7 @@ public class NsdService extends INsdManager.Stub { // This event should be only sent by the legacy (target SDK < S) clients. // Mark the sending client as legacy. case NsdManager.DAEMON_STARTUP: - cInfo = mClients.get(msg.replyTo); + cInfo = getClientInfoForReply(msg); if (cInfo != null) { cancelStop(); cInfo.setLegacy(); @@ -230,6 +233,11 @@ public class NsdService extends INsdManager.Stub { } return HANDLED; } + + private ClientInfo getClientInfoForReply(Message msg) { + final ListenerArgs args = (ListenerArgs) msg.obj; + return mClients.get(args.connector); + } } class DisabledState extends State { @@ -289,122 +297,119 @@ public class NsdService extends INsdManager.Stub { @Override public boolean processMessage(Message msg) { - ClientInfo clientInfo; - NsdServiceInfo servInfo; - int id; + final ClientInfo clientInfo; + final int id; + final int clientId = msg.arg2; + final ListenerArgs args; switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: - return NOT_HANDLED; - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: - return NOT_HANDLED; case NsdManager.DISABLE: //TODO: cleanup clients transitionTo(mDisabledState); break; case NsdManager.DISCOVER_SERVICES: if (DBG) Slog.d(TAG, "Discover services"); - servInfo = (NsdServiceInfo) msg.obj; - clientInfo = mClients.get(msg.replyTo); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); if (requestLimitReached(clientInfo)) { - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.FAILURE_MAX_LIMIT); + clientInfo.onDiscoverServicesFailed( + clientId, NsdManager.FAILURE_MAX_LIMIT); break; } maybeStartDaemon(); id = getUniqueId(); - if (discoverServices(id, servInfo.getServiceType())) { + if (discoverServices(id, args.serviceInfo.getServiceType())) { if (DBG) { Slog.d(TAG, "Discover " + msg.arg2 + " " + id + - servInfo.getServiceType()); + args.serviceInfo.getServiceType()); } - storeRequestMap(msg.arg2, id, clientInfo, msg.what); - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo); + storeRequestMap(clientId, id, clientInfo, msg.what); + clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo); } else { stopServiceDiscovery(id); - replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED, + clientInfo.onDiscoverServicesFailed(clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.STOP_DISCOVERY: if (DBG) Slog.d(TAG, "Stop service discovery"); - clientInfo = mClients.get(msg.replyTo); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); try { - id = clientInfo.mClientIds.get(msg.arg2); + id = clientInfo.mClientIds.get(clientId); } catch (NullPointerException e) { - replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onStopDiscoveryFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; } - removeRequestMap(msg.arg2, id, clientInfo); + removeRequestMap(clientId, id, clientInfo); if (stopServiceDiscovery(id)) { - replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED); + clientInfo.onStopDiscoverySucceeded(clientId); } else { - replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onStopDiscoveryFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.REGISTER_SERVICE: if (DBG) Slog.d(TAG, "Register service"); - clientInfo = mClients.get(msg.replyTo); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); if (requestLimitReached(clientInfo)) { - replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_MAX_LIMIT); + clientInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_MAX_LIMIT); break; } maybeStartDaemon(); id = getUniqueId(); - if (registerService(id, (NsdServiceInfo) msg.obj)) { - if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id); - storeRequestMap(msg.arg2, id, clientInfo, msg.what); + if (registerService(id, args.serviceInfo)) { + if (DBG) Slog.d(TAG, "Register " + clientId + " " + id); + storeRequestMap(clientId, id, clientInfo, msg.what); // Return success after mDns reports success } else { unregisterService(id); - replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.UNREGISTER_SERVICE: if (DBG) Slog.d(TAG, "unregister service"); - clientInfo = mClients.get(msg.replyTo); - try { - id = clientInfo.mClientIds.get(msg.arg2); - } catch (NullPointerException e) { - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); + if (clientInfo == null) { + Slog.e(TAG, "Unknown connector in unregistration"); break; } - removeRequestMap(msg.arg2, id, clientInfo); + id = clientInfo.mClientIds.get(clientId); + removeRequestMap(clientId, id, clientInfo); if (unregisterService(id)) { - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED); + clientInfo.onUnregisterServiceSucceeded(clientId); } else { - replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onUnregisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.RESOLVE_SERVICE: if (DBG) Slog.d(TAG, "Resolve service"); - servInfo = (NsdServiceInfo) msg.obj; - clientInfo = mClients.get(msg.replyTo); - + args = (ListenerArgs) msg.obj; + clientInfo = mClients.get(args.connector); if (clientInfo.mResolvedService != null) { - replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_ALREADY_ACTIVE); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_ALREADY_ACTIVE); break; } maybeStartDaemon(); id = getUniqueId(); - if (resolveService(id, servInfo)) { + if (resolveService(id, args.serviceInfo)) { clientInfo.mResolvedService = new NsdServiceInfo(); - storeRequestMap(msg.arg2, id, clientInfo, msg.what); + storeRequestMap(clientId, id, clientInfo, msg.what); } else { - replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } break; case NsdManager.NATIVE_DAEMON_EVENT: @@ -449,30 +454,27 @@ public class NsdService extends INsdManager.Stub { case NativeResponseCode.SERVICE_FOUND: /* NNN uniqueId serviceName regType domain */ servInfo = new NsdServiceInfo(cooked[2], cooked[3]); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0, - clientId, servInfo); + clientInfo.onServiceFound(clientId, servInfo); break; case NativeResponseCode.SERVICE_LOST: /* NNN uniqueId serviceName regType domain */ servInfo = new NsdServiceInfo(cooked[2], cooked[3]); - clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0, - clientId, servInfo); + clientInfo.onServiceLost(clientId, servInfo); break; case NativeResponseCode.SERVICE_DISCOVERY_FAILED: /* NNN uniqueId errorCode */ - clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onDiscoverServicesFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_REGISTERED: /* NNN regId serviceName regType */ servInfo = new NsdServiceInfo(cooked[2], null); - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED, - id, clientId, servInfo); + clientInfo.onRegisterServiceSucceeded(clientId, servInfo); break; case NativeResponseCode.SERVICE_REGISTRATION_FAILED: /* NNN regId errorCode */ - clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onRegisterServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_UPDATED: /* NNN regId */ @@ -511,8 +513,8 @@ public class NsdService extends INsdManager.Stub { if (getAddrInfo(id2, cooked[3])) { storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); } else { - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); clientInfo.mResolvedService = null; } break; @@ -521,26 +523,26 @@ public class NsdService extends INsdManager.Stub { stopResolveService(id); removeRequestMap(clientId, id, clientInfo); clientInfo.mResolvedService = null; - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_GET_ADDR_FAILED: /* NNN resolveId errorCode */ stopGetAddrInfo(id); removeRequestMap(clientId, id, clientInfo); clientInfo.mResolvedService = null; - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: /* NNN resolveId hostname ttl addr */ try { clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED, - 0, clientId, clientInfo.mResolvedService); + clientInfo.onResolveServiceSucceeded( + clientId, clientInfo.mResolvedService); } catch (java.net.UnknownHostException e) { - clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED, - NsdManager.FAILURE_INTERNAL_ERROR, clientId); + clientInfo.onResolveServiceFailed( + clientId, NsdManager.FAILURE_INTERNAL_ERROR); } stopGetAddrInfo(id); removeRequestMap(clientId, id, clientInfo); @@ -601,15 +603,71 @@ public class NsdService extends INsdManager.Stub { return service; } - public Messenger getMessenger() { + @Override + public INsdServiceConnector connect(INsdManagerCallback cb) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService"); - return new Messenger(mNsdStateMachine.getHandler()); + final INsdServiceConnector connector = new NsdServiceConnector(); + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.REGISTER_CLIENT, new Pair<>(connector, cb))); + return connector; } - public void setEnabled(boolean isEnabled) { - NetworkStack.checkNetworkStackPermission(mContext); - mNsdSettings.putEnabledStatus(isEnabled); - notifyEnabled(isEnabled); + private static class ListenerArgs { + public final NsdServiceConnector connector; + public final NsdServiceInfo serviceInfo; + ListenerArgs(NsdServiceConnector connector, NsdServiceInfo serviceInfo) { + this.connector = connector; + this.serviceInfo = serviceInfo; + } + } + + private class NsdServiceConnector extends INsdServiceConnector.Stub + implements IBinder.DeathRecipient { + @Override + public void registerService(int listenerKey, NsdServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.REGISTER_SERVICE, 0, listenerKey, + new ListenerArgs(this, serviceInfo))); + } + + @Override + public void unregisterService(int listenerKey) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.UNREGISTER_SERVICE, 0, listenerKey, + new ListenerArgs(this, null))); + } + + @Override + public void discoverServices(int listenerKey, NsdServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.DISCOVER_SERVICES, 0, listenerKey, + new ListenerArgs(this, serviceInfo))); + } + + @Override + public void stopDiscovery(int listenerKey) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.STOP_DISCOVERY, 0, listenerKey, new ListenerArgs(this, null))); + } + + @Override + public void resolveService(int listenerKey, NsdServiceInfo serviceInfo) { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.RESOLVE_SERVICE, 0, listenerKey, + new ListenerArgs(this, serviceInfo))); + } + + @Override + public void startDaemon() { + mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage( + NsdManager.DAEMON_STARTUP, new ListenerArgs(this, null))); + } + + @Override + public void binderDied() { + mNsdStateMachine.sendMessage( + mNsdStateMachine.obtainMessage(NsdManager.UNREGISTER_CLIENT, this)); + } } private void notifyEnabled(boolean isEnabled) { @@ -832,43 +890,11 @@ public class NsdService extends INsdManager.Stub { mNsdStateMachine.dump(fd, pw, args); } - /* arg2 on the source message has an id that needs to be retained in replies - * see NsdManager for details */ - private Message obtainMessage(Message srcMsg) { - Message msg = Message.obtain(); - msg.arg2 = srcMsg.arg2; - return msg; - } - - private void replyToMessage(Message msg, int what) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, int arg1) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - dstMsg.arg1 = arg1; - mReplyChannel.replyToMessage(msg, dstMsg); - } - - private void replyToMessage(Message msg, int what, Object obj) { - if (msg.replyTo == null) return; - Message dstMsg = obtainMessage(msg); - dstMsg.what = what; - dstMsg.obj = obj; - mReplyChannel.replyToMessage(msg, dstMsg); - } - /* Information tracked per client */ private class ClientInfo { private static final int MAX_LIMIT = 10; - private final AsyncChannel mChannel; - private final Messenger mMessenger; + private final INsdManagerCallback mCb; /* Remembers a resolved service until getaddrinfo completes */ private NsdServiceInfo mResolvedService; @@ -881,17 +907,14 @@ public class NsdService extends INsdManager.Stub { // The target SDK of this client < Build.VERSION_CODES.S private boolean mIsLegacy = false; - private ClientInfo(AsyncChannel c, Messenger m) { - mChannel = c; - mMessenger = m; - if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m); + private ClientInfo(INsdManagerCallback cb) { + mCb = cb; + if (DBG) Slog.d(TAG, "New client"); } @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("mChannel ").append(mChannel).append("\n"); - sb.append("mMessenger ").append(mMessenger).append("\n"); sb.append("mResolvedService ").append(mResolvedService).append("\n"); sb.append("mIsLegacy ").append(mIsLegacy).append("\n"); for(int i = 0; i< mClientIds.size(); i++) { @@ -949,6 +972,102 @@ public class NsdService extends INsdManager.Stub { } return mClientIds.keyAt(idx); } + + void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) { + try { + mCb.onDiscoverServicesStarted(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onDiscoverServicesStarted", e); + } + } + + void onDiscoverServicesFailed(int listenerKey, int error) { + try { + mCb.onDiscoverServicesFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onDiscoverServicesFailed", e); + } + } + + void onServiceFound(int listenerKey, NsdServiceInfo info) { + try { + mCb.onServiceFound(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onServiceFound(", e); + } + } + + void onServiceLost(int listenerKey, NsdServiceInfo info) { + try { + mCb.onServiceLost(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onServiceLost(", e); + } + } + + void onStopDiscoveryFailed(int listenerKey, int error) { + try { + mCb.onStopDiscoveryFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onStopDiscoveryFailed", e); + } + } + + void onStopDiscoverySucceeded(int listenerKey) { + try { + mCb.onStopDiscoverySucceeded(listenerKey); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onStopDiscoverySucceeded", e); + } + } + + void onRegisterServiceFailed(int listenerKey, int error) { + try { + mCb.onRegisterServiceFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onRegisterServiceFailed", e); + } + } + + void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) { + try { + mCb.onRegisterServiceSucceeded(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onRegisterServiceSucceeded", e); + } + } + + void onUnregisterServiceFailed(int listenerKey, int error) { + try { + mCb.onUnregisterServiceFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onUnregisterServiceFailed", e); + } + } + + void onUnregisterServiceSucceeded(int listenerKey) { + try { + mCb.onUnregisterServiceSucceeded(listenerKey); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onUnregisterServiceSucceeded", e); + } + } + + void onResolveServiceFailed(int listenerKey, int error) { + try { + mCb.onResolveServiceFailed(listenerKey, error); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onResolveServiceFailed", e); + } + } + + void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) { + try { + mCb.onResolveServiceSucceeded(listenerKey, info); + } catch (RemoteException e) { + Log.e(TAG, "Error calling onResolveServiceSucceeded", e); + } + } } /** From e6498416d6024bce4048c90deb34f1fd4a5364b4 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Wed, 3 Nov 2021 19:57:54 +0800 Subject: [PATCH 680/881] Fix normalize doesn't work on carrier template From android 12, the subscriberId is being used for different network types. For instances: The TYPE_WIFI with subscriberId means that it is a merged wifi network. The TYPE_CARRIER means that the network associate to specific carrier network (subscriberId). So remove the check "isMatchRuleMobile" and only check whether subscriberId is being used in NetworkTemplate or not. Bug: 194939211 Test: atest -c NetworkTemplateTest Change-Id: I80c9f887cf8b4714716d657da92ed273a532ce27 Merged-In: I80c9f887cf8b4714716d657da92ed273a532ce27 --- core/java/android/net/NetworkTemplate.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 249154aa91..762816dd9f 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -782,8 +782,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. *

@@ -798,8 +798,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * @@ -811,7 +811,12 @@ public class NetworkTemplate implements Parcelable { * A, but also matches B. */ public static NetworkTemplate normalize(NetworkTemplate template, List mergedList) { - if (!template.isMatchRuleMobile()) return template; + // Now there are several types of network which uses SubscriberId to store network + // information. For instances: + // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network. + // The TYPE_CARRIER means that the network associate to specific carrier network. + + if (template.mSubscriberId == null) return template; for (String[] merged : mergedList) { if (ArrayUtils.contains(merged, template.mSubscriberId)) { From 65168935558ca436967b2aa2b5b2dd801ec6b462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Tue, 2 Nov 2021 00:05:55 -0700 Subject: [PATCH 681/881] replace R + 1 with S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: TreeHugger Bug: 170424293 Signed-off-by: Maciej Żenczykowski Change-Id: Ic28aa1a568bbd0b6d4f06abb7294415afd695fff --- core/java/android/net/IpSecAlgorithm.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 7ef5bac092..86052484ea 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -232,11 +232,10 @@ public final class IpSecAlgorithm implements Parcelable { ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_HMAC_SHA512, SDK_VERSION_ZERO); ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_AES_GCM, SDK_VERSION_ZERO); - // STOPSHIP: b/170424293 Use Build.VERSION_CODES.S when it is defined - ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.R + 1); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.R + 1); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.R + 1); - ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.R + 1); + ALGO_TO_REQUIRED_FIRST_SDK.put(CRYPT_AES_CTR, Build.VERSION_CODES.S); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_XCBC, Build.VERSION_CODES.S); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_AES_CMAC, Build.VERSION_CODES.S); + ALGO_TO_REQUIRED_FIRST_SDK.put(AUTH_CRYPT_CHACHA20_POLY1305, Build.VERSION_CODES.S); } private static final Set ENABLED_ALGOS = From 0b99c46bcde8e607d9233c474035da95ab68a6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 14 Apr 2021 06:39:33 -0700 Subject: [PATCH 682/881] remove qtaguid parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes the legacy (and untested) xt_qtaguid non-ebpf code path (ie. dead code). Test: git grep 'QTAGUID_IFACE_STATS|QTAGUID_UID_STATS|parseIfaceStats|parseUidStats' finds nothing Signed-off-by: Maciej Żenczykowski Change-Id: I922910238474f2cfb74eba19b219bc792ce4abc3 --- ...android_server_net_NetworkStatsService.cpp | 109 +----------------- 1 file changed, 3 insertions(+), 106 deletions(-) diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 10b248a70e..6a355e500d 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -38,9 +38,6 @@ using android::bpf::bpfGetIfaceStats; namespace android { -static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt"; -static const char* QTAGUID_UID_STATS = "/proc/net/xt_qtaguid/stats"; - // NOTE: keep these in sync with TrafficStats.java static const uint64_t UNKNOWN = -1; @@ -72,94 +69,10 @@ static uint64_t getStatsType(Stats* stats, StatsType type) { } } -static int parseIfaceStats(const char* iface, Stats* stats) { - FILE *fp = fopen(QTAGUID_IFACE_STATS, "r"); - if (fp == NULL) { - return -1; - } - - char buffer[384]; - char cur_iface[32]; - bool foundTcp = false; - uint64_t rxBytes, rxPackets, txBytes, txPackets, tcpRxPackets, tcpTxPackets; - - while (fgets(buffer, sizeof(buffer), fp) != NULL) { - int matched = sscanf(buffer, "%31s %" SCNu64 " %" SCNu64 " %" SCNu64 - " %" SCNu64 " " "%*u %" SCNu64 " %*u %*u %*u %*u " - "%*u %" SCNu64 " %*u %*u %*u %*u", cur_iface, &rxBytes, - &rxPackets, &txBytes, &txPackets, &tcpRxPackets, &tcpTxPackets); - if (matched >= 5) { - if (matched == 7) { - foundTcp = true; - } - if (!iface || !strcmp(iface, cur_iface)) { - stats->rxBytes += rxBytes; - stats->rxPackets += rxPackets; - stats->txBytes += txBytes; - stats->txPackets += txPackets; - if (matched == 7) { - stats->tcpRxPackets += tcpRxPackets; - stats->tcpTxPackets += tcpTxPackets; - } - } - } - } - - if (!foundTcp) { - stats->tcpRxPackets = UNKNOWN; - stats->tcpTxPackets = UNKNOWN; - } - - if (fclose(fp) != 0) { - return -1; - } - return 0; -} - -static int parseUidStats(const uint32_t uid, Stats* stats) { - FILE *fp = fopen(QTAGUID_UID_STATS, "r"); - if (fp == NULL) { - return -1; - } - - char buffer[384]; - char iface[32]; - uint32_t idx, cur_uid, set; - uint64_t tag, rxBytes, rxPackets, txBytes, txPackets; - - while (fgets(buffer, sizeof(buffer), fp) != NULL) { - if (sscanf(buffer, - "%" SCNu32 " %31s 0x%" SCNx64 " %u %u %" SCNu64 " %" SCNu64 - " %" SCNu64 " %" SCNu64 "", - &idx, iface, &tag, &cur_uid, &set, &rxBytes, &rxPackets, - &txBytes, &txPackets) == 9) { - if (uid == cur_uid && tag == 0L) { - stats->rxBytes += rxBytes; - stats->rxPackets += rxPackets; - stats->txBytes += txBytes; - stats->txPackets += txPackets; - } - } - } - - if (fclose(fp) != 0) { - return -1; - } - return 0; -} - static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) { Stats stats = {}; - if (useBpfStats) { - if (bpfGetIfaceStats(NULL, &stats) == 0) { - return getStatsType(&stats, (StatsType) type); - } else { - return UNKNOWN; - } - } - - if (parseIfaceStats(NULL, &stats) == 0) { + if (bpfGetIfaceStats(NULL, &stats) == 0) { return getStatsType(&stats, (StatsType) type); } else { return UNKNOWN; @@ -175,15 +88,7 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type, Stats stats = {}; - if (useBpfStats) { - if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) { - return getStatsType(&stats, (StatsType) type); - } else { - return UNKNOWN; - } - } - - if (parseIfaceStats(iface8.c_str(), &stats) == 0) { + if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) { return getStatsType(&stats, (StatsType) type); } else { return UNKNOWN; @@ -193,15 +98,7 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type, static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) { Stats stats = {}; - if (useBpfStats) { - if (bpfGetUidStats(uid, &stats) == 0) { - return getStatsType(&stats, (StatsType) type); - } else { - return UNKNOWN; - } - } - - if (parseUidStats(uid, &stats) == 0) { + if (bpfGetUidStats(uid, &stats) == 0) { return getStatsType(&stats, (StatsType) type); } else { return UNKNOWN; From 6976b5996ed4dc0477b5c7dc712a7f83417a0224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 14 Apr 2021 07:34:00 -0700 Subject: [PATCH 683/881] bpf is required - remove checkBpfStatsEnable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: git grep 'nativeGetTotalStat|nativeGetIfaceStat|nativeGetUidStat' - shows all locations have been updated git grep 'checkBpfStatsEnable' - find nothings relevant (just services/art-profile) Signed-off-by: Maciej Żenczykowski Change-Id: Ib584ea57c39d5ab0605787b05133097fd2c82a39 --- .../android/server/net/NetworkStatsService.java | 16 ++++++---------- ...om_android_server_net_NetworkStatsService.cpp | 13 ++++++------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 097b0711ef..e7b768df99 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1084,13 +1084,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) { return UNSUPPORTED; } - return nativeGetUidStat(uid, type, checkBpfStatsEnable()); + return nativeGetUidStat(uid, type); } @Override public long getIfaceStats(@NonNull String iface, int type) { Objects.requireNonNull(iface); - long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); + long nativeIfaceStats = nativeGetIfaceStat(iface, type); if (nativeIfaceStats == -1) { return nativeIfaceStats; } else { @@ -1104,7 +1104,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public long getTotalStats(int type) { - long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable()); + long nativeTotalStats = nativeGetTotalStat(type); if (nativeTotalStats == -1) { return nativeTotalStats; } else { @@ -1137,10 +1137,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - private boolean checkBpfStatsEnable() { - return mUseBpfTrafficStats; - } - /** * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to * reflect current {@link #mPersistThreshold} value. Always defers to @@ -2249,7 +2245,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - private static native long nativeGetTotalStat(int type, boolean useBpfStats); - private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats); - private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats); + private static native long nativeGetTotalStat(int type); + private static native long nativeGetIfaceStat(String iface, int type); + private static native long nativeGetUidStat(int uid, int type); } diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 6a355e500d..5178132e4a 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -69,7 +69,7 @@ static uint64_t getStatsType(Stats* stats, StatsType type) { } } -static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) { +static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) { Stats stats = {}; if (bpfGetIfaceStats(NULL, &stats) == 0) { @@ -79,8 +79,7 @@ static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfS } } -static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type, - jboolean useBpfStats) { +static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) { ScopedUtfChars iface8(env, iface); if (iface8.c_str() == NULL) { return UNKNOWN; @@ -95,7 +94,7 @@ static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type, } } -static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) { +static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) { Stats stats = {}; if (bpfGetUidStats(uid, &stats) == 0) { @@ -106,9 +105,9 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean } static const JNINativeMethod gMethods[] = { - {"nativeGetTotalStat", "(IZ)J", (void*) getTotalStat}, - {"nativeGetIfaceStat", "(Ljava/lang/String;IZ)J", (void*) getIfaceStat}, - {"nativeGetUidStat", "(IIZ)J", (void*) getUidStat}, + {"nativeGetTotalStat", "(I)J", (void*)getTotalStat}, + {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat}, + {"nativeGetUidStat", "(II)J", (void*)getUidStat}, }; int register_android_server_net_NetworkStatsService(JNIEnv* env) { From a2343dcbcc539248a250295fdb126940bdadc67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 14 Apr 2021 08:14:25 -0700 Subject: [PATCH 684/881] bpf is required - remove mUseBpfTrafficStats field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: git grep mUseBpfTrafficStats TreeHugger Signed-off-by: Maciej Żenczykowski Change-Id: I0be3b802e2ebd175b2a58061bf821aba02a8ec8a --- .../core/java/com/android/server/net/NetworkStatsService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index e7b768df99..f4b72a15d0 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -215,8 +215,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final PowerManager.WakeLock mWakeLock; - private final boolean mUseBpfTrafficStats; - private final ContentObserver mContentObserver; private final ContentResolver mContentResolver; @@ -438,7 +436,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers"); mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir"); mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir"); - mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists(); mDeps = Objects.requireNonNull(deps, "missing Dependencies"); final HandlerThread handlerThread = mDeps.makeHandlerThread(); From 79237fad47eaec43905ca083fa2e78f56d3fde2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Wed, 14 Apr 2021 08:22:05 -0700 Subject: [PATCH 685/881] bpf is required so /sys/fs/bpf/map_netd_app_uid_stats_map always exists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (we cannot just remove the argument, since the test code path still goes via the legacy xt_qtaguid code paths with sample data) Test: TreeHugger Signed-off-by: Maciej Żenczykowski Change-Id: I044d0363aaab0dbbb90c40ca466cc48f169d649a --- .../core/java/com/android/server/net/NetworkStatsFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java index 431b00914f..e6433db11d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsFactory.java +++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java @@ -159,7 +159,7 @@ public class NetworkStatsFactory { } public NetworkStatsFactory() { - this(new File("/proc/"), new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists()); + this(new File("/proc/"), true); } @VisibleForTesting From e46f8703e3f5a9c5b69096ae81cdde0f7130ff89 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Wed, 3 Nov 2021 19:57:54 +0800 Subject: [PATCH 686/881] Fix normalize doesn't work on carrier template From android 12, the subscriberId is being used for different network types. For instances: The TYPE_WIFI with subscriberId means that it is a merged wifi network. The TYPE_CARRIER means that the network associate to specific carrier network (subscriberId). So remove the check "isMatchRuleMobile" and only check whether subscriberId is being used in NetworkTemplate or not. Bug: 194939211 Test: atest -c NetworkTemplateTest Change-Id: I80c9f887cf8b4714716d657da92ed273a532ce27 Merged-In: I80c9f887cf8b4714716d657da92ed273a532ce27 (cherry picked from commit e6498416d6024bce4048c90deb34f1fd4a5364b4) Merged-In:I80c9f887cf8b4714716d657da92ed273a532ce27 --- core/java/android/net/NetworkTemplate.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 249154aa91..762816dd9f 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -782,8 +782,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. *

@@ -798,8 +798,8 @@ public class NetworkTemplate implements Parcelable { } /** - * Examine the given template and normalize if it refers to a "merged" - * mobile subscriber. We pick the "lowest" merged subscriber as the primary + * Examine the given template and normalize it. + * We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * @@ -811,7 +811,12 @@ public class NetworkTemplate implements Parcelable { * A, but also matches B. */ public static NetworkTemplate normalize(NetworkTemplate template, List mergedList) { - if (!template.isMatchRuleMobile()) return template; + // Now there are several types of network which uses SubscriberId to store network + // information. For instances: + // The TYPE_WIFI with subscriberId means that it is a merged carrier wifi network. + // The TYPE_CARRIER means that the network associate to specific carrier network. + + if (template.mSubscriberId == null) return template; for (String[] merged : mergedList) { if (ArrayUtils.contains(merged, template.mSubscriberId)) { From 575e81496c9507127a0b2b9a7363f14fb1e8cc9f Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 19 Nov 2021 07:08:10 +0000 Subject: [PATCH 687/881] Clear calling identity when notifying alert/limit reached When the NetworkStatsProvider reports alert/limit reached, NetworkStatsService will relay the event to other services such as NPMS or NMS. The identity should be cleared before calling into other services. Test: TH Bug: 181106917 Change-Id: I2a7b273dc30156a84b30566319894ec3a42d4429 --- .../com/android/server/net/NetworkStatsService.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 097b0711ef..f3bbe7c818 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -150,6 +150,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; +import com.android.net.module.util.BinderUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; @@ -2104,14 +2105,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void notifyAlertReached() throws RemoteException { - mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */); + // This binder object can only have been obtained by a process that holds + // NETWORK_STATS_PROVIDER. Thus, no additional permission check is required. + BinderUtils.withCleanCallingIdentity(() -> + mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */)); } @Override public void notifyWarningOrLimitReached() { Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); - LocalServices.getService(NetworkPolicyManagerInternal.class) - .onStatsProviderWarningOrLimitReached(mTag); + BinderUtils.withCleanCallingIdentity(() -> + LocalServices.getService(NetworkPolicyManagerInternal.class) + .onStatsProviderWarningOrLimitReached(mTag)); } @Override From 4d7813dacc7b68c77361426a74a11c015fdb10bc Mon Sep 17 00:00:00 2001 From: gary-wzl77 Date: Wed, 13 Oct 2021 20:53:00 +0800 Subject: [PATCH 688/881] net: fix NPE when reading IP configurations When the default gateway is not used in IP configurations, for example the gateway info in ip configurations was fed with custom gateway address ``` out.writeUTF(GATEWAY_KEY); out.writeInt(0); // Default route. out.writeInt(1); // Have a gateway. out.writeUTF(staticIpConfiguration.getGateway().getHostAddress()); ``` A NPE occurred. When there is no destination, assume it is default route and use the gateway address in all cases. Test: manual Change-Id: I5904efad5d277de6724f81d99e62c21ff8347caa Signed-off-by: gary-wzl77 --- .../core/java/com/android/server/net/IpConfigStore.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java index df1eb6d9fe..d17dbde496 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/services/core/java/com/android/server/net/IpConfigStore.java @@ -322,8 +322,11 @@ public class IpConfigStore { gateway = InetAddresses.parseNumericAddress(in.readUTF()); } // If the destination is a default IPv4 route, use the gateway - // address unless already set. - if (dest.getAddress() instanceof Inet4Address + // address unless already set. If there is no destination, assume + // it is default route and use the gateway address in all cases. + if (dest == null) { + gatewayAddress = gateway; + } else if (dest.getAddress() instanceof Inet4Address && dest.getPrefixLength() == 0 && gatewayAddress == null) { gatewayAddress = gateway; } else { From d622cde7ee31d5d8f0f3ab4607160932a487f807 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 15 Nov 2021 09:20:37 +0000 Subject: [PATCH 689/881] [MS06] Add carrier template fields into cloud backup/restore NetworkTemplate with MATCH_CARRIER can be created in NPMS, and can be backup by SettingsBackupAgent. However, since the meteredness is not stored in the backup. After incorrectly deducing from match rule, meteredness always becomes METERED_ALL after restoring from backup. This change also adds debug log if any non-persistable template is being backed up. Test: TH, dedicated test is included in the follow-up CL. Bug: 204830222 Change-Id: I865b1d6e571ed998a75b776f01afc7c2534af2dc --- core/java/android/net/NetworkTemplate.java | 48 ++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index ee24084e63..c906a13bf4 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -69,10 +69,18 @@ import java.util.Objects; public class NetworkTemplate implements Parcelable { private static final String TAG = "NetworkTemplate"; + /** + * Initial Version of the backup serializer. + */ + public static final int BACKUP_VERSION_1_INIT = 1; + /** + * Version of the backup serializer that added carrier template support. + */ + public static final int BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE = 2; /** * Current Version of the Backup Serializer. */ - private static final int BACKUP_VERSION = 1; + private static final int BACKUP_VERSION = BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE; public static final int MATCH_MOBILE = 1; public static final int MATCH_WIFI = 4; @@ -285,6 +293,10 @@ public class NetworkTemplate implements Parcelable { private final int mRoaming; private final int mDefaultNetwork; private final int mSubType; + /** + * The subscriber Id match rule defines how the template should match networks with + * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail. + */ private final int mSubscriberIdMatchRule; // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}. @@ -348,7 +360,7 @@ public class NetworkTemplate implements Parcelable { mSubscriberIdMatchRule = subscriberIdMatchRule; checkValidSubscriberIdMatchRule(); if (!isKnownMatchRule(matchRule)) { - Log.e(TAG, "Unknown network template rule " + matchRule + throw new IllegalArgumentException("Unknown network template rule " + matchRule + " will not match any identity."); } } @@ -842,11 +854,17 @@ public class NetworkTemplate implements Parcelable { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); + if (!isPersistable()) { + Log.wtf(TAG, "Trying to backup non-persistable template: " + this); + } + out.writeInt(BACKUP_VERSION); out.writeInt(mMatchRule); BackupUtils.writeString(out, mSubscriberId); BackupUtils.writeString(out, mNetworkId); + out.writeInt(mMetered); + out.writeInt(mSubscriberIdMatchRule); return baos.toByteArray(); } @@ -854,7 +872,7 @@ public class NetworkTemplate implements Parcelable { public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in) throws IOException, BackupUtils.BadVersionException { int version = in.readInt(); - if (version < 1 || version > BACKUP_VERSION) { + if (version < BACKUP_VERSION_1_INIT || version > BACKUP_VERSION) { throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); } @@ -862,11 +880,27 @@ public class NetworkTemplate implements Parcelable { String subscriberId = BackupUtils.readString(in); String networkId = BackupUtils.readString(in); - if (!isKnownMatchRule(matchRule)) { - throw new BackupUtils.BadVersionException( - "Restored network template contains unknown match rule " + matchRule); + final int metered; + final int subscriberIdMatchRule; + if (version >= BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE) { + metered = in.readInt(); + subscriberIdMatchRule = in.readInt(); + } else { + // For backward compatibility, fill the missing filters from match rules. + metered = (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD + || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL; + subscriberIdMatchRule = SUBSCRIBER_ID_MATCH_RULE_EXACT; } - return new NetworkTemplate(matchRule, subscriberId, networkId); + try { + return new NetworkTemplate(matchRule, + subscriberId, new String[] { subscriberId }, + networkId, metered, NetworkStats.ROAMING_ALL, + NetworkStats.DEFAULT_NETWORK_ALL, NetworkTemplate.NETWORK_TYPE_ALL, + NetworkTemplate.OEM_MANAGED_ALL, subscriberIdMatchRule); + } catch (IllegalArgumentException e) { + throw new BackupUtils.BadVersionException( + "Restored network template contains unknown match rule " + matchRule, e); + } } } From 9dbe49f9545f7df550d53dc9b5cb8ad2f0ffb44f Mon Sep 17 00:00:00 2001 From: paulhu Date: Thu, 18 Nov 2021 15:29:03 +0800 Subject: [PATCH 690/881] Centralize nsd associated files Move all nsd associated files include framework, service and test to package/Nsd first. After clear all hidden API dependencies, we can easily migrate these files into connectivity mainline module. Bug: 206893064 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: Id26f471a10fe7882e31ccc2dbb73219461f00dbd --- packages/Nsd/OWNERS | 1 + packages/Nsd/framework/Android.bp | 54 +++++++++++++++++++ .../android/net/nsd/NsdServiceInfo.aidl | 0 .../src}/android/net/nsd/INsdManager.aidl | 0 .../android/net/nsd/INsdManagerCallback.aidl | 0 .../android/net/nsd/INsdServiceConnector.aidl | 0 .../src}/android/net/nsd/NsdManager.java | 0 .../src}/android/net/nsd/NsdServiceInfo.java | 0 packages/Nsd/service/Android.bp | 31 +++++++++++ .../INativeDaemonConnectorCallbacks.java | 0 .../android/server/NativeDaemonConnector.java | 0 .../NativeDaemonConnectorException.java | 0 .../com/android/server/NativeDaemonEvent.java | 0 .../server/NativeDaemonTimeoutException.java | 0 .../src}/com/android/server/NsdService.java | 0 .../server/NativeDaemonConnectorTest.java | 0 16 files changed, 86 insertions(+) create mode 100644 packages/Nsd/OWNERS create mode 100644 packages/Nsd/framework/Android.bp rename {core/java => packages/Nsd/framework/aidl-export}/android/net/nsd/NsdServiceInfo.aidl (100%) rename {core/java => packages/Nsd/framework/src}/android/net/nsd/INsdManager.aidl (100%) rename {core/java => packages/Nsd/framework/src}/android/net/nsd/INsdManagerCallback.aidl (100%) rename {core/java => packages/Nsd/framework/src}/android/net/nsd/INsdServiceConnector.aidl (100%) rename {core/java => packages/Nsd/framework/src}/android/net/nsd/NsdManager.java (100%) rename {core/java => packages/Nsd/framework/src}/android/net/nsd/NsdServiceInfo.java (100%) create mode 100644 packages/Nsd/service/Android.bp rename {services/core/java => packages/Nsd/service/src}/com/android/server/INativeDaemonConnectorCallbacks.java (100%) rename {services/core/java => packages/Nsd/service/src}/com/android/server/NativeDaemonConnector.java (100%) rename {services/core/java => packages/Nsd/service/src}/com/android/server/NativeDaemonConnectorException.java (100%) rename {services/core/java => packages/Nsd/service/src}/com/android/server/NativeDaemonEvent.java (100%) rename {services/core/java => packages/Nsd/service/src}/com/android/server/NativeDaemonTimeoutException.java (100%) rename {services/core/java => packages/Nsd/service/src}/com/android/server/NsdService.java (100%) rename {services/tests/servicestests/src => packages/Nsd/tests/unit/java}/com/android/server/NativeDaemonConnectorTest.java (100%) diff --git a/packages/Nsd/OWNERS b/packages/Nsd/OWNERS new file mode 100644 index 0000000000..4862377852 --- /dev/null +++ b/packages/Nsd/OWNERS @@ -0,0 +1 @@ +file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking \ No newline at end of file diff --git a/packages/Nsd/framework/Android.bp b/packages/Nsd/framework/Android.bp new file mode 100644 index 0000000000..2363a9f8d4 --- /dev/null +++ b/packages/Nsd/framework/Android.bp @@ -0,0 +1,54 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], +} + +filegroup { + name: "framework-connectivity-nsd-internal-sources", + srcs: [ + "src/**/*.java", + "src/**/*.aidl", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-nsd-aidl-export-sources", + srcs: [ + "aidl-export/**/*.aidl", + ], + path: "aidl-export", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-nsd-sources", + srcs: [ + ":framework-connectivity-nsd-internal-sources", + ":framework-connectivity-nsd-aidl-export-sources", + ], + visibility: [ + "//frameworks/base", + ], +} diff --git a/core/java/android/net/nsd/NsdServiceInfo.aidl b/packages/Nsd/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl similarity index 100% rename from core/java/android/net/nsd/NsdServiceInfo.aidl rename to packages/Nsd/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl diff --git a/core/java/android/net/nsd/INsdManager.aidl b/packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl similarity index 100% rename from core/java/android/net/nsd/INsdManager.aidl rename to packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl diff --git a/core/java/android/net/nsd/INsdManagerCallback.aidl b/packages/Nsd/framework/src/android/net/nsd/INsdManagerCallback.aidl similarity index 100% rename from core/java/android/net/nsd/INsdManagerCallback.aidl rename to packages/Nsd/framework/src/android/net/nsd/INsdManagerCallback.aidl diff --git a/core/java/android/net/nsd/INsdServiceConnector.aidl b/packages/Nsd/framework/src/android/net/nsd/INsdServiceConnector.aidl similarity index 100% rename from core/java/android/net/nsd/INsdServiceConnector.aidl rename to packages/Nsd/framework/src/android/net/nsd/INsdServiceConnector.aidl diff --git a/core/java/android/net/nsd/NsdManager.java b/packages/Nsd/framework/src/android/net/nsd/NsdManager.java similarity index 100% rename from core/java/android/net/nsd/NsdManager.java rename to packages/Nsd/framework/src/android/net/nsd/NsdManager.java diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java similarity index 100% rename from core/java/android/net/nsd/NsdServiceInfo.java rename to packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java diff --git a/packages/Nsd/service/Android.bp b/packages/Nsd/service/Android.bp new file mode 100644 index 0000000000..529f58d130 --- /dev/null +++ b/packages/Nsd/service/Android.bp @@ -0,0 +1,31 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package { + // See: http://go/android-license-faq + default_applicable_licenses: ["Android-Apache-2.0"], +} + +filegroup { + name: "services.connectivity-nsd-sources", + srcs: [ + "src/**/*.java", + ], + path: "src", + visibility: [ + "//frameworks/base/services/core", + ], +} diff --git a/services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java b/packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java similarity index 100% rename from services/core/java/com/android/server/INativeDaemonConnectorCallbacks.java rename to packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java similarity index 100% rename from services/core/java/com/android/server/NativeDaemonConnector.java rename to packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java diff --git a/services/core/java/com/android/server/NativeDaemonConnectorException.java b/packages/Nsd/service/src/com/android/server/NativeDaemonConnectorException.java similarity index 100% rename from services/core/java/com/android/server/NativeDaemonConnectorException.java rename to packages/Nsd/service/src/com/android/server/NativeDaemonConnectorException.java diff --git a/services/core/java/com/android/server/NativeDaemonEvent.java b/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java similarity index 100% rename from services/core/java/com/android/server/NativeDaemonEvent.java rename to packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java diff --git a/services/core/java/com/android/server/NativeDaemonTimeoutException.java b/packages/Nsd/service/src/com/android/server/NativeDaemonTimeoutException.java similarity index 100% rename from services/core/java/com/android/server/NativeDaemonTimeoutException.java rename to packages/Nsd/service/src/com/android/server/NativeDaemonTimeoutException.java diff --git a/services/core/java/com/android/server/NsdService.java b/packages/Nsd/service/src/com/android/server/NsdService.java similarity index 100% rename from services/core/java/com/android/server/NsdService.java rename to packages/Nsd/service/src/com/android/server/NsdService.java diff --git a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java b/packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java similarity index 100% rename from services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java rename to packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java From c047d9a273fdcc75a16d2f9ba1332d5fe3b26711 Mon Sep 17 00:00:00 2001 From: paulhu Date: Wed, 17 Nov 2021 09:35:33 +0800 Subject: [PATCH 691/881] Replace @hide APIs NSD associated files are going to move into connectivity mainline module in T, so need convert all hidden APIs to formal API surfaces. - Replace Slog with Log - Remove useless implements Watchdog.Monitor - Replace Build.IS_DEBUGGABLE with Build.isDebuggable() - Replace Preconditions.checkState90 by checking null directly. - Replace Lists.newArrayList() by new ArrayList<>() - Replace DumpUtils.checkDumpPermission() by checking DUMP permission directly. Bug: 206702844 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: I6bc478b852c10591959d9e0615af63e675532abe --- .../android/server/NativeDaemonConnector.java | 43 ++++++------- .../com/android/server/NativeDaemonEvent.java | 15 +++-- .../src/com/android/server/NsdService.java | 60 ++++++++++--------- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java b/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java index eac767f735..02475dd1ea 100644 --- a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java +++ b/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java @@ -26,12 +26,10 @@ import android.os.PowerManager; import android.os.SystemClock; import android.os.SystemProperties; import android.util.LocalLog; -import android.util.Slog; +import android.util.Log; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import com.android.server.power.ShutdownThread; -import com.google.android.collect.Lists; import java.io.FileDescriptor; import java.io.IOException; @@ -40,19 +38,19 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.LinkedList; +import java.util.Objects; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import java.util.LinkedList; -import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; /** * Generic connector class for interfacing with a native daemon which uses the * {@code libsysutils} FrameworkListener protocol. */ -final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor { +final class NativeDaemonConnector implements Runnable, Handler.Callback { private final static boolean VDBG = false; private final String TAG; @@ -107,7 +105,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo /** * Enable Set debugging mode, which causes messages to also be written to both - * {@link Slog} in addition to internal log. + * {@link Log} in addition to internal log. */ public void setDebug(boolean debug) { mDebug = debug; @@ -126,7 +124,9 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo * calls while holding a lock on the given object. */ public void setWarnIfHeld(Object warnIfHeld) { - Preconditions.checkState(mWarnIfHeld == null); + if (mWarnIfHeld != null) { + throw new IllegalStateException("warnIfHeld is already set."); + } mWarnIfHeld = Objects.requireNonNull(warnIfHeld); } @@ -183,7 +183,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo // In order to ensure that unprivileged apps aren't able to impersonate native daemons on // production devices, even if said native daemons ill-advisedly pick a socket name that // starts with __test__, only allow this on debug builds. - if (mSocket.startsWith("__test__") && Build.IS_DEBUGGABLE) { + if (mSocket.startsWith("__test__") && Build.isDebuggable()) { return new LocalSocketAddress(mSocket); } else { return new LocalSocketAddress(mSocket, LocalSocketAddress.Namespace.RESERVED); @@ -375,7 +375,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo try { latch.await(); } catch (InterruptedException e) { - Slog.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e); + Log.wtf(TAG, "Interrupted while waiting for unsolicited response handling", e); } } @@ -462,13 +462,13 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo public NativeDaemonEvent[] executeForList(long timeoutMs, String cmd, Object... args) throws NativeDaemonConnectorException { if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) { - Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x" + Log.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x" + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable()); } final long startTime = SystemClock.elapsedRealtime(); - final ArrayList events = Lists.newArrayList(); + final ArrayList events = new ArrayList<>(); final StringBuilder rawBuilder = new StringBuilder(); final StringBuilder logBuilder = new StringBuilder(); @@ -571,7 +571,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo */ public static class Command { private String mCmd; - private ArrayList mArguments = Lists.newArrayList(); + private ArrayList mArguments = new ArrayList<>(); public Command(String cmd, Object... args) { mCmd = cmd; @@ -586,11 +586,6 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo } } - /** {@inheritDoc} */ - public void monitor() { - synchronized (mDaemonLock) { } - } - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { mLocalLog.dump(fd, pw, args); pw.println(); @@ -598,12 +593,12 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo } private void log(String logstring) { - if (mDebug) Slog.d(TAG, logstring); + if (mDebug) Log.d(TAG, logstring); mLocalLog.log(logstring); } private void loge(String logstring) { - Slog.e(TAG, logstring); + Log.e(TAG, logstring); mLocalLog.log(logstring); } @@ -659,12 +654,12 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo if (found == null) { // didn't find it - make sure our queue isn't too big before adding while (mPendingCmds.size() >= mMaxCount) { - Slog.e("NativeDaemonConnector.ResponseQueue", + Log.e("NativeDaemonConnector.ResponseQueue", "more buffered than allowed: " + mPendingCmds.size() + " >= " + mMaxCount); // let any waiter timeout waiting for this PendingCmd pendingCmd = mPendingCmds.remove(); - Slog.e("NativeDaemonConnector.ResponseQueue", + Log.e("NativeDaemonConnector.ResponseQueue", "Removing request: " + pendingCmd.logCmd + " (" + pendingCmd.cmdNum + ")"); } @@ -706,7 +701,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo result = found.responses.poll(timeoutMs, TimeUnit.MILLISECONDS); } catch (InterruptedException e) {} if (result == null) { - Slog.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response"); + Log.e("NativeDaemonConnector.ResponseQueue", "Timeout waiting for response"); } return result; } diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java b/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java index e6feda3dad..5683694346 100644 --- a/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java +++ b/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java @@ -16,8 +16,7 @@ package com.android.server; -import android.util.Slog; -import com.google.android.collect.Lists; +import android.util.Log; import java.io.FileDescriptor; import java.util.ArrayList; @@ -179,7 +178,7 @@ public class NativeDaemonEvent { * {@link #getMessage()} for any events matching the requested code. */ public static String[] filterMessageList(NativeDaemonEvent[] events, int matchCode) { - final ArrayList result = Lists.newArrayList(); + final ArrayList result = new ArrayList<>(); for (NativeDaemonEvent event : events) { if (event.getCode() == matchCode) { result.add(event.getMessage()); @@ -212,7 +211,7 @@ public class NativeDaemonEvent { int wordEnd = -1; boolean quoted = false; - if (DEBUG_ROUTINE) Slog.e(LOGTAG, "parsing '" + rawEvent + "'"); + if (DEBUG_ROUTINE) Log.e(LOGTAG, "parsing '" + rawEvent + "'"); if (rawEvent.charAt(current) == '\"') { quoted = true; current++; @@ -240,14 +239,14 @@ public class NativeDaemonEvent { word = word.replace("\\\\", "\\"); word = word.replace("\\\"", "\""); - if (DEBUG_ROUTINE) Slog.e(LOGTAG, "found '" + word + "'"); + if (DEBUG_ROUTINE) Log.e(LOGTAG, "found '" + word + "'"); parsed.add(word); // find the beginning of the next word - either of these options int nextSpace = rawEvent.indexOf(' ', current); int nextQuote = rawEvent.indexOf(" \"", current); if (DEBUG_ROUTINE) { - Slog.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote); + Log.e(LOGTAG, "nextSpace=" + nextSpace + ", nextQuote=" + nextQuote); } if (nextQuote > -1 && nextQuote <= nextSpace) { quoted = true; @@ -259,8 +258,8 @@ public class NativeDaemonEvent { } } // else we just start the next word after the current and read til the end if (DEBUG_ROUTINE) { - Slog.e(LOGTAG, "next loop - current=" + current + - ", length=" + length + ", quoted=" + quoted); + Log.e(LOGTAG, "next loop - current=" + current + + ", length=" + length + ", quoted=" + quoted); } } return parsed.toArray(new String[parsed.size()]); diff --git a/packages/Nsd/service/src/com/android/server/NsdService.java b/packages/Nsd/service/src/com/android/server/NsdService.java index 3e0208411c..76ecea726b 100644 --- a/packages/Nsd/service/src/com/android/server/NsdService.java +++ b/packages/Nsd/service/src/com/android/server/NsdService.java @@ -19,6 +19,7 @@ package com.android.server; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.database.ContentObserver; import android.net.Uri; import android.net.nsd.INsdManager; @@ -36,12 +37,10 @@ import android.provider.Settings; import android.util.Base64; import android.util.Log; import android.util.Pair; -import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.DumpUtils; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.net.module.util.DnsSdTxtRecord; @@ -228,7 +227,7 @@ public class NsdService extends INsdManager.Stub { break; case NsdManager.NATIVE_DAEMON_EVENT: default: - Slog.e(TAG, "Unhandled " + msg); + Log.e(TAG, "Unhandled " + msg); return NOT_HANDLED; } return HANDLED; @@ -274,7 +273,7 @@ public class NsdService extends INsdManager.Stub { private boolean requestLimitReached(ClientInfo clientInfo) { if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) { - if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo); + if (DBG) Log.d(TAG, "Exceeded max outstanding requests " + clientInfo); return true; } return false; @@ -307,7 +306,7 @@ public class NsdService extends INsdManager.Stub { transitionTo(mDisabledState); break; case NsdManager.DISCOVER_SERVICES: - if (DBG) Slog.d(TAG, "Discover services"); + if (DBG) Log.d(TAG, "Discover services"); args = (ListenerArgs) msg.obj; clientInfo = mClients.get(args.connector); @@ -321,8 +320,8 @@ public class NsdService extends INsdManager.Stub { id = getUniqueId(); if (discoverServices(id, args.serviceInfo.getServiceType())) { if (DBG) { - Slog.d(TAG, "Discover " + msg.arg2 + " " + id + - args.serviceInfo.getServiceType()); + Log.d(TAG, "Discover " + msg.arg2 + " " + id + + args.serviceInfo.getServiceType()); } storeRequestMap(clientId, id, clientInfo, msg.what); clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo); @@ -333,7 +332,7 @@ public class NsdService extends INsdManager.Stub { } break; case NsdManager.STOP_DISCOVERY: - if (DBG) Slog.d(TAG, "Stop service discovery"); + if (DBG) Log.d(TAG, "Stop service discovery"); args = (ListenerArgs) msg.obj; clientInfo = mClients.get(args.connector); @@ -353,7 +352,7 @@ public class NsdService extends INsdManager.Stub { } break; case NsdManager.REGISTER_SERVICE: - if (DBG) Slog.d(TAG, "Register service"); + if (DBG) Log.d(TAG, "Register service"); args = (ListenerArgs) msg.obj; clientInfo = mClients.get(args.connector); if (requestLimitReached(clientInfo)) { @@ -365,7 +364,7 @@ public class NsdService extends INsdManager.Stub { maybeStartDaemon(); id = getUniqueId(); if (registerService(id, args.serviceInfo)) { - if (DBG) Slog.d(TAG, "Register " + clientId + " " + id); + if (DBG) Log.d(TAG, "Register " + clientId + " " + id); storeRequestMap(clientId, id, clientInfo, msg.what); // Return success after mDns reports success } else { @@ -375,11 +374,11 @@ public class NsdService extends INsdManager.Stub { } break; case NsdManager.UNREGISTER_SERVICE: - if (DBG) Slog.d(TAG, "unregister service"); + if (DBG) Log.d(TAG, "unregister service"); args = (ListenerArgs) msg.obj; clientInfo = mClients.get(args.connector); if (clientInfo == null) { - Slog.e(TAG, "Unknown connector in unregistration"); + Log.e(TAG, "Unknown connector in unregistration"); break; } id = clientInfo.mClientIds.get(clientId); @@ -392,7 +391,7 @@ public class NsdService extends INsdManager.Stub { } break; case NsdManager.RESOLVE_SERVICE: - if (DBG) Slog.d(TAG, "Resolve service"); + if (DBG) Log.d(TAG, "Resolve service"); args = (ListenerArgs) msg.obj; clientInfo = mClients.get(args.connector); @@ -430,7 +429,7 @@ public class NsdService extends INsdManager.Stub { ClientInfo clientInfo = mIdToClientInfoMap.get(id); if (clientInfo == null) { String name = NativeResponseCode.nameOf(code); - Slog.e(TAG, String.format("id %d for %s has no client mapping", id, name)); + Log.e(TAG, String.format("id %d for %s has no client mapping", id, name)); return false; } @@ -441,14 +440,14 @@ public class NsdService extends INsdManager.Stub { // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY, // and we may get in this situation. String name = NativeResponseCode.nameOf(code); - Slog.d(TAG, String.format( + Log.d(TAG, String.format( "Notification %s for listener id %d that is no longer active", name, id)); return false; } if (DBG) { String name = NativeResponseCode.nameOf(code); - Slog.d(TAG, String.format("Native daemon message %s: %s", name, raw)); + Log.d(TAG, String.format("Native daemon message %s: %s", name, raw)); } switch (code) { case NativeResponseCode.SERVICE_FOUND: @@ -492,7 +491,7 @@ public class NsdService extends INsdManager.Stub { ++index; } if (index >= cooked[2].length()) { - Slog.e(TAG, "Invalid service found " + raw); + Log.e(TAG, "Invalid service found " + raw); break; } String name = cooked[2].substring(0, index); @@ -562,13 +561,13 @@ public class NsdService extends INsdManager.Stub { char c = s.charAt(i); if (c == '\\') { if (++i >= s.length()) { - Slog.e(TAG, "Unexpected end of escape sequence in: " + s); + Log.e(TAG, "Unexpected end of escape sequence in: " + s); break; } c = s.charAt(i); if (c != '.' && c != '\\') { if (i + 2 >= s.length()) { - Slog.e(TAG, "Unexpected end of escape sequence in: " + s); + Log.e(TAG, "Unexpected end of escape sequence in: " + s); break; } c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0')); @@ -685,7 +684,7 @@ public class NsdService extends INsdManager.Stub { private boolean isNsdEnabled() { boolean ret = mNsdSettings.isEnabled(); if (DBG) { - Slog.d(TAG, "Network service discovery is " + (ret ? "enabled" : "disabled")); + Log.d(TAG, "Network service discovery is " + (ret ? "enabled" : "disabled")); } return ret; } @@ -795,12 +794,12 @@ public class NsdService extends INsdManager.Stub { */ public boolean execute(Object... args) { if (DBG) { - Slog.d(TAG, "mdnssd " + Arrays.toString(args)); + Log.d(TAG, "mdnssd " + Arrays.toString(args)); } try { mNativeConnector.execute("mdnssd", args); } catch (NativeDaemonConnectorException e) { - Slog.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e); + Log.e(TAG, "Failed to execute mdnssd " + Arrays.toString(args), e); return false; } return true; @@ -831,7 +830,7 @@ public class NsdService extends INsdManager.Stub { private boolean registerService(int regId, NsdServiceInfo service) { if (DBG) { - Slog.d(TAG, "registerService: " + regId + " " + service); + Log.d(TAG, "registerService: " + regId + " " + service); } String name = service.getServiceName(); String type = service.getServiceType(); @@ -880,7 +879,12 @@ public class NsdService extends INsdManager.Stub { @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump " + TAG + + " due to missing android.permission.DUMP permission"); + return; + } for (ClientInfo client : mClients.values()) { pw.println("Client Info"); @@ -909,7 +913,7 @@ public class NsdService extends INsdManager.Stub { private ClientInfo(INsdManagerCallback cb) { mCb = cb; - if (DBG) Slog.d(TAG, "New client"); + if (DBG) Log.d(TAG, "New client"); } @Override @@ -943,8 +947,10 @@ public class NsdService extends INsdManager.Stub { clientId = mClientIds.keyAt(i); globalId = mClientIds.valueAt(i); mIdToClientInfoMap.remove(globalId); - if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId + - " global-ID " + globalId + " type " + mClientRequests.get(clientId)); + if (DBG) { + Log.d(TAG, "Terminating client-ID " + clientId + + " global-ID " + globalId + " type " + mClientRequests.get(clientId)); + } switch (mClientRequests.get(clientId)) { case NsdManager.DISCOVER_SERVICES: stopServiceDiscovery(globalId); From 3279219a5a0e46462b8b5dcfdee269586b2a0ca3 Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 30 Nov 2021 13:31:29 +0800 Subject: [PATCH 692/881] Stop using NSD_ON setting NSD_ON setting has never been set since it created. Besides, CTS tests assume that nsd service is always enabled otherwise the tests will fail. Thus, remove the setting from NsdService which is no need to read/write it and it's also a hidden symbols. Bug: 206702844 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: Id3cef7def96925cec5095e12910e9b97ba7efb11 --- .../src/com/android/server/NsdService.java | 75 +------------------ 1 file changed, 4 insertions(+), 71 deletions(-) diff --git a/packages/Nsd/service/src/com/android/server/NsdService.java b/packages/Nsd/service/src/com/android/server/NsdService.java index 76ecea726b..497107dbf9 100644 --- a/packages/Nsd/service/src/com/android/server/NsdService.java +++ b/packages/Nsd/service/src/com/android/server/NsdService.java @@ -16,12 +16,9 @@ package com.android.server; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.database.ContentObserver; -import android.net.Uri; import android.net.nsd.INsdManager; import android.net.nsd.INsdManagerCallback; import android.net.nsd.INsdServiceConnector; @@ -33,7 +30,6 @@ import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; import android.util.Base64; import android.util.Log; import android.util.Pair; @@ -66,7 +62,6 @@ public class NsdService extends INsdManager.Stub { private static final long CLEANUP_DELAY_MS = 10000; private final Context mContext; - private final NsdSettings mNsdSettings; private final NsdStateMachine mNsdStateMachine; private final DaemonConnection mDaemon; private final NativeCallbackReceiver mDaemonCallback; @@ -121,30 +116,14 @@ public class NsdService extends INsdManager.Stub { this.removeMessages(NsdManager.DAEMON_CLEANUP); } - /** - * Observes the NSD on/off setting, and takes action when changed. - */ - private void registerForNsdSetting() { - final ContentObserver contentObserver = new ContentObserver(this.getHandler()) { - @Override - public void onChange(boolean selfChange) { - notifyEnabled(isNsdEnabled()); - } - }; - - final Uri uri = Settings.Global.getUriFor(Settings.Global.NSD_ON); - mNsdSettings.registerContentObserver(uri, contentObserver); - } - NsdStateMachine(String name, Handler handler) { super(name, handler); addState(mDefaultState); addState(mDisabledState, mDefaultState); addState(mEnabledState, mDefaultState); - State initialState = isNsdEnabled() ? mEnabledState : mDisabledState; + State initialState = mEnabledState; setInitialState(initialState); setLogRecSize(25); - registerForNsdSetting(); } class DefaultState extends State { @@ -580,11 +559,9 @@ public class NsdService extends INsdManager.Stub { } @VisibleForTesting - NsdService(Context ctx, NsdSettings settings, Handler handler, - DaemonConnectionSupplier fn, long cleanupDelayMs) { + NsdService(Context ctx, Handler handler, DaemonConnectionSupplier fn, long cleanupDelayMs) { mCleanupDelayMs = cleanupDelayMs; mContext = ctx; - mNsdSettings = settings; mNsdStateMachine = new NsdStateMachine(TAG, handler); mNsdStateMachine.start(); mDaemonCallback = new NativeCallbackReceiver(); @@ -592,12 +569,11 @@ public class NsdService extends INsdManager.Stub { } public static NsdService create(Context context) throws InterruptedException { - NsdSettings settings = NsdSettings.makeDefault(context); HandlerThread thread = new HandlerThread(TAG); thread.start(); Handler handler = new Handler(thread.getLooper()); - NsdService service = new NsdService(context, settings, handler, - DaemonConnection::new, CLEANUP_DELAY_MS); + NsdService service = + new NsdService(context, handler, DaemonConnection::new, CLEANUP_DELAY_MS); service.mDaemonCallback.awaitConnection(); return service; } @@ -669,10 +645,6 @@ public class NsdService extends INsdManager.Stub { } } - private void notifyEnabled(boolean isEnabled) { - mNsdStateMachine.sendMessage(isEnabled ? NsdManager.ENABLE : NsdManager.DISABLE); - } - private void sendNsdStateChangeBroadcast(boolean isEnabled) { final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); @@ -681,14 +653,6 @@ public class NsdService extends INsdManager.Stub { mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); } - private boolean isNsdEnabled() { - boolean ret = mNsdSettings.isEnabled(); - if (DBG) { - Log.d(TAG, "Network service discovery is " + (ret ? "enabled" : "disabled")); - } - return ret; - } - private int getUniqueId() { if (++mUniqueId == INVALID_ID) return ++mUniqueId; return mUniqueId; @@ -1075,35 +1039,4 @@ public class NsdService extends INsdManager.Stub { } } } - - /** - * Interface which encapsulates dependencies of NsdService that are hard to mock, hard to - * override, or have side effects on global state in unit tests. - */ - @VisibleForTesting - public interface NsdSettings { - boolean isEnabled(); - void putEnabledStatus(boolean isEnabled); - void registerContentObserver(Uri uri, ContentObserver observer); - - static NsdSettings makeDefault(Context context) { - final ContentResolver resolver = context.getContentResolver(); - return new NsdSettings() { - @Override - public boolean isEnabled() { - return Settings.Global.getInt(resolver, Settings.Global.NSD_ON, 1) == 1; - } - - @Override - public void putEnabledStatus(boolean isEnabled) { - Settings.Global.putInt(resolver, Settings.Global.NSD_ON, isEnabled ? 1 : 0); - } - - @Override - public void registerContentObserver(Uri uri, ContentObserver observer) { - resolver.registerContentObserver(uri, false, observer); - } - }; - } - } } From db0b20b2edf21047dab89927e3e7b21ef9b79be2 Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 23 Nov 2021 09:49:22 +0800 Subject: [PATCH 693/881] Remove @hide symbols from NativeDaemonConnector - FgThread is an service internal class that NativeDaemonConnector can not use it after moving into mainline module. Thus, replace it by creating a new thread. - Remove shutting down check because the original problem owner netd isn't used NativeDaemonConnector now. Bug: 206702844 Test: atest FrameworksNetTests CtsNetTestCases Change-Id: Ib2e227ef1e361f96b397abd7c2a88420ad5a2f22 --- .../android/server/NativeDaemonConnector.java | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java b/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java index 02475dd1ea..ec8d7798e1 100644 --- a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java +++ b/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java @@ -20,16 +20,15 @@ import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.Build; import android.os.Handler; +import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.PowerManager; import android.os.SystemClock; -import android.os.SystemProperties; import android.util.LocalLog; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; -import com.android.server.power.ShutdownThread; import java.io.FileDescriptor; import java.io.IOException; @@ -83,13 +82,6 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback { NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket, int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) { - this(callbacks, socket, responseQueueSize, logTag, maxLogSize, wl, - FgThread.get().getLooper()); - } - - NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket, - int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl, - Looper looper) { mCallbacks = callbacks; mSocket = socket; mResponseQueue = new ResponseQueue(responseQueueSize); @@ -97,10 +89,12 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback { if (mWakeLock != null) { mWakeLock.setReferenceCounted(true); } - mLooper = looper; mSequenceNumber = new AtomicInteger(0); TAG = logTag != null ? logTag : "NativeDaemonConnector"; mLocalLog = new LocalLog(maxLogSize); + final HandlerThread thread = new HandlerThread(TAG); + thread.start(); + mLooper = thread.getLooper(); } /** @@ -135,23 +129,15 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback { mCallbackHandler = new Handler(mLooper, this); while (true) { - if (isShuttingDown()) break; try { listenToSocket(); } catch (Exception e) { loge("Error in NativeDaemonConnector: " + e); - if (isShuttingDown()) break; SystemClock.sleep(5000); } } } - private static boolean isShuttingDown() { - String shutdownAct = SystemProperties.get( - ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); - return shutdownAct != null && shutdownAct.length() > 0; - } - @Override public boolean handleMessage(Message msg) { final String event = (String) msg.obj; From 3d9e9bbb3ec66717d0a8a732b86fa4071dd8433a Mon Sep 17 00:00:00 2001 From: James Mattis Date: Sun, 14 Nov 2021 14:38:07 -0800 Subject: [PATCH 694/881] Removing unused int network score from eth factory Hard coded network scores are no longer used however they still exist in EthernetNetworkFactory. This change removes this unused code in favor of the NetworkScore object. Bug: 209679953 Test: m && atest com.android.server.ethernet.EthernetNetworkFactoryTest Change-Id: Ic9035964fc0e0bdf1dbd1ee845ba3293c753dd8d --- .../server/ethernet/EthernetNetworkAgent.java | 4 +- .../ethernet/EthernetNetworkFactory.java | 99 ++++--------------- .../ethernet/EthernetNetworkFactoryTest.java | 16 ++- 3 files changed, 27 insertions(+), 92 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java b/service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java index 5598fc6a11..57fbce7e86 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkAgent.java @@ -22,6 +22,7 @@ import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkProvider; +import android.net.NetworkScore; import android.os.Looper; import android.annotation.NonNull; import android.annotation.Nullable; @@ -41,11 +42,10 @@ public class EthernetNetworkAgent extends NetworkAgent { @NonNull Looper looper, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, - int networkScore, @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider, @NonNull Callbacks cb) { - super(context, looper, TAG, nc, lp, networkScore, config, provider); + super(context, looper, TAG, nc, lp, new NetworkScore.Builder().build(), config, provider); mCallbacks = cb; } diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index cd086e721f..26532d7355 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -79,11 +79,9 @@ public class EthernetNetworkFactory extends NetworkFactory { } public EthernetNetworkAgent makeEthernetNetworkAgent(Context context, Looper looper, - NetworkCapabilities nc, LinkProperties lp, int networkScore, - NetworkAgentConfig config, NetworkProvider provider, - EthernetNetworkAgent.Callbacks cb) { - return new EthernetNetworkAgent(context, looper, nc, lp, networkScore, config, provider, - cb); + NetworkCapabilities nc, LinkProperties lp, NetworkAgentConfig config, + NetworkProvider provider, EthernetNetworkAgent.Callbacks cb) { + return new EthernetNetworkAgent(context, looper, nc, lp, config, provider, cb); } public InterfaceParams getNetworkInterfaceByName(String name) { @@ -293,49 +291,24 @@ public class EthernetNetworkFactory extends NetworkFactory { private @Nullable IpConfiguration mIpConfig; /** - * An object to contain all transport type information, including base network score and - * the legacy transport type it maps to (if any) - */ - private static class TransportInfo { - final int mLegacyType; - final int mScore; - - private TransportInfo(int legacyType, int score) { - mLegacyType = legacyType; - mScore = score; - } - } - - /** - * A map of TRANSPORT_* types to TransportInfo, making scoring and legacy type information - * available for each type an ethernet interface could propagate. + * A map of TRANSPORT_* types to legacy transport types available for each type an ethernet + * interface could propagate. * - * Unfortunately, base scores for the various transports are not yet centrally located. - * They've been lifted from the corresponding NetworkFactory files in the meantime. - * - * Additionally, there are no legacy type equivalents to LOWPAN or WIFI_AWARE. These types - * are set to TYPE_NONE to match the behavior of their own network factories. + * There are no legacy type equivalents to LOWPAN or WIFI_AWARE. These types are set to + * TYPE_NONE to match the behavior of their own network factories. */ - private static final SparseArray sTransports = new SparseArray(); + private static final SparseArray sTransports = new SparseArray(); static { - // LowpanInterfaceTracker.NETWORK_SCORE - sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN, - new TransportInfo(ConnectivityManager.TYPE_NONE, 30)); - // WifiAwareDataPathStateManager.NETWORK_FACTORY_SCORE_AVAIL - sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE, - new TransportInfo(ConnectivityManager.TYPE_NONE, 1)); - // EthernetNetworkFactory.NETWORK_SCORE sTransports.put(NetworkCapabilities.TRANSPORT_ETHERNET, - new TransportInfo(ConnectivityManager.TYPE_ETHERNET, 70)); - // BluetoothTetheringNetworkFactory.NETWORK_SCORE + ConnectivityManager.TYPE_ETHERNET); sTransports.put(NetworkCapabilities.TRANSPORT_BLUETOOTH, - new TransportInfo(ConnectivityManager.TYPE_BLUETOOTH, 69)); - // WifiNetworkFactory.SCORE_FILTER / NetworkAgent.WIFI_BASE_SCORE - sTransports.put(NetworkCapabilities.TRANSPORT_WIFI, - new TransportInfo(ConnectivityManager.TYPE_WIFI, 60)); - // TelephonyNetworkFactory.TELEPHONY_NETWORK_SCORE + ConnectivityManager.TYPE_BLUETOOTH); + sTransports.put(NetworkCapabilities.TRANSPORT_WIFI, ConnectivityManager.TYPE_WIFI); sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR, - new TransportInfo(ConnectivityManager.TYPE_MOBILE, 50)); + ConnectivityManager.TYPE_MOBILE); + sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN, ConnectivityManager.TYPE_NONE); + sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE, + ConnectivityManager.TYPE_NONE); } long refCount = 0; @@ -397,7 +370,7 @@ public class EthernetNetworkFactory extends NetworkFactory { mContext = context; mNetworkFactory = networkFactory; mDeps = deps; - int legacyType = ConnectivityManager.TYPE_NONE; + final int legacyType; int[] transportTypes = mCapabilities.getTransportTypes(); if (transportTypes.length > 0) { @@ -432,40 +405,7 @@ public class EthernetNetworkFactory extends NetworkFactory { * to legacy TYPE_NONE if there is no known conversion */ private static int getLegacyType(int transport) { - TransportInfo transportInfo = sTransports.get(transport, /* if dne */ null); - if (transportInfo != null) { - return transportInfo.mLegacyType; - } - return ConnectivityManager.TYPE_NONE; - } - - /** - * Determines the network score based on the transport associated with the interface. - * Ethernet interfaces could propagate a transport types forward. Since we can't - * get more information about the statuses of the interfaces on the other end of the local - * interface, we'll best-effort assign the score as the base score of the assigned transport - * when the link is up. When the link is down, the score is set to zero. - * - * This function is called with the purpose of assigning and updating the network score of - * the member NetworkAgent. - */ - private int getNetworkScore() { - // never set the network score below 0. - if (!mLinkUp) { - return 0; - } - - int[] transportTypes = mCapabilities.getTransportTypes(); - if (transportTypes.length < 1) { - Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no " - + "transport type associated with it. Score set to zero"); - return 0; - } - TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null); - if (transportInfo != null) { - return transportInfo.mScore; - } - return 0; + return sTransports.get(transport, ConnectivityManager.TYPE_NONE); } private void start() { @@ -502,8 +442,8 @@ public class EthernetNetworkFactory extends NetworkFactory { .setLegacyExtraInfo(mHwAddress) .build(); mNetworkAgent = mDeps.makeEthernetNetworkAgent(mContext, mHandler.getLooper(), - mCapabilities, mLinkProperties, getNetworkScore(), config, - mNetworkFactory.getProvider(), new EthernetNetworkAgent.Callbacks() { + mCapabilities, mLinkProperties, config, mNetworkFactory.getProvider(), + new EthernetNetworkAgent.Callbacks() { @Override public void onNetworkUnwanted() { // if mNetworkAgent is null, we have already called stop. @@ -620,7 +560,6 @@ public class EthernetNetworkFactory extends NetworkFactory { + "hwAddress: " + mHwAddress + ", " + "networkCapabilities: " + mCapabilities + ", " + "networkAgent: " + mNetworkAgent + ", " - + "score: " + getNetworkScore() + ", " + "ipClient: " + mIpClient + "," + "linkProperties: " + mLinkProperties + "}"; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index cc03ff2817..f4bb15ec09 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -20,7 +20,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; @@ -90,14 +89,13 @@ public class EthernetNetworkFactoryTest { } private void setupNetworkAgentMock() { - when(mDeps.makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), - any())).thenAnswer(new AnswerWithArguments() { + when(mDeps.makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any())) + .thenAnswer(new AnswerWithArguments() { public EthernetNetworkAgent answer( Context context, Looper looper, NetworkCapabilities nc, LinkProperties lp, - int networkScore, NetworkAgentConfig config, NetworkProvider provider, EthernetNetworkAgent.Callbacks cb) { @@ -190,8 +188,7 @@ public class EthernetNetworkFactoryTest { mLooper.dispatchAll(); // provisioning succeeded, verify that the network agent is created, registered, and marked // as connected. - verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), - any()); + verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); verify(mNetworkAgent).register(); verify(mNetworkAgent).markConnected(); clearInvocations(mDeps); @@ -256,8 +253,8 @@ public class EthernetNetworkFactoryTest { assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); // There should not be an active IPClient or NetworkAgent. verify(mDeps, never()).makeIpClient(any(), any(), any()); - verify(mDeps, never()).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), - any(), any()); + verify(mDeps, never()) + .makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); } @Test @@ -382,8 +379,7 @@ public class EthernetNetworkFactoryTest { mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); mLooper.dispatchAll(); - verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), - any()); + verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); // verify that unwanted is ignored clearInvocations(mIpClient); From af9daf023dc78f7ebc5900fd8b766e4820a4b5f5 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 7 Dec 2021 15:47:11 -0800 Subject: [PATCH 695/881] Adding test coverage for eth transport overrides Added test coverage regarding how EthernetTracker consumes the xml config as set in config_ethernet_interfaces. Additionally, adding test coverage for transport override functionality in EthernetNetworkFactory. Bug: 206170402 Test: atest com.android.server.ethernet.EthernetTrackerTest && atest com.android.server.ethernet.EthernetNetworkFactoryTest Change-Id: I3d55a230d3f28154ed6fdac6d63ed57bf589d3bd --- .../server/ethernet/EthernetTracker.java | 40 +++++++--- .../ethernet/EthernetNetworkFactoryTest.java | 78 +++++++++++++++---- .../server/ethernet/EthernetTrackerTest.java | 24 ++++++ 3 files changed, 116 insertions(+), 26 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index d79c7a9dfd..86aefbcff2 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -18,6 +18,7 @@ package com.android.server.ethernet; import static android.net.TestNetworkManager.TEST_TAP_PREFIX; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; @@ -453,21 +454,24 @@ final class EthernetTracker { * ;[Network Capabilities];[IP config];[Override Transport]} */ private void parseEthernetConfig(String configString) { - String[] tokens = configString.split(";", /* limit of tokens */ 4); - String name = tokens[0]; - String capabilities = tokens.length > 1 ? tokens[1] : null; - String transport = tokens.length > 3 ? tokens[3] : null; + final EthernetTrackerConfig config = createEthernetTrackerConfig(configString); NetworkCapabilities nc = createNetworkCapabilities( - !TextUtils.isEmpty(capabilities) /* clear default capabilities */, capabilities, - transport).build(); - mNetworkCapabilities.put(name, nc); + !TextUtils.isEmpty(config.mCapabilities) /* clear default capabilities */, + config.mCapabilities, config.mTransport).build(); + mNetworkCapabilities.put(config.mName, nc); - if (tokens.length > 2 && !TextUtils.isEmpty(tokens[2])) { - IpConfiguration ipConfig = parseStaticIpConfiguration(tokens[2]); - mIpConfigurations.put(name, ipConfig); + if (null != config.mIpConfig) { + IpConfiguration ipConfig = parseStaticIpConfiguration(config.mIpConfig); + mIpConfigurations.put(config.mName, ipConfig); } } + @VisibleForTesting + static EthernetTrackerConfig createEthernetTrackerConfig(@NonNull final String configString) { + Objects.requireNonNull(configString, "EthernetTrackerConfig requires non-null config"); + return new EthernetTrackerConfig(configString.split(";", /* limit of tokens */ 4)); + } + private static NetworkCapabilities createDefaultNetworkCapabilities(boolean isTestIface) { NetworkCapabilities.Builder builder = createNetworkCapabilities( false /* clear default capabilities */, null, null) @@ -672,4 +676,20 @@ final class EthernetTracker { mFactory.dump(fd, pw, args); }); } + + @VisibleForTesting + static class EthernetTrackerConfig { + final String mName; + final String mCapabilities; + final String mIpConfig; + final String mTransport; + + EthernetTrackerConfig(@NonNull final String[] tokens) { + Objects.requireNonNull(tokens, "EthernetTrackerConfig requires non-null tokens"); + mName = tokens[0]; + mCapabilities = tokens.length > 1 ? tokens[1] : null; + mIpConfig = tokens.length > 2 && !TextUtils.isEmpty(tokens[2]) ? tokens[2] : null; + mTransport = tokens.length > 3 ? tokens[3] : null; + } + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index f4bb15ec09..0cd9c1811e 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.clearInvocations; @@ -29,9 +30,11 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.NonNull; import android.app.test.MockAnswerUtil.AnswerWithArguments; import android.content.Context; import android.content.res.Resources; +import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; import android.net.IpConfiguration; import android.net.LinkProperties; @@ -145,9 +148,9 @@ public class EthernetNetworkFactoryTest { .build(); } - private NetworkCapabilities.Builder createInterfaceCapsBuilder() { + private NetworkCapabilities.Builder createInterfaceCapsBuilder(final int transportType) { return new NetworkCapabilities.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .addTransportType(transportType) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); } @@ -172,7 +175,13 @@ public class EthernetNetworkFactoryTest { // creates an interface with provisioning in progress (since updating the interface link state // automatically starts the provisioning process) private void createInterfaceUndergoingProvisioning(String iface) throws Exception { - mNetFactory.addInterface(iface, iface, createInterfaceCapsBuilder().build(), + // Default to the ethernet transport type. + createInterfaceUndergoingProvisioning(iface, NetworkCapabilities.TRANSPORT_ETHERNET); + } + + private void createInterfaceUndergoingProvisioning( + @NonNull final String iface, final int transportType) throws Exception { + mNetFactory.addInterface(iface, iface, createInterfaceCapsBuilder(transportType).build(), createDefaultIpConfig()); assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); @@ -182,13 +191,22 @@ public class EthernetNetworkFactoryTest { } // creates a provisioned interface - private void createProvisionedInterface(String iface) throws Exception { - createInterfaceUndergoingProvisioning(iface); + private void createAndVerifyProvisionedInterface(String iface) throws Exception { + // Default to the ethernet transport type. + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_ETHERNET, + ConnectivityManager.TYPE_ETHERNET); + } + + private void createAndVerifyProvisionedInterface( + @NonNull final String iface, final int transportType, final int expectedLegacyType) + throws Exception { + createInterfaceUndergoingProvisioning(iface, transportType); mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); mLooper.dispatchAll(); - // provisioning succeeded, verify that the network agent is created, registered, and marked - // as connected. - verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); + // provisioning succeeded, verify that the network agent is created, registered, marked + // as connected and legacy type are correctly set. + verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), + argThat(x -> x.getLegacyType() == expectedLegacyType), any(), any()); verify(mNetworkAgent).register(); verify(mNetworkAgent).markConnected(); clearInvocations(mDeps); @@ -201,7 +219,7 @@ public class EthernetNetworkFactoryTest { // followed by releaseNetworkFor which will stop the NetworkAgent and IpClient. When // EthernetNetworkFactory#updateInterfaceLinkState(iface, true) is called, the interface // is automatically provisioned even if nobody has ever called needNetworkFor - createProvisionedInterface(iface); + createAndVerifyProvisionedInterface(iface); // Interface is already provisioned, so startProvisioning / register should not be called // again @@ -240,7 +258,7 @@ public class EthernetNetworkFactoryTest { @Test public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception { String iface = "eth0"; - createProvisionedInterface(iface); + createAndVerifyProvisionedInterface(iface); assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); verify(mIpClient).shutdown(); verify(mNetworkAgent).unregister(); @@ -266,7 +284,7 @@ public class EthernetNetworkFactoryTest { @Test public void testNeedNetworkForOnProvisionedInterface() throws Exception { - createProvisionedInterface("eth0"); + createAndVerifyProvisionedInterface("eth0"); mNetFactory.needNetworkFor(createDefaultRequest()); verify(mIpClient, never()).startProvisioning(any()); } @@ -299,7 +317,7 @@ public class EthernetNetworkFactoryTest { public void testProvisioningLoss() throws Exception { String iface = "eth0"; when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams); - createProvisionedInterface(iface); + createAndVerifyProvisionedInterface(iface); mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); mLooper.dispatchAll(); @@ -315,7 +333,7 @@ public class EthernetNetworkFactoryTest { // mocked method returns null by default, but just to be explicit in the test: when(mDeps.getNetworkInterfaceByName(eq(iface))).thenReturn(null); - createProvisionedInterface(iface); + createAndVerifyProvisionedInterface(iface); mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); mLooper.dispatchAll(); verify(mIpClient).shutdown(); @@ -345,7 +363,7 @@ public class EthernetNetworkFactoryTest { @Test public void testLinkPropertiesChanged() throws Exception { - createProvisionedInterface("eth0"); + createAndVerifyProvisionedInterface("eth0"); LinkProperties lp = new LinkProperties(); mIpClientCallbacks.onLinkPropertiesChange(lp); @@ -355,7 +373,7 @@ public class EthernetNetworkFactoryTest { @Test public void testNetworkUnwanted() throws Exception { - createProvisionedInterface("eth0"); + createAndVerifyProvisionedInterface("eth0"); mNetworkAgent.getCallbacks().onNetworkUnwanted(); mLooper.dispatchAll(); @@ -368,7 +386,7 @@ public class EthernetNetworkFactoryTest { String iface = "eth0"; // ensures provisioning is restarted after provisioning loss when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams); - createProvisionedInterface(iface); + createAndVerifyProvisionedInterface(iface); EthernetNetworkAgent.Callbacks oldCbs = mNetworkAgent.getCallbacks(); // replace network agent in EthernetNetworkFactory @@ -388,4 +406,32 @@ public class EthernetNetworkFactoryTest { verify(mIpClient, never()).shutdown(); verify(mNetworkAgent, never()).unregister(); } + + @Test + public void testTransportOverrideIsCorrectlySet() throws Exception { + final String iface = "eth0"; + // createProvisionedInterface() has verifications in place for transport override + // functionality which for EthernetNetworkFactory is network score and legacy type mappings. + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_ETHERNET, + ConnectivityManager.TYPE_ETHERNET); + mNetFactory.removeInterface(iface); + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_BLUETOOTH, + ConnectivityManager.TYPE_BLUETOOTH); + mNetFactory.removeInterface(iface); + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_WIFI, + ConnectivityManager.TYPE_WIFI); + mNetFactory.removeInterface(iface); + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_CELLULAR, + ConnectivityManager.TYPE_MOBILE); + mNetFactory.removeInterface(iface); + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_LOWPAN, + ConnectivityManager.TYPE_NONE); + mNetFactory.removeInterface(iface); + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_WIFI_AWARE, + ConnectivityManager.TYPE_NONE); + mNetFactory.removeInterface(iface); + createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_TEST, + ConnectivityManager.TYPE_NONE); + mNetFactory.removeInterface(iface); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index ee9f349a28..6ea2154337 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -17,6 +17,7 @@ package com.android.server.ethernet; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import android.net.InetAddresses; @@ -242,4 +243,27 @@ public class EthernetTrackerTest { EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies, configTransports).build()); } + + @Test + public void testCreateEthernetTrackerConfigReturnsCorrectValue() { + final String name = "1"; + final String capabilities = "2"; + final String ipConfig = "3"; + final String transport = "4"; + final String configString = String.join(";", name, capabilities, ipConfig, transport); + + final EthernetTracker.EthernetTrackerConfig config = + EthernetTracker.createEthernetTrackerConfig(configString); + + assertEquals(name, config.mName); + assertEquals(capabilities, config.mCapabilities); + assertEquals(ipConfig, config.mIpConfig); + assertEquals(transport, config.mTransport); + } + + @Test + public void testCreateEthernetTrackerConfigThrowsNpeWithNullInput() { + assertThrows(NullPointerException.class, + () -> EthernetTracker.createEthernetTrackerConfig(null)); + } } From 874001496b9375b255f4ddca309439cee54da849 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 8 Dec 2021 15:24:57 +0800 Subject: [PATCH 696/881] Move f/b/packages/Nsd files to f/b/packages/ConnectivityT Move Nsd files to ConnectivityT so that nsd, ipsec, ethernet and netstats files can live in the same directory and it will be easier to move everything in frameworks/base/packages/ConnectivityT to packages/modules/Connectivity after fixing all of the hidden API usages. Bug: 204153604 Test: FrameworksNetTests CtsNetTestCases Change-Id: I411e242e8739d15920cfc2fe274115f7f39bd89f --- packages/Nsd/framework/Android.bp => framework-t/Sources.bp | 0 .../src/android/net/nsd/INsdManager.aidl | 0 .../src/android/net/nsd/INsdManagerCallback.aidl | 0 .../src/android/net/nsd/INsdServiceConnector.aidl | 0 .../src/android/net/nsd/NsdManager.java | 0 .../src/android/net/nsd/NsdServiceInfo.java | 0 .../aidl-export/android/net/nsd/NsdServiceInfo.aidl | 0 packages/Nsd/OWNERS | 1 - packages/Nsd/service/Android.bp => service-t/Sources.bp | 0 .../src/com/android/server/INativeDaemonConnectorCallbacks.java | 0 .../src/com/android/server/NativeDaemonConnector.java | 0 .../src/com/android/server/NativeDaemonConnectorException.java | 0 .../src/com/android/server/NativeDaemonEvent.java | 0 .../src/com/android/server/NativeDaemonTimeoutException.java | 0 .../service => service-t}/src/com/android/server/NsdService.java | 0 .../unit/java/com/android/server/NativeDaemonConnectorTest.java | 0 16 files changed, 1 deletion(-) rename packages/Nsd/framework/Android.bp => framework-t/Sources.bp (100%) rename {packages/Nsd/framework => framework-t}/src/android/net/nsd/INsdManager.aidl (100%) rename {packages/Nsd/framework => framework-t}/src/android/net/nsd/INsdManagerCallback.aidl (100%) rename {packages/Nsd/framework => framework-t}/src/android/net/nsd/INsdServiceConnector.aidl (100%) rename {packages/Nsd/framework => framework-t}/src/android/net/nsd/NsdManager.java (100%) rename {packages/Nsd/framework => framework-t}/src/android/net/nsd/NsdServiceInfo.java (100%) rename {packages/Nsd/framework => framework}/aidl-export/android/net/nsd/NsdServiceInfo.aidl (100%) delete mode 100644 packages/Nsd/OWNERS rename packages/Nsd/service/Android.bp => service-t/Sources.bp (100%) rename {packages/Nsd/service => service-t}/src/com/android/server/INativeDaemonConnectorCallbacks.java (100%) rename {packages/Nsd/service => service-t}/src/com/android/server/NativeDaemonConnector.java (100%) rename {packages/Nsd/service => service-t}/src/com/android/server/NativeDaemonConnectorException.java (100%) rename {packages/Nsd/service => service-t}/src/com/android/server/NativeDaemonEvent.java (100%) rename {packages/Nsd/service => service-t}/src/com/android/server/NativeDaemonTimeoutException.java (100%) rename {packages/Nsd/service => service-t}/src/com/android/server/NsdService.java (100%) rename {packages/Nsd/tests => tests}/unit/java/com/android/server/NativeDaemonConnectorTest.java (100%) diff --git a/packages/Nsd/framework/Android.bp b/framework-t/Sources.bp similarity index 100% rename from packages/Nsd/framework/Android.bp rename to framework-t/Sources.bp diff --git a/packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl b/framework-t/src/android/net/nsd/INsdManager.aidl similarity index 100% rename from packages/Nsd/framework/src/android/net/nsd/INsdManager.aidl rename to framework-t/src/android/net/nsd/INsdManager.aidl diff --git a/packages/Nsd/framework/src/android/net/nsd/INsdManagerCallback.aidl b/framework-t/src/android/net/nsd/INsdManagerCallback.aidl similarity index 100% rename from packages/Nsd/framework/src/android/net/nsd/INsdManagerCallback.aidl rename to framework-t/src/android/net/nsd/INsdManagerCallback.aidl diff --git a/packages/Nsd/framework/src/android/net/nsd/INsdServiceConnector.aidl b/framework-t/src/android/net/nsd/INsdServiceConnector.aidl similarity index 100% rename from packages/Nsd/framework/src/android/net/nsd/INsdServiceConnector.aidl rename to framework-t/src/android/net/nsd/INsdServiceConnector.aidl diff --git a/packages/Nsd/framework/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java similarity index 100% rename from packages/Nsd/framework/src/android/net/nsd/NsdManager.java rename to framework-t/src/android/net/nsd/NsdManager.java diff --git a/packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java b/framework-t/src/android/net/nsd/NsdServiceInfo.java similarity index 100% rename from packages/Nsd/framework/src/android/net/nsd/NsdServiceInfo.java rename to framework-t/src/android/net/nsd/NsdServiceInfo.java diff --git a/packages/Nsd/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl b/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl similarity index 100% rename from packages/Nsd/framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl rename to framework/aidl-export/android/net/nsd/NsdServiceInfo.aidl diff --git a/packages/Nsd/OWNERS b/packages/Nsd/OWNERS deleted file mode 100644 index 4862377852..0000000000 --- a/packages/Nsd/OWNERS +++ /dev/null @@ -1 +0,0 @@ -file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking \ No newline at end of file diff --git a/packages/Nsd/service/Android.bp b/service-t/Sources.bp similarity index 100% rename from packages/Nsd/service/Android.bp rename to service-t/Sources.bp diff --git a/packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java b/service-t/src/com/android/server/INativeDaemonConnectorCallbacks.java similarity index 100% rename from packages/Nsd/service/src/com/android/server/INativeDaemonConnectorCallbacks.java rename to service-t/src/com/android/server/INativeDaemonConnectorCallbacks.java diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java b/service-t/src/com/android/server/NativeDaemonConnector.java similarity index 100% rename from packages/Nsd/service/src/com/android/server/NativeDaemonConnector.java rename to service-t/src/com/android/server/NativeDaemonConnector.java diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonConnectorException.java b/service-t/src/com/android/server/NativeDaemonConnectorException.java similarity index 100% rename from packages/Nsd/service/src/com/android/server/NativeDaemonConnectorException.java rename to service-t/src/com/android/server/NativeDaemonConnectorException.java diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java b/service-t/src/com/android/server/NativeDaemonEvent.java similarity index 100% rename from packages/Nsd/service/src/com/android/server/NativeDaemonEvent.java rename to service-t/src/com/android/server/NativeDaemonEvent.java diff --git a/packages/Nsd/service/src/com/android/server/NativeDaemonTimeoutException.java b/service-t/src/com/android/server/NativeDaemonTimeoutException.java similarity index 100% rename from packages/Nsd/service/src/com/android/server/NativeDaemonTimeoutException.java rename to service-t/src/com/android/server/NativeDaemonTimeoutException.java diff --git a/packages/Nsd/service/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java similarity index 100% rename from packages/Nsd/service/src/com/android/server/NsdService.java rename to service-t/src/com/android/server/NsdService.java diff --git a/packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java b/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java similarity index 100% rename from packages/Nsd/tests/unit/java/com/android/server/NativeDaemonConnectorTest.java rename to tests/unit/java/com/android/server/NativeDaemonConnectorTest.java From 635e46a2a06416e813d3f81fb913ab3fbfb0d428 Mon Sep 17 00:00:00 2001 From: Zhomart Mukhamejanov Date: Thu, 9 Dec 2021 21:25:48 -0800 Subject: [PATCH 697/881] Add javadoc to NetworkStats related classes. Bug: n/a Test: n/a Change-Id: If7f4d68ea89adbcbc02c1e0a06a11f6330f5d8f3 --- core/java/android/net/INetworkStatsSession.aidl | 12 +++++++++++- core/java/android/net/NetworkStats.java | 4 +++- core/java/android/net/NetworkStatsHistory.java | 12 ++++++++++++ .../android/server/net/NetworkStatsCollection.java | 13 +++++++++---- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl index f13f2cb664..dfedf6633d 100644 --- a/core/java/android/net/INetworkStatsSession.aidl +++ b/core/java/android/net/INetworkStatsSession.aidl @@ -33,7 +33,17 @@ interface INetworkStatsSession { @UnsupportedAppUsage NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields); - /** Return network layer usage summary per UID for traffic that matches template. */ + /** + * Return network layer usage summary per UID for traffic that matches template. + * + *

The resulting {@code NetworkStats#getElapsedRealtime()} contains time delta between + * {@code start} and {@code end}. + * + * @param template - a predicate to filter netstats. + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param includeTags - includes data usage tags if true. + */ @UnsupportedAppUsage NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags); /** Return historical network layer stats for specific UID traffic that matches template. */ diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 46c83df96b..c7ffc19338 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -220,8 +220,10 @@ public final class NetworkStats implements Parcelable { // TODO: move fields to "mVariable" notation /** - * {@link SystemClock#elapsedRealtime()} timestamp when this data was + * {@link SystemClock#elapsedRealtime()} timestamp in milliseconds when this data was * generated. + * It's a timestamps delta when {@link #subtract()}, + * {@code INetworkStatsSession#getSummaryForAllUid()} methods are used. */ private long elapsedRealtime; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index f41306301d..a875e1ad45 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -526,6 +526,13 @@ public class NetworkStatsHistory implements Parcelable { /** * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. + * + *

If the active bucket is not completed yet, it returns the proportional value of it + * based on its duration and the {@code end} param. + * + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param recycle - entry instance for performance, could be null. */ @UnsupportedAppUsage public Entry getValues(long start, long end, Entry recycle) { @@ -535,6 +542,11 @@ public class NetworkStatsHistory implements Parcelable { /** * Return interpolated data usage across the requested range. Interpolates * across buckets, so values may be rounded slightly. + * + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param now - current timestamp in milliseconds since the epoch (wall clock). + * @param recycle - entry instance for performance, could be null. */ @UnsupportedAppUsage public Entry getValues(long start, long end, long now, Entry recycle) { diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index df372b1459..213ea402f5 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -59,16 +59,15 @@ import com.android.internal.util.FastDataOutput; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; -import libcore.io.IoUtils; - import com.google.android.collect.Lists; import com.google.android.collect.Maps; +import libcore.io.IoUtils; + import java.io.BufferedInputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; -import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -335,7 +334,13 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** * Summarize all {@link NetworkStatsHistory} in this collection which match - * the requested parameters. + * the requested parameters across the requested range. + * + * @param template - a predicate for filtering netstats. + * @param start - start of the range, timestamp in milliseconds since the epoch. + * @param end - end of the range, timestamp in milliseconds since the epoch. + * @param accessLevel - caller access level. + * @param callerUid - caller UID. */ public NetworkStats getSummary(NetworkTemplate template, long start, long end, @NetworkStatsAccess.Level int accessLevel, int callerUid) { From 8074ed308bafdbc868406aa9aae3ec466685a755 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 7 Dec 2021 08:25:31 +0000 Subject: [PATCH 698/881] [MS08] Move NetworkStats files to f/b/package/ConnectivityT NetworkStatsService is going to be moved into ConnectivityService module. Move all related files to packages/ConnectivityT so that it can be easily migrate these files to connectivity module after clearing the hidden API usages. Bug: 197717846 Test: TH Change-Id: Iead00832b5eb7b1dc40a92027c5a14ae8316b16c --- framework-t/Sources.bp | 68 +++++++++++++++++-- .../src}/android/app/usage/NetworkStats.java | 0 .../app/usage/NetworkStatsManager.java | 0 .../src}/android/net/DataUsageRequest.aidl | 0 .../src}/android/net/DataUsageRequest.java | 0 .../android/net/INetworkStatsService.aidl | 0 .../android/net/INetworkStatsSession.aidl | 0 .../src}/android/net/NetworkIdentity.java | 0 .../android/net/NetworkStateSnapshot.java | 0 .../src}/android/net/NetworkStats.java | 0 .../src}/android/net/NetworkStatsHistory.aidl | 0 .../src}/android/net/NetworkStatsHistory.java | 0 .../src}/android/net/NetworkTemplate.java | 0 .../src}/android/net/TrafficStats.java | 0 .../android/net/UnderlyingNetworkInfo.aidl | 0 .../android/net/UnderlyingNetworkInfo.java | 0 .../provider/INetworkStatsProvider.aidl | 0 .../INetworkStatsProviderCallback.aidl | 0 .../provider/NetworkStatsProvider.java | 0 .../android/net/NetworkStats.aidl | 0 .../android/net/NetworkTemplate.aidl | 0 service-t/Sources.bp | 36 +++++++++- .../server/net/NetworkIdentitySet.java | 0 .../server/net/NetworkStatsAccess.java | 0 .../server/net/NetworkStatsCollection.java | 0 .../server/net/NetworkStatsFactory.java | 0 .../server/net/NetworkStatsObservers.java | 0 .../server/net/NetworkStatsRecorder.java | 0 .../server/net/NetworkStatsService.java | 0 .../net/NetworkStatsSubscriptionsMonitor.java | 0 30 files changed, 98 insertions(+), 6 deletions(-) rename {core/java => framework-t/src}/android/app/usage/NetworkStats.java (100%) rename {core/java => framework-t/src}/android/app/usage/NetworkStatsManager.java (100%) rename {core/java => framework-t/src}/android/net/DataUsageRequest.aidl (100%) rename {core/java => framework-t/src}/android/net/DataUsageRequest.java (100%) rename {core/java => framework-t/src}/android/net/INetworkStatsService.aidl (100%) rename {core/java => framework-t/src}/android/net/INetworkStatsSession.aidl (100%) rename {core/java => framework-t/src}/android/net/NetworkIdentity.java (100%) rename {core/java => framework-t/src}/android/net/NetworkStateSnapshot.java (100%) rename {core/java => framework-t/src}/android/net/NetworkStats.java (100%) rename {core/java => framework-t/src}/android/net/NetworkStatsHistory.aidl (100%) rename {core/java => framework-t/src}/android/net/NetworkStatsHistory.java (100%) rename {core/java => framework-t/src}/android/net/NetworkTemplate.java (100%) rename {core/java => framework-t/src}/android/net/TrafficStats.java (100%) rename {core/java => framework-t/src}/android/net/UnderlyingNetworkInfo.aidl (100%) rename {core/java => framework-t/src}/android/net/UnderlyingNetworkInfo.java (100%) rename {core/java => framework-t/src}/android/net/netstats/provider/INetworkStatsProvider.aidl (100%) rename {core/java => framework-t/src}/android/net/netstats/provider/INetworkStatsProviderCallback.aidl (100%) rename {core/java => framework-t/src}/android/net/netstats/provider/NetworkStatsProvider.java (100%) rename {core/java => framework/aidl-export}/android/net/NetworkStats.aidl (100%) rename {core/java => framework/aidl-export}/android/net/NetworkTemplate.aidl (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkIdentitySet.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkStatsAccess.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkStatsCollection.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkStatsFactory.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkStatsObservers.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkStatsRecorder.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkStatsService.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/NetworkStatsSubscriptionsMonitor.java (100%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 2363a9f8d4..9c07f399f9 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -19,11 +19,58 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +// NetworkStats related libraries. + +filegroup { + name: "framework-connectivity-netstats-internal-sources", + srcs: [ + "src/android/app/usage/*.java", + "src/android/net/DataUsage*.*", + "src/android/net/INetworkStats*.*", + "src/android/net/NetworkIdentity*.java", + "src/android/net/NetworkStateSnapshot.*", + "src/android/net/NetworkStats*.*", + "src/android/net/NetworkTemplate.*", + "src/android/net/TrafficStats.java", + "src/android/net/UnderlyingNetworkInfo.*", + "src/android/net/netstats/**/*.*", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-netstats-aidl-export-sources", + srcs: [ + "aidl-export/android/net/NetworkStats.aidl", + "aidl-export/android/net/NetworkTemplate.aidl", + ], + path: "aidl-export", + visibility: [ + "//visibility:private", + ], +} + +filegroup { + name: "framework-connectivity-netstats-sources", + srcs: [ + ":framework-connectivity-netstats-internal-sources", + ":framework-connectivity-netstats-aidl-export-sources", + ], + visibility: [ + "//visibility:private", + ], +} + +// Nsd related libraries. + filegroup { name: "framework-connectivity-nsd-internal-sources", srcs: [ - "src/**/*.java", - "src/**/*.aidl", + "src/android/net/nsd/*.aidl", + "src/android/net/nsd/*.java", ], path: "src", visibility: [ @@ -34,7 +81,7 @@ filegroup { filegroup { name: "framework-connectivity-nsd-aidl-export-sources", srcs: [ - "aidl-export/**/*.aidl", + "aidl-export/android/net/nsd/*.aidl", ], path: "aidl-export", visibility: [ @@ -49,6 +96,19 @@ filegroup { ":framework-connectivity-nsd-aidl-export-sources", ], visibility: [ - "//frameworks/base", + "//visibility:private", ], } + +// Connectivity-T common libraries. + +filegroup { + name: "framework-connectivity-tiramisu-sources", + srcs: [ + ":framework-connectivity-netstats-sources", + ":framework-connectivity-nsd-sources", + ], + visibility: [ + "//frameworks/base", + ], +} \ No newline at end of file diff --git a/core/java/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java similarity index 100% rename from core/java/android/app/usage/NetworkStats.java rename to framework-t/src/android/app/usage/NetworkStats.java diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java similarity index 100% rename from core/java/android/app/usage/NetworkStatsManager.java rename to framework-t/src/android/app/usage/NetworkStatsManager.java diff --git a/core/java/android/net/DataUsageRequest.aidl b/framework-t/src/android/net/DataUsageRequest.aidl similarity index 100% rename from core/java/android/net/DataUsageRequest.aidl rename to framework-t/src/android/net/DataUsageRequest.aidl diff --git a/core/java/android/net/DataUsageRequest.java b/framework-t/src/android/net/DataUsageRequest.java similarity index 100% rename from core/java/android/net/DataUsageRequest.java rename to framework-t/src/android/net/DataUsageRequest.java diff --git a/core/java/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl similarity index 100% rename from core/java/android/net/INetworkStatsService.aidl rename to framework-t/src/android/net/INetworkStatsService.aidl diff --git a/core/java/android/net/INetworkStatsSession.aidl b/framework-t/src/android/net/INetworkStatsSession.aidl similarity index 100% rename from core/java/android/net/INetworkStatsSession.aidl rename to framework-t/src/android/net/INetworkStatsSession.aidl diff --git a/core/java/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java similarity index 100% rename from core/java/android/net/NetworkIdentity.java rename to framework-t/src/android/net/NetworkIdentity.java diff --git a/core/java/android/net/NetworkStateSnapshot.java b/framework-t/src/android/net/NetworkStateSnapshot.java similarity index 100% rename from core/java/android/net/NetworkStateSnapshot.java rename to framework-t/src/android/net/NetworkStateSnapshot.java diff --git a/core/java/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java similarity index 100% rename from core/java/android/net/NetworkStats.java rename to framework-t/src/android/net/NetworkStats.java diff --git a/core/java/android/net/NetworkStatsHistory.aidl b/framework-t/src/android/net/NetworkStatsHistory.aidl similarity index 100% rename from core/java/android/net/NetworkStatsHistory.aidl rename to framework-t/src/android/net/NetworkStatsHistory.aidl diff --git a/core/java/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java similarity index 100% rename from core/java/android/net/NetworkStatsHistory.java rename to framework-t/src/android/net/NetworkStatsHistory.java diff --git a/core/java/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java similarity index 100% rename from core/java/android/net/NetworkTemplate.java rename to framework-t/src/android/net/NetworkTemplate.java diff --git a/core/java/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java similarity index 100% rename from core/java/android/net/TrafficStats.java rename to framework-t/src/android/net/TrafficStats.java diff --git a/core/java/android/net/UnderlyingNetworkInfo.aidl b/framework-t/src/android/net/UnderlyingNetworkInfo.aidl similarity index 100% rename from core/java/android/net/UnderlyingNetworkInfo.aidl rename to framework-t/src/android/net/UnderlyingNetworkInfo.aidl diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/framework-t/src/android/net/UnderlyingNetworkInfo.java similarity index 100% rename from core/java/android/net/UnderlyingNetworkInfo.java rename to framework-t/src/android/net/UnderlyingNetworkInfo.java diff --git a/core/java/android/net/netstats/provider/INetworkStatsProvider.aidl b/framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl similarity index 100% rename from core/java/android/net/netstats/provider/INetworkStatsProvider.aidl rename to framework-t/src/android/net/netstats/provider/INetworkStatsProvider.aidl diff --git a/core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl similarity index 100% rename from core/java/android/net/netstats/provider/INetworkStatsProviderCallback.aidl rename to framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl diff --git a/core/java/android/net/netstats/provider/NetworkStatsProvider.java b/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java similarity index 100% rename from core/java/android/net/netstats/provider/NetworkStatsProvider.java rename to framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java diff --git a/core/java/android/net/NetworkStats.aidl b/framework/aidl-export/android/net/NetworkStats.aidl similarity index 100% rename from core/java/android/net/NetworkStats.aidl rename to framework/aidl-export/android/net/NetworkStats.aidl diff --git a/core/java/android/net/NetworkTemplate.aidl b/framework/aidl-export/android/net/NetworkTemplate.aidl similarity index 100% rename from core/java/android/net/NetworkTemplate.aidl rename to framework/aidl-export/android/net/NetworkTemplate.aidl diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 529f58d130..6a64910609 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -19,13 +19,45 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +// NetworkStats related libraries. + +filegroup { + name: "services.connectivity-netstats-sources", + srcs: [ + "src/com/android/server/net/NetworkIdentity*.java", + "src/com/android/server/net/NetworkStats*.java", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +// Nsd related libraries. + filegroup { name: "services.connectivity-nsd-sources", srcs: [ - "src/**/*.java", + "src/com/android/server/INativeDaemon*.java", + "src/com/android/server/NativeDaemon*.java", + "src/com/android/server/Nsd*.java", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + +// Connectivity-T common libraries. + +filegroup { + name: "services.connectivity-tiramisu-sources", + srcs: [ + ":services.connectivity-netstats-sources", + ":services.connectivity-nsd-sources", ], path: "src", visibility: [ "//frameworks/base/services/core", ], -} +} \ No newline at end of file diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/service-t/src/com/android/server/net/NetworkIdentitySet.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkIdentitySet.java rename to service-t/src/com/android/server/net/NetworkIdentitySet.java diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/service-t/src/com/android/server/net/NetworkStatsAccess.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkStatsAccess.java rename to service-t/src/com/android/server/net/NetworkStatsAccess.java diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/service-t/src/com/android/server/net/NetworkStatsCollection.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkStatsCollection.java rename to service-t/src/com/android/server/net/NetworkStatsCollection.java diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkStatsFactory.java rename to service-t/src/com/android/server/net/NetworkStatsFactory.java diff --git a/services/core/java/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkStatsObservers.java rename to service-t/src/com/android/server/net/NetworkStatsObservers.java diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkStatsRecorder.java rename to service-t/src/com/android/server/net/NetworkStatsRecorder.java diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkStatsService.java rename to service-t/src/com/android/server/net/NetworkStatsService.java diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java similarity index 100% rename from services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java rename to service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java From 4b2fa5914a68612ee93a586e320cdcbecdc55e6e Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 10 Dec 2021 07:46:43 +0000 Subject: [PATCH 699/881] [MS07.1] Move NetworkStatsCollection/IdentitySet into frameworks These files are needed for the data migration util system Api interfaces to allow OEMs to construct NetworkStats* objects. Thus, they need to be moved into android.net package, and some of them will be exposed as @SystemApi in T. Eventually these classes will be moved into the Connectivity module, but in the mean time they will be temporarily moved to f/b/package/ConnectivityT for the preparation stage. However, the tests are already in the module. Therefore for the S-derived branch, the test cannot see the renamed classes since any framework CLs will not be auto-merged into this branch. Thus, the tests need to stay disabled on the S-derived branch, and will be re-enabled after all files are moved into the module. Test: TH Bug: 197717846 Change-Id: I95278a99cf2437ada28001161ceea17a1d32f2a4 --- .../src/android}/net/NetworkIdentitySet.java | 13 ++++--- .../src/android}/net/NetworkStatsAccess.java | 10 ++++-- .../android}/net/NetworkStatsCollection.java | 35 ++++++++++++------- .../server/net/NetworkStatsObservers.java | 3 ++ .../server/net/NetworkStatsRecorder.java | 3 ++ .../server/net/NetworkStatsService.java | 3 ++ 6 files changed, 47 insertions(+), 20 deletions(-) rename {service-t/src/com/android/server => framework-t/src/android}/net/NetworkIdentitySet.java (97%) rename {service-t/src/com/android/server => framework-t/src/android}/net/NetworkStatsAccess.java (98%) rename {service-t/src/com/android/server => framework-t/src/android}/net/NetworkStatsCollection.java (97%) diff --git a/service-t/src/com/android/server/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java similarity index 97% rename from service-t/src/com/android/server/net/NetworkIdentitySet.java rename to framework-t/src/android/net/NetworkIdentitySet.java index 22ed781da9..abbebef85c 100644 --- a/service-t/src/com/android/server/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.android.server.net; +package android.net; + +import static android.net.ConnectivityManager.TYPE_MOBILE; -import android.net.NetworkIdentity; import android.service.NetworkIdentitySetProto; import android.util.proto.ProtoOutputStream; @@ -25,8 +26,6 @@ import java.io.DataOutput; import java.io.IOException; import java.util.HashSet; -import static android.net.ConnectivityManager.TYPE_MOBILE; - /** * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} * active on that interface. @@ -97,6 +96,9 @@ public class NetworkIdentitySet extends HashSet implements } } + /** + * Method to serialize this object into a {@code DataOutput}. + */ public void writeToStream(DataOutput out) throws IOException { out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK); out.writeInt(size()); @@ -179,6 +181,9 @@ public class NetworkIdentitySet extends HashSet implements return ident.compareTo(anotherIdent); } + /** + * Method to dump this object into proto debug file. + */ public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); diff --git a/service-t/src/com/android/server/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java similarity index 98% rename from service-t/src/com/android/server/net/NetworkStatsAccess.java rename to framework-t/src/android/net/NetworkStatsAccess.java index d25eae409d..3885a9e6d5 100644 --- a/service-t/src/com/android/server/net/NetworkStatsAccess.java +++ b/framework-t/src/android/net/NetworkStatsAccess.java @@ -11,10 +11,10 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ -package com.android.server.net; +package android.net; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.net.NetworkStats.UID_ALL; @@ -37,7 +37,11 @@ import com.android.server.LocalServices; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -/** Utility methods for controlling access to network stats APIs. */ +/** + * Utility methods for controlling access to network stats APIs. + * + * @hide + */ public final class NetworkStatsAccess { private NetworkStatsAccess() {} diff --git a/service-t/src/com/android/server/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java similarity index 97% rename from service-t/src/com/android/server/net/NetworkStatsCollection.java rename to framework-t/src/android/net/NetworkStatsCollection.java index 213ea402f5..0d3b9ed4e3 100644 --- a/service-t/src/com/android/server/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server.net; +package android.net; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; @@ -31,13 +31,7 @@ import static android.net.TrafficStats.UID_REMOVED; import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; -import static com.android.server.net.NetworkStatsService.TAG; -import android.net.NetworkIdentity; -import android.net.NetworkStats; -import android.net.NetworkStatsHistory; -import android.net.NetworkTemplate; -import android.net.TrafficStats; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; @@ -85,8 +79,11 @@ import java.util.Objects; /** * Collection of {@link NetworkStatsHistory}, stored based on combined key of * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. + * + * @hide */ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer { + private static final String TAG = NetworkStatsCollection.class.getSimpleName(); /** File header magic number: "ANET" */ private static final int FILE_MAGIC = 0x414E4554; @@ -366,8 +363,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; - entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() ? - DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO; + entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() + ? DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO; entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO; entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; @@ -521,6 +518,12 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** + * Read legacy network summary statistics file format into the collection, + * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}. + * + * @deprecated + */ @Deprecated public void readLegacyNetwork(File file) throws IOException { final AtomicFile inputFile = new AtomicFile(file); @@ -560,6 +563,12 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** + * Read legacy Uid statistics file format into the collection, + * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}. + * + * @deprecated + */ @Deprecated public void readLegacyUid(File file, boolean onlyTags) throws IOException { final AtomicFile inputFile = new AtomicFile(file); @@ -774,19 +783,19 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W public final int set; public final int tag; - private final int hashCode; + private final int mHashCode; - public Key(NetworkIdentitySet ident, int uid, int set, int tag) { + Key(NetworkIdentitySet ident, int uid, int set, int tag) { this.ident = ident; this.uid = uid; this.set = set; this.tag = tag; - hashCode = Objects.hash(ident, uid, set, tag); + mHashCode = Objects.hash(ident, uid, set, tag); } @Override public int hashCode() { - return hashCode; + return mHashCode; } @Override diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java index 2564daeaa1..1a0866d2f9 100644 --- a/service-t/src/com/android/server/net/NetworkStatsObservers.java +++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java @@ -22,7 +22,10 @@ import static com.android.internal.util.Preconditions.checkArgument; import android.app.usage.NetworkStatsManager; import android.net.DataUsageRequest; +import android.net.NetworkIdentitySet; import android.net.NetworkStats; +import android.net.NetworkStatsAccess; +import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Bundle; diff --git a/service-t/src/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java index 978ae87d39..5e27c776cc 100644 --- a/service-t/src/com/android/server/net/NetworkStatsRecorder.java +++ b/service-t/src/com/android/server/net/NetworkStatsRecorder.java @@ -21,8 +21,11 @@ import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.text.format.DateUtils.YEAR_IN_MILLIS; +import android.net.NetworkIdentitySet; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; +import android.net.NetworkStatsAccess; +import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index c876d411fa..2beca73ecd 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -96,11 +96,14 @@ import android.net.INetworkStatsSession; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; +import android.net.NetworkIdentitySet; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicObserver; +import android.net.NetworkStatsAccess; +import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; From 24138d07edb6dceff7bd147e29e46a55376089db Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 2 Nov 2021 02:39:49 +0000 Subject: [PATCH 700/881] [MS01] Move NetworkTemplate cloud backup functions to NetworkPolicy Since NetworkTemplate will be moved into the mainline module. It is necessary to remove hidden BackupUtil usage from NetworkTemplate. Also, it is also a hazard to maintain compatibility for byte buffer interfaces. Thus, move out these cloud backup functions to NetworkPolicy to address these concerns. Test: atest NetworkPolicyTest NetworkPolicyManagerServiceTest Bug: 204830222 Change-Id: I3ec55f7e419ea13db535acff2457d8e7aaebdce8 --- .../src/android/net/NetworkTemplate.java | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index c906a13bf4..8b9c14df7d 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -44,16 +44,10 @@ import android.os.Parcelable; import android.telephony.Annotation.NetworkType; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.BackupUtils; -import android.util.Log; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -69,19 +63,6 @@ import java.util.Objects; public class NetworkTemplate implements Parcelable { private static final String TAG = "NetworkTemplate"; - /** - * Initial Version of the backup serializer. - */ - public static final int BACKUP_VERSION_1_INIT = 1; - /** - * Version of the backup serializer that added carrier template support. - */ - public static final int BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE = 2; - /** - * Current Version of the Backup Serializer. - */ - private static final int BACKUP_VERSION = BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE; - public static final int MATCH_MOBILE = 1; public static final int MATCH_WIFI = 4; public static final int MATCH_ETHERNET = 5; @@ -849,58 +830,4 @@ public class NetworkTemplate implements Parcelable { return new NetworkTemplate[size]; } }; - - public byte[] getBytesForBackup() throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(baos); - - if (!isPersistable()) { - Log.wtf(TAG, "Trying to backup non-persistable template: " + this); - } - - out.writeInt(BACKUP_VERSION); - - out.writeInt(mMatchRule); - BackupUtils.writeString(out, mSubscriberId); - BackupUtils.writeString(out, mNetworkId); - out.writeInt(mMetered); - out.writeInt(mSubscriberIdMatchRule); - - return baos.toByteArray(); - } - - public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in) - throws IOException, BackupUtils.BadVersionException { - int version = in.readInt(); - if (version < BACKUP_VERSION_1_INIT || version > BACKUP_VERSION) { - throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version"); - } - - int matchRule = in.readInt(); - String subscriberId = BackupUtils.readString(in); - String networkId = BackupUtils.readString(in); - - final int metered; - final int subscriberIdMatchRule; - if (version >= BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE) { - metered = in.readInt(); - subscriberIdMatchRule = in.readInt(); - } else { - // For backward compatibility, fill the missing filters from match rules. - metered = (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD - || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL; - subscriberIdMatchRule = SUBSCRIBER_ID_MATCH_RULE_EXACT; - } - - try { - return new NetworkTemplate(matchRule, - subscriberId, new String[] { subscriberId }, - networkId, metered, NetworkStats.ROAMING_ALL, - NetworkStats.DEFAULT_NETWORK_ALL, NetworkTemplate.NETWORK_TYPE_ALL, - NetworkTemplate.OEM_MANAGED_ALL, subscriberIdMatchRule); - } catch (IllegalArgumentException e) { - throw new BackupUtils.BadVersionException( - "Restored network template contains unknown match rule " + matchRule, e); - } - } } From 2c62aabec6ede2b0263cd81c027cf72ef3988235 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 2 Nov 2021 06:52:46 +0000 Subject: [PATCH 701/881] [MS03] Remove ServiceNotFoundException hidden API usage Since ServiceNotFoundException is not a system API. Remove the unsupported interface which uses this exception. This is safe since the method annotated with maxTargetSdk = R and from dashboard it is not using by anybody. Test: TH Bug: 204830222 Change-Id: Ib8c0ce7b165732d24929851792d35371b90a5dfc --- .../src/android/app/usage/NetworkStatsManager.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 8a6c85d548..ca83309216 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -45,8 +45,6 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.ServiceManager.ServiceNotFoundException; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.DataUnit; @@ -135,15 +133,6 @@ public class NetworkStatsManager { private int mFlags; - /** - * {@hide} - */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public NetworkStatsManager(Context context) throws ServiceNotFoundException { - this(context, INetworkStatsService.Stub.asInterface( - ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE))); - } - /** @hide */ @VisibleForTesting public NetworkStatsManager(Context context, INetworkStatsService service) { From 51ce7c1fa0dbf8fd5ab587252f17a98617a2d054 Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 23 Nov 2021 16:16:13 +0800 Subject: [PATCH 702/881] Register NSD service from ConnectivityFrameworkInitializerTiramisu INsdManager is going to move into connectivity mainline module and it will be not visible to SystemServiceRegistry after migration done. Thus, use ConnectivityFrameworkInitializerTiramisu to register NSD service instead. ConnectivityFrameworkInitializerTiramisu will be implemented in the framework-connectivity-tiramisu bootclasspath JAR, which need to be separated from the S+ framework-connectivity bootclasspath JAR to be only loaded by the module on T+. So its methods cannot be in the same class as ConnectivityFrameworkInitializer. Bug: 206702844 Test: atest FrameworksNetTests CtsNetTestCases Merged-In: Ibf89ab9a35e35dac4978ba70c7ab306b6155a4a3 Change-Id: Ibf89ab9a35e35dac4978ba70c7ab306b6155a4a3 --- framework-t/Sources.bp | 14 ++++- ...nectivityFrameworkInitializerTiramisu.java | 52 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 9c07f399f9..3e82b28ce6 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -102,13 +102,25 @@ filegroup { // Connectivity-T common libraries. +filegroup { + name: "framework-connectivity-tiramisu-internal-sources", + srcs: [ + "src/android/net/ConnectivityFrameworkInitializerTiramisu.java", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + filegroup { name: "framework-connectivity-tiramisu-sources", srcs: [ ":framework-connectivity-netstats-sources", ":framework-connectivity-nsd-sources", + ":framework-connectivity-tiramisu-internal-sources", ], visibility: [ "//frameworks/base", ], -} \ No newline at end of file +} diff --git a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java new file mode 100644 index 0000000000..630f902ecf --- /dev/null +++ b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.SystemApi; +import android.app.SystemServiceRegistry; +import android.content.Context; +import android.net.nsd.INsdManager; +import android.net.nsd.NsdManager; + +/** + * Class for performing registration for Connectivity services which are exposed via updatable APIs + * since Android T. + * + * @hide + */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +public final class ConnectivityFrameworkInitializerTiramisu { + private ConnectivityFrameworkInitializerTiramisu() {} + + /** + * Called by {@link SystemServiceRegistry}'s static initializer and registers nsd services to + * {@link Context}, so that {@link Context#getSystemService} can return them. + * + * @throws IllegalStateException if this is called anywhere besides + * {@link SystemServiceRegistry}. + */ + public static void registerServiceWrappers() { + SystemServiceRegistry.registerContextAwareService( + Context.NSD_SERVICE, + NsdManager.class, + (context, serviceBinder) -> { + INsdManager service = INsdManager.Stub.asInterface(serviceBinder); + return new NsdManager(context, service); + } + ); + } +} From 5393e070ed9afdbf4540e2ddfb297224f6869f29 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 9 Sep 2021 17:59:37 +0900 Subject: [PATCH 703/881] Remove Preconditions, Protocol @hide usage Remove hidden API usage of the Preconditions and Protocol classes in NsdManager. NsdManager does not share its handler with other components, so it does not need to use specific message IDs from Protocol. Preconditions can also be easily replaced with stable API alternatives. Bug: 190249673 Test: atest FrameworksNetTests CtsNetTestCases:NsdManagerTest Change-Id: Ia173f99b82c90df702291c3690f4a7b047e90daa --- .../src/android/net/nsd/NsdManager.java | 102 ++++++++++-------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java index 6c597e26e0..0f21e55b9f 100644 --- a/framework-t/src/android/net/nsd/NsdManager.java +++ b/framework-t/src/android/net/nsd/NsdManager.java @@ -16,10 +16,6 @@ package android.net.nsd; -import static com.android.internal.util.Preconditions.checkArgument; -import static com.android.internal.util.Preconditions.checkNotNull; -import static com.android.internal.util.Preconditions.checkStringNotEmpty; - import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; @@ -32,11 +28,13 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Protocol; + +import java.util.Objects; /** * The Network Service Discovery Manager class provides the API to discover services @@ -175,65 +173,63 @@ public final class NsdManager { */ public static final int NSD_STATE_ENABLED = 2; - private static final int BASE = Protocol.BASE_NSD_MANAGER; + /** @hide */ + public static final int DISCOVER_SERVICES = 1; + /** @hide */ + public static final int DISCOVER_SERVICES_STARTED = 2; + /** @hide */ + public static final int DISCOVER_SERVICES_FAILED = 3; + /** @hide */ + public static final int SERVICE_FOUND = 4; + /** @hide */ + public static final int SERVICE_LOST = 5; /** @hide */ - public static final int DISCOVER_SERVICES = BASE + 1; + public static final int STOP_DISCOVERY = 6; /** @hide */ - public static final int DISCOVER_SERVICES_STARTED = BASE + 2; + public static final int STOP_DISCOVERY_FAILED = 7; /** @hide */ - public static final int DISCOVER_SERVICES_FAILED = BASE + 3; - /** @hide */ - public static final int SERVICE_FOUND = BASE + 4; - /** @hide */ - public static final int SERVICE_LOST = BASE + 5; + public static final int STOP_DISCOVERY_SUCCEEDED = 8; /** @hide */ - public static final int STOP_DISCOVERY = BASE + 6; + public static final int REGISTER_SERVICE = 9; /** @hide */ - public static final int STOP_DISCOVERY_FAILED = BASE + 7; + public static final int REGISTER_SERVICE_FAILED = 10; /** @hide */ - public static final int STOP_DISCOVERY_SUCCEEDED = BASE + 8; + public static final int REGISTER_SERVICE_SUCCEEDED = 11; /** @hide */ - public static final int REGISTER_SERVICE = BASE + 9; + public static final int UNREGISTER_SERVICE = 12; /** @hide */ - public static final int REGISTER_SERVICE_FAILED = BASE + 10; + public static final int UNREGISTER_SERVICE_FAILED = 13; /** @hide */ - public static final int REGISTER_SERVICE_SUCCEEDED = BASE + 11; + public static final int UNREGISTER_SERVICE_SUCCEEDED = 14; /** @hide */ - public static final int UNREGISTER_SERVICE = BASE + 12; + public static final int RESOLVE_SERVICE = 15; /** @hide */ - public static final int UNREGISTER_SERVICE_FAILED = BASE + 13; + public static final int RESOLVE_SERVICE_FAILED = 16; /** @hide */ - public static final int UNREGISTER_SERVICE_SUCCEEDED = BASE + 14; + public static final int RESOLVE_SERVICE_SUCCEEDED = 17; /** @hide */ - public static final int RESOLVE_SERVICE = BASE + 18; - /** @hide */ - public static final int RESOLVE_SERVICE_FAILED = BASE + 19; - /** @hide */ - public static final int RESOLVE_SERVICE_SUCCEEDED = BASE + 20; + public static final int DAEMON_CLEANUP = 18; /** @hide */ - public static final int DAEMON_CLEANUP = BASE + 21; + public static final int DAEMON_STARTUP = 19; /** @hide */ - public static final int DAEMON_STARTUP = BASE + 22; + public static final int ENABLE = 20; + /** @hide */ + public static final int DISABLE = 21; /** @hide */ - public static final int ENABLE = BASE + 24; - /** @hide */ - public static final int DISABLE = BASE + 25; + public static final int NATIVE_DAEMON_EVENT = 22; /** @hide */ - public static final int NATIVE_DAEMON_EVENT = BASE + 26; - + public static final int REGISTER_CLIENT = 23; /** @hide */ - public static final int REGISTER_CLIENT = BASE + 27; - /** @hide */ - public static final int UNREGISTER_CLIENT = BASE + 28; + public static final int UNREGISTER_CLIENT = 24; /** Dns based service discovery protocol */ public static final int PROTOCOL_DNS_SD = 0x0001; @@ -550,7 +546,9 @@ public final class NsdManager { final int key; synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - checkArgument(valueIndex == -1, "listener already in use"); + if (valueIndex != -1) { + throw new IllegalArgumentException("listener already in use"); + } key = nextListenerKey(); mListenerMap.put(key, listener); mServiceMap.put(key, s); @@ -569,7 +567,9 @@ public final class NsdManager { checkListener(listener); synchronized (mMapLock) { int valueIndex = mListenerMap.indexOfValue(listener); - checkArgument(valueIndex != -1, "listener not registered"); + if (valueIndex == -1) { + throw new IllegalArgumentException("listener not registered"); + } return mListenerMap.keyAt(valueIndex); } } @@ -598,7 +598,9 @@ public final class NsdManager { */ public void registerService(NsdServiceInfo serviceInfo, int protocolType, RegistrationListener listener) { - checkArgument(serviceInfo.getPort() > 0, "Invalid port number"); + if (serviceInfo.getPort() <= 0) { + throw new IllegalArgumentException("Invalid port number"); + } checkServiceInfo(serviceInfo); checkProtocol(protocolType); int key = putListener(listener, serviceInfo); @@ -660,7 +662,9 @@ public final class NsdManager { * Cannot be null. Cannot be in use for an active service discovery. */ public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { - checkStringNotEmpty(serviceType, "Service type cannot be empty"); + if (TextUtils.isEmpty(serviceType)) { + throw new IllegalArgumentException("Service type cannot be empty"); + } checkProtocol(protocolType); NsdServiceInfo s = new NsdServiceInfo(); @@ -719,16 +723,22 @@ public final class NsdManager { } private static void checkListener(Object listener) { - checkNotNull(listener, "listener cannot be null"); + Objects.requireNonNull(listener, "listener cannot be null"); } private static void checkProtocol(int protocolType) { - checkArgument(protocolType == PROTOCOL_DNS_SD, "Unsupported protocol"); + if (protocolType != PROTOCOL_DNS_SD) { + throw new IllegalArgumentException("Unsupported protocol"); + } } private static void checkServiceInfo(NsdServiceInfo serviceInfo) { - checkNotNull(serviceInfo, "NsdServiceInfo cannot be null"); - checkStringNotEmpty(serviceInfo.getServiceName(), "Service name cannot be empty"); - checkStringNotEmpty(serviceInfo.getServiceType(), "Service type cannot be empty"); + Objects.requireNonNull(serviceInfo, "NsdServiceInfo cannot be null"); + if (TextUtils.isEmpty(serviceInfo.getServiceName())) { + throw new IllegalArgumentException("Service name cannot be empty"); + } + if (TextUtils.isEmpty(serviceInfo.getServiceType())) { + throw new IllegalArgumentException("Service type cannot be empty"); + } } } From 8f4e23616c25f06a266196f919dea0e8712da359 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 10 Dec 2021 17:36:49 +0800 Subject: [PATCH 704/881] Move IpSec associated files to f/b/packages/ConnectivityT IpSecService is going to be moved into Connectivity mainline module. Move all ipsec associated files to packages/ConnectivityT so that it can be easily migrate these files to connectivity module after clearing the hidden API usages. Bug: 204153604 Test: build pass FrameworksNetTests CtsNetTestCases Change-Id: I562b47f18e345988a2638cf886f86818f9144b91 --- framework-t/Sources.bp | 19 +++++++++++++++--- .../src}/android/net/IIpSecService.aidl | 0 .../src}/android/net/IpSecAlgorithm.java | 0 .../src}/android/net/IpSecConfig.aidl | 0 .../src}/android/net/IpSecConfig.java | 0 .../src}/android/net/IpSecManager.java | 0 .../src}/android/net/IpSecSpiResponse.aidl | 0 .../src}/android/net/IpSecSpiResponse.java | 0 .../src}/android/net/IpSecTransform.java | 0 .../android/net/IpSecTransformResponse.aidl | 0 .../android/net/IpSecTransformResponse.java | 0 .../net/IpSecTunnelInterfaceResponse.aidl | 0 .../net/IpSecTunnelInterfaceResponse.java | 0 .../android/net/IpSecUdpEncapResponse.aidl | 0 .../android/net/IpSecUdpEncapResponse.java | 0 service-t/Sources.bp | 20 +++++++++++++++---- .../src}/com/android/server/IpSecService.java | 0 17 files changed, 32 insertions(+), 7 deletions(-) rename {core/java => framework-t/src}/android/net/IIpSecService.aidl (100%) rename {core/java => framework-t/src}/android/net/IpSecAlgorithm.java (100%) rename {core/java => framework-t/src}/android/net/IpSecConfig.aidl (100%) rename {core/java => framework-t/src}/android/net/IpSecConfig.java (100%) rename {core/java => framework-t/src}/android/net/IpSecManager.java (100%) rename {core/java => framework-t/src}/android/net/IpSecSpiResponse.aidl (100%) rename {core/java => framework-t/src}/android/net/IpSecSpiResponse.java (100%) rename {core/java => framework-t/src}/android/net/IpSecTransform.java (100%) rename {core/java => framework-t/src}/android/net/IpSecTransformResponse.aidl (100%) rename {core/java => framework-t/src}/android/net/IpSecTransformResponse.java (100%) rename {core/java => framework-t/src}/android/net/IpSecTunnelInterfaceResponse.aidl (100%) rename {core/java => framework-t/src}/android/net/IpSecTunnelInterfaceResponse.java (100%) rename {core/java => framework-t/src}/android/net/IpSecUdpEncapResponse.aidl (100%) rename {core/java => framework-t/src}/android/net/IpSecUdpEncapResponse.java (100%) rename {services/core/java => service-t/src}/com/android/server/IpSecService.java (100%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 3e82b28ce6..931a55b27d 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -100,6 +100,20 @@ filegroup { ], } +// IpSec related libraries. + +filegroup { + name: "framework-connectivity-ipsec-sources", + srcs: [ + "src/android/net/IIpSecService.aidl", + "src/android/net/IpSec*.*", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + // Connectivity-T common libraries. filegroup { @@ -116,11 +130,10 @@ filegroup { filegroup { name: "framework-connectivity-tiramisu-sources", srcs: [ + ":framework-connectivity-ipsec-sources", ":framework-connectivity-netstats-sources", ":framework-connectivity-nsd-sources", ":framework-connectivity-tiramisu-internal-sources", ], - visibility: [ - "//frameworks/base", - ], + visibility: ["//frameworks/base"], } diff --git a/core/java/android/net/IIpSecService.aidl b/framework-t/src/android/net/IIpSecService.aidl similarity index 100% rename from core/java/android/net/IIpSecService.aidl rename to framework-t/src/android/net/IIpSecService.aidl diff --git a/core/java/android/net/IpSecAlgorithm.java b/framework-t/src/android/net/IpSecAlgorithm.java similarity index 100% rename from core/java/android/net/IpSecAlgorithm.java rename to framework-t/src/android/net/IpSecAlgorithm.java diff --git a/core/java/android/net/IpSecConfig.aidl b/framework-t/src/android/net/IpSecConfig.aidl similarity index 100% rename from core/java/android/net/IpSecConfig.aidl rename to framework-t/src/android/net/IpSecConfig.aidl diff --git a/core/java/android/net/IpSecConfig.java b/framework-t/src/android/net/IpSecConfig.java similarity index 100% rename from core/java/android/net/IpSecConfig.java rename to framework-t/src/android/net/IpSecConfig.java diff --git a/core/java/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java similarity index 100% rename from core/java/android/net/IpSecManager.java rename to framework-t/src/android/net/IpSecManager.java diff --git a/core/java/android/net/IpSecSpiResponse.aidl b/framework-t/src/android/net/IpSecSpiResponse.aidl similarity index 100% rename from core/java/android/net/IpSecSpiResponse.aidl rename to framework-t/src/android/net/IpSecSpiResponse.aidl diff --git a/core/java/android/net/IpSecSpiResponse.java b/framework-t/src/android/net/IpSecSpiResponse.java similarity index 100% rename from core/java/android/net/IpSecSpiResponse.java rename to framework-t/src/android/net/IpSecSpiResponse.java diff --git a/core/java/android/net/IpSecTransform.java b/framework-t/src/android/net/IpSecTransform.java similarity index 100% rename from core/java/android/net/IpSecTransform.java rename to framework-t/src/android/net/IpSecTransform.java diff --git a/core/java/android/net/IpSecTransformResponse.aidl b/framework-t/src/android/net/IpSecTransformResponse.aidl similarity index 100% rename from core/java/android/net/IpSecTransformResponse.aidl rename to framework-t/src/android/net/IpSecTransformResponse.aidl diff --git a/core/java/android/net/IpSecTransformResponse.java b/framework-t/src/android/net/IpSecTransformResponse.java similarity index 100% rename from core/java/android/net/IpSecTransformResponse.java rename to framework-t/src/android/net/IpSecTransformResponse.java diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.aidl b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl similarity index 100% rename from core/java/android/net/IpSecTunnelInterfaceResponse.aidl rename to framework-t/src/android/net/IpSecTunnelInterfaceResponse.aidl diff --git a/core/java/android/net/IpSecTunnelInterfaceResponse.java b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java similarity index 100% rename from core/java/android/net/IpSecTunnelInterfaceResponse.java rename to framework-t/src/android/net/IpSecTunnelInterfaceResponse.java diff --git a/core/java/android/net/IpSecUdpEncapResponse.aidl b/framework-t/src/android/net/IpSecUdpEncapResponse.aidl similarity index 100% rename from core/java/android/net/IpSecUdpEncapResponse.aidl rename to framework-t/src/android/net/IpSecUdpEncapResponse.aidl diff --git a/core/java/android/net/IpSecUdpEncapResponse.java b/framework-t/src/android/net/IpSecUdpEncapResponse.java similarity index 100% rename from core/java/android/net/IpSecUdpEncapResponse.java rename to framework-t/src/android/net/IpSecUdpEncapResponse.java diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 6a64910609..7b8817692b 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -48,16 +48,28 @@ filegroup { ], } +// IpSec related libraries. + +filegroup { + name: "services.connectivity-ipsec-sources", + srcs: [ + "src/com/android/server/IpSecService.java", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + // Connectivity-T common libraries. filegroup { name: "services.connectivity-tiramisu-sources", srcs: [ + ":services.connectivity-ipsec-sources", ":services.connectivity-netstats-sources", ":services.connectivity-nsd-sources", ], path: "src", - visibility: [ - "//frameworks/base/services/core", - ], -} \ No newline at end of file + visibility: ["//frameworks/base/services/core"], +} diff --git a/services/core/java/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java similarity index 100% rename from services/core/java/com/android/server/IpSecService.java rename to service-t/src/com/android/server/IpSecService.java From b24f3da2b95d9543bc268e266fde714134f67f97 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 6 Dec 2021 15:18:42 +0800 Subject: [PATCH 705/881] Fix style errors for IpSec associated files Bug: 204153604 Test: build pass. Change-Id: I940de8bef7f693dcce8808148a975bea1f36712c --- .../src/android/net/IpSecAlgorithm.java | 2 +- framework-t/src/android/net/IpSecManager.java | 12 +++---- .../android/net/IpSecTransformResponse.java | 3 +- .../net/IpSecTunnelInterfaceResponse.java | 3 +- .../android/net/IpSecUdpEncapResponse.java | 4 ++- .../src/com/android/server/IpSecService.java | 33 ++++++++++--------- 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/framework-t/src/android/net/IpSecAlgorithm.java b/framework-t/src/android/net/IpSecAlgorithm.java index 86052484ea..840af28b77 100644 --- a/framework-t/src/android/net/IpSecAlgorithm.java +++ b/framework-t/src/android/net/IpSecAlgorithm.java @@ -297,7 +297,7 @@ public final class IpSecAlgorithm implements Parcelable { return mTruncLenBits; } - /* Parcelable Implementation */ + /** Parcelable Implementation */ public int describeContents() { return 0; } diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java index c10680761f..837629911c 100644 --- a/framework-t/src/android/net/IpSecManager.java +++ b/framework-t/src/android/net/IpSecManager.java @@ -99,9 +99,9 @@ public final class IpSecManager { /** @hide */ public interface Status { - public static final int OK = 0; - public static final int RESOURCE_UNAVAILABLE = 1; - public static final int SPI_UNAVAILABLE = 2; + int OK = 0; + int RESOURCE_UNAVAILABLE = 1; + int SPI_UNAVAILABLE = 2; } /** @hide */ @@ -276,7 +276,7 @@ public final class IpSecManager { * @param destinationAddress the destination address for traffic bearing the requested SPI. * For inbound traffic, the destination should be an address currently assigned on-device. * @return the reserved SecurityParameterIndex - * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * @throws ResourceUnavailableException indicating that too many SPIs are * currently allocated for this user */ @NonNull @@ -307,9 +307,9 @@ public final class IpSecManager { * @param requestedSpi the requested SPI. The range 1-255 is reserved and may not be used. See * RFC 4303 Section 2.1. * @return the reserved SecurityParameterIndex - * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are + * @throws ResourceUnavailableException indicating that too many SPIs are * currently allocated for this user - * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be + * @throws SpiUnavailableException indicating that the requested SPI could not be * reserved */ @NonNull diff --git a/framework-t/src/android/net/IpSecTransformResponse.java b/framework-t/src/android/net/IpSecTransformResponse.java index a38488954f..363f3165ee 100644 --- a/framework-t/src/android/net/IpSecTransformResponse.java +++ b/framework-t/src/android/net/IpSecTransformResponse.java @@ -60,7 +60,8 @@ public final class IpSecTransformResponse implements Parcelable { resourceId = in.readInt(); } - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = + @android.annotation.NonNull + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecTransformResponse createFromParcel(Parcel in) { return new IpSecTransformResponse(in); diff --git a/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java index e3411e003d..127e30a693 100644 --- a/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java +++ b/framework-t/src/android/net/IpSecTunnelInterfaceResponse.java @@ -65,7 +65,8 @@ public final class IpSecTunnelInterfaceResponse implements Parcelable { interfaceName = in.readString(); } - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = + @android.annotation.NonNull + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecTunnelInterfaceResponse createFromParcel(Parcel in) { return new IpSecTunnelInterfaceResponse(in); diff --git a/framework-t/src/android/net/IpSecUdpEncapResponse.java b/framework-t/src/android/net/IpSecUdpEncapResponse.java index 4e7ba9b515..732cf198a9 100644 --- a/framework-t/src/android/net/IpSecUdpEncapResponse.java +++ b/framework-t/src/android/net/IpSecUdpEncapResponse.java @@ -18,6 +18,7 @@ package android.net; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; + import java.io.FileDescriptor; import java.io.IOException; @@ -83,7 +84,8 @@ public final class IpSecUdpEncapResponse implements Parcelable { fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); } - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = + @android.annotation.NonNull + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public IpSecUdpEncapResponse createFromParcel(Parcel in) { return new IpSecUdpEncapResponse(in); diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java index aeb814327e..dfc57c136f 100644 --- a/service-t/src/com/android/server/IpSecService.java +++ b/service-t/src/com/android/server/IpSecService.java @@ -132,7 +132,7 @@ public class IpSecService extends IIpSecService.Stub { interface IpSecServiceConfiguration { INetd getNetdInstance() throws RemoteException; - static IpSecServiceConfiguration GETSRVINSTANCE = + IpSecServiceConfiguration GETSRVINSTANCE = new IpSecServiceConfiguration() { @Override public INetd getNetdInstance() throws RemoteException { @@ -491,8 +491,8 @@ public class IpSecService extends IIpSecService.Stub { *

This class associates kernel resources with the UID that owns and controls them. */ private abstract class OwnedResourceRecord implements IResource { - final int pid; - final int uid; + final int mPid; + final int mUid; protected final int mResourceId; OwnedResourceRecord(int resourceId) { @@ -501,8 +501,8 @@ public class IpSecService extends IIpSecService.Stub { throw new IllegalArgumentException("Resource ID must not be INVALID_RESOURCE_ID"); } mResourceId = resourceId; - pid = Binder.getCallingPid(); - uid = Binder.getCallingUid(); + mPid = Binder.getCallingPid(); + mUid = Binder.getCallingUid(); getResourceTracker().take(); } @@ -512,7 +512,7 @@ public class IpSecService extends IIpSecService.Stub { /** Convenience method; retrieves the user resource record for the stored UID. */ protected UserRecord getUserRecord() { - return mUserResourceTracker.getUserRecord(uid); + return mUserResourceTracker.getUserRecord(mUid); } @Override @@ -527,9 +527,9 @@ public class IpSecService extends IIpSecService.Stub { .append("{mResourceId=") .append(mResourceId) .append(", pid=") - .append(pid) + .append(mPid) .append(", uid=") - .append(uid) + .append(mUid) .append("}") .toString(); } @@ -545,7 +545,7 @@ public class IpSecService extends IIpSecService.Stub { SparseArray> mArray = new SparseArray<>(); private final String mTypeName; - public RefcountedResourceArray(String typeName) { + RefcountedResourceArray(String typeName) { this.mTypeName = typeName; } @@ -628,7 +628,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - uid, + mUid, mConfig.getSourceAddress(), mConfig.getDestinationAddress(), spi, @@ -696,7 +696,7 @@ public class IpSecService extends IIpSecService.Stub { mSrvConfig .getNetdInstance() .ipSecDeleteSecurityAssociation( - uid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, + mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, 0 /* mask */, 0 /* if_id */); } } catch (ServiceSpecificException | RemoteException e) { @@ -849,14 +849,14 @@ public class IpSecService extends IIpSecService.Stub { for (int selAddrFamily : ADDRESS_FAMILIES) { netd.ipSecDeleteSecurityPolicy( - uid, + mUid, selAddrFamily, IpSecManager.DIRECTION_OUT, mOkey, 0xffffffff, mIfId); netd.ipSecDeleteSecurityPolicy( - uid, + mUid, selAddrFamily, IpSecManager.DIRECTION_IN, mIkey, @@ -1025,7 +1025,7 @@ public class IpSecService extends IIpSecService.Stub { @NonNull private AppOpsManager getAppOpsManager() { AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); - if(appOps == null) throw new RuntimeException("System Server couldn't get AppOps"); + if (appOps == null) throw new RuntimeException("System Server couldn't get AppOps"); return appOps; } @@ -1054,6 +1054,7 @@ public class IpSecService extends IIpSecService.Stub { mUidFdTagger = uidFdTagger; } + /** Called by system server when system is ready. */ public void systemReady() { if (isNetdAlive()) { Log.d(TAG, "IpSecService is ready"); @@ -1229,7 +1230,7 @@ public class IpSecService extends IIpSecService.Stub { *

Since the socket is created on behalf of an unprivileged application, all traffic * should be accounted to the UID of the unprivileged application. */ - public void tag(FileDescriptor fd, int uid) throws IOException; + void tag(FileDescriptor fd, int uid) throws IOException; } /** @@ -1771,7 +1772,7 @@ public class IpSecService extends IIpSecService.Stub { TransformRecord info = userRecord.mTransformRecords.getResourceOrThrow(resourceId); // TODO: make this a function. - if (info.pid != getCallingPid() || info.uid != callingUid) { + if (info.mPid != getCallingPid() || info.mUid != callingUid) { throw new SecurityException("Only the owner of an IpSec Transform may apply it!"); } From 92b7afc77705719bb45960c91da6bd119f6c5018 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Sat, 27 Nov 2021 00:30:35 +0800 Subject: [PATCH 706/881] Refactor IpSecServiceConfiguration to Dependencies IpSecService is going to be moved into ConnectivityService module, so the hidden API usage should be removed. NetdService.getNetdInstance is a hidden API, therefore the alternative is to get the instance by Context.getSystemService. Bug: 204153604 Test: FrameworksNetTests Change-Id: I1bd8efc03c37654d12a8eadd3e78ed45e10b5691 --- .../src/com/android/server/IpSecService.java | 99 ++++++++++--------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java index dfc57c136f..f251b86b7a 100644 --- a/service-t/src/com/android/server/IpSecService.java +++ b/service-t/src/com/android/server/IpSecService.java @@ -119,6 +119,7 @@ public class IpSecService extends IIpSecService.Stub { /* Binder context for this service */ private final Context mContext; + private final Dependencies mDeps; /** * The next non-repeating global ID for tracking resources between users, this service, and @@ -129,23 +130,24 @@ public class IpSecService extends IIpSecService.Stub { @GuardedBy("IpSecService.this") private int mNextResourceId = 1; - interface IpSecServiceConfiguration { - INetd getNetdInstance() throws RemoteException; - - IpSecServiceConfiguration GETSRVINSTANCE = - new IpSecServiceConfiguration() { - @Override - public INetd getNetdInstance() throws RemoteException { - final INetd netd = NetdService.getInstance(); - if (netd == null) { - throw new RemoteException("Failed to Get Netd Instance"); - } - return netd; - } - }; + /** + * Dependencies of IpSecService, for injection in tests. + */ + @VisibleForTesting + public static class Dependencies { + /** + * Get a reference to INetd. + */ + public INetd getNetdInstance(Context context) throws RemoteException { + final INetd netd = INetd.Stub.asInterface((IBinder) + context.getSystemService(Context.NETD_SERVICE)); + if (netd == null) { + throw new RemoteException("Failed to Get Netd Instance"); + } + return netd; + } } - private final IpSecServiceConfiguration mSrvConfig; final UidFdTagger mUidFdTagger; /** @@ -625,8 +627,8 @@ public class IpSecService extends IIpSecService.Stub { public void freeUnderlyingResources() { int spi = mSpi.getSpi(); try { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecDeleteSecurityAssociation( mUid, mConfig.getSourceAddress(), @@ -678,11 +680,14 @@ public class IpSecService extends IIpSecService.Stub { private final String mSourceAddress; private final String mDestinationAddress; private int mSpi; + private final Context mContext; private boolean mOwnedByTransform = false; - SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) { + SpiRecord(Context context, int resourceId, String sourceAddress, + String destinationAddress, int spi) { super(resourceId); + mContext = context; mSourceAddress = sourceAddress; mDestinationAddress = destinationAddress; mSpi = spi; @@ -693,8 +698,8 @@ public class IpSecService extends IIpSecService.Stub { public void freeUnderlyingResources() { try { if (!mOwnedByTransform) { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecDeleteSecurityAssociation( mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, 0 /* mask */, 0 /* if_id */); @@ -816,8 +821,10 @@ public class IpSecService extends IIpSecService.Stub { private final int mIfId; private Network mUnderlyingNetwork; + private final Context mContext; TunnelInterfaceRecord( + Context context, int resourceId, String interfaceName, Network underlyingNetwork, @@ -828,6 +835,7 @@ public class IpSecService extends IIpSecService.Stub { int intfId) { super(resourceId); + mContext = context; mInterfaceName = interfaceName; mUnderlyingNetwork = underlyingNetwork; mLocalAddress = localAddr; @@ -844,7 +852,7 @@ public class IpSecService extends IIpSecService.Stub { // Teardown VTI // Delete global policies try { - final INetd netd = mSrvConfig.getNetdInstance(); + final INetd netd = mDeps.getNetdInstance(mContext); netd.ipSecRemoveTunnelInterface(mInterfaceName); for (int selAddrFamily : ADDRESS_FAMILIES) { @@ -1012,7 +1020,7 @@ public class IpSecService extends IIpSecService.Stub { * @param context Binder context for this service */ private IpSecService(Context context) { - this(context, IpSecServiceConfiguration.GETSRVINSTANCE); + this(context, new Dependencies()); } static IpSecService create(Context context) @@ -1031,10 +1039,10 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, IpSecServiceConfiguration config) { + public IpSecService(Context context, Dependencies deps) { this( context, - config, + deps, (fd, uid) -> { try { TrafficStats.setThreadStatsUid(uid); @@ -1047,10 +1055,9 @@ public class IpSecService extends IIpSecService.Stub { /** @hide */ @VisibleForTesting - public IpSecService(Context context, IpSecServiceConfiguration config, - UidFdTagger uidFdTagger) { + public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) { mContext = context; - mSrvConfig = config; + mDeps = deps; mUidFdTagger = uidFdTagger; } @@ -1077,7 +1084,7 @@ public class IpSecService extends IIpSecService.Stub { synchronized boolean isNetdAlive() { try { - final INetd netd = mSrvConfig.getNetdInstance(); + final INetd netd = mDeps.getNetdInstance(mContext); if (netd == null) { return false; } @@ -1143,14 +1150,15 @@ public class IpSecService extends IIpSecService.Stub { } spi = - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi); Log.d(TAG, "Allocated SPI " + spi); userRecord.mSpiRecords.put( resourceId, new RefcountedResource( - new SpiRecord(resourceId, "", destinationAddress, spi), binder)); + new SpiRecord(mContext, resourceId, "", + destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { if (e.errorCode == OsConstants.ENOENT) { return new IpSecSpiResponse( @@ -1267,7 +1275,7 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mSrvConfig.getNetdInstance().ipSecSetEncapSocketOwner( + mDeps.getNetdInstance(mContext).ipSecSetEncapSocketOwner( new ParcelFileDescriptor(sockFd), callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); @@ -1330,7 +1338,7 @@ public class IpSecService extends IIpSecService.Stub { // Create VTI // Add inbound/outbound global policies // (use reqid = 0) - final INetd netd = mSrvConfig.getNetdInstance(); + final INetd netd = mDeps.getNetdInstance(mContext); netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); BinderUtils.withCleanCallingIdentity(() -> { @@ -1385,6 +1393,7 @@ public class IpSecService extends IIpSecService.Stub { resourceId, new RefcountedResource( new TunnelInterfaceRecord( + mContext, resourceId, intfName, underlyingNetwork, @@ -1426,8 +1435,8 @@ public class IpSecService extends IIpSecService.Stub { try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .interfaceAddAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), @@ -1455,8 +1464,8 @@ public class IpSecService extends IIpSecService.Stub { try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .interfaceDelAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), @@ -1670,8 +1679,8 @@ public class IpSecService extends IIpSecService.Stub { cryptName = crypt.getName(); } - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecAddSecurityAssociation( Binder.getCallingUid(), c.getMode(), @@ -1782,8 +1791,8 @@ public class IpSecService extends IIpSecService.Stub { c.getMode() == IpSecTransform.MODE_TRANSPORT, "Transform mode was not Transport mode; cannot be applied to a socket"); - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecApplyTransportModeTransform( socket, callingUid, @@ -1802,8 +1811,8 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) throws RemoteException { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecRemoveTransportModeTransform(socket); } @@ -1879,8 +1888,8 @@ public class IpSecService extends IIpSecService.Stub { // Always update the policy with the relevant XFRM_IF_ID for (int selAddrFamily : ADDRESS_FAMILIES) { - mSrvConfig - .getNetdInstance() + mDeps + .getNetdInstance(mContext) .ipSecUpdateSecurityPolicy( callingUid, selAddrFamily, From f318d55576d449a811e82bffa80cdc836127ec9f Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 29 Nov 2021 16:31:32 +0800 Subject: [PATCH 707/881] Remove NetdService usage from IpSecService IpSecService is going to be moved into ConnectivityService module. So, NetdService won't be visible to IpSecService since it is a hidden class. NetdService.get(timeout) is a method that blocks for specified time until INetd instance is available. In SystemServer IpSecService is created after NetworkManagementService and NMS uses NetdService.get() to get INetd instance which is a method that blocks until an INetd instance is available. Thus, connectNativeNetdService can be removed because NMS already waits for INetd instance is available so IpSecService should be able to get INetd instance immediately. Bug: 204153604 Test: FrameworksNetTest Change-Id: I007cb28de63783d60084f93dddb4de78faa0e868 --- .../src/com/android/server/IpSecService.java | 194 +++++++----------- 1 file changed, 78 insertions(+), 116 deletions(-) diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java index f251b86b7a..d1e432e80f 100644 --- a/service-t/src/com/android/server/IpSecService.java +++ b/service-t/src/com/android/server/IpSecService.java @@ -45,7 +45,6 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.TrafficStats; -import android.net.util.NetdService; import android.os.Binder; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -96,8 +95,6 @@ import java.util.Objects; public class IpSecService extends IIpSecService.Stub { private static final String TAG = "IpSecService"; private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); - - private static final String NETD_SERVICE_NAME = "netd"; private static final int[] ADDRESS_FAMILIES = new int[] {OsConstants.AF_INET, OsConstants.AF_INET6}; @@ -106,6 +103,8 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting static final int MAX_PORT_BIND_ATTEMPTS = 10; + private final INetd mNetd; + static { try { INADDR_ANY = InetAddress.getByAddress(new byte[] {0, 0, 0, 0}); @@ -627,16 +626,14 @@ public class IpSecService extends IIpSecService.Stub { public void freeUnderlyingResources() { int spi = mSpi.getSpi(); try { - mDeps - .getNetdInstance(mContext) - .ipSecDeleteSecurityAssociation( - mUid, - mConfig.getSourceAddress(), - mConfig.getDestinationAddress(), - spi, - mConfig.getMarkValue(), - mConfig.getMarkMask(), - mConfig.getXfrmInterfaceId()); + mNetd.ipSecDeleteSecurityAssociation( + mUid, + mConfig.getSourceAddress(), + mConfig.getDestinationAddress(), + spi, + mConfig.getMarkValue(), + mConfig.getMarkMask(), + mConfig.getXfrmInterfaceId()); } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Failed to delete SA with ID: " + mResourceId, e); } @@ -680,14 +677,12 @@ public class IpSecService extends IIpSecService.Stub { private final String mSourceAddress; private final String mDestinationAddress; private int mSpi; - private final Context mContext; private boolean mOwnedByTransform = false; - SpiRecord(Context context, int resourceId, String sourceAddress, + SpiRecord(int resourceId, String sourceAddress, String destinationAddress, int spi) { super(resourceId); - mContext = context; mSourceAddress = sourceAddress; mDestinationAddress = destinationAddress; mSpi = spi; @@ -698,11 +693,9 @@ public class IpSecService extends IIpSecService.Stub { public void freeUnderlyingResources() { try { if (!mOwnedByTransform) { - mDeps - .getNetdInstance(mContext) - .ipSecDeleteSecurityAssociation( - mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, - 0 /* mask */, 0 /* if_id */); + mNetd.ipSecDeleteSecurityAssociation( + mUid, mSourceAddress, mDestinationAddress, mSpi, 0 /* mark */, + 0 /* mask */, 0 /* if_id */); } } catch (ServiceSpecificException | RemoteException e) { Log.e(TAG, "Failed to delete SPI reservation with ID: " + mResourceId, e); @@ -821,10 +814,8 @@ public class IpSecService extends IIpSecService.Stub { private final int mIfId; private Network mUnderlyingNetwork; - private final Context mContext; TunnelInterfaceRecord( - Context context, int resourceId, String interfaceName, Network underlyingNetwork, @@ -835,7 +826,6 @@ public class IpSecService extends IIpSecService.Stub { int intfId) { super(resourceId); - mContext = context; mInterfaceName = interfaceName; mUnderlyingNetwork = underlyingNetwork; mLocalAddress = localAddr; @@ -852,18 +842,17 @@ public class IpSecService extends IIpSecService.Stub { // Teardown VTI // Delete global policies try { - final INetd netd = mDeps.getNetdInstance(mContext); - netd.ipSecRemoveTunnelInterface(mInterfaceName); + mNetd.ipSecRemoveTunnelInterface(mInterfaceName); for (int selAddrFamily : ADDRESS_FAMILIES) { - netd.ipSecDeleteSecurityPolicy( + mNetd.ipSecDeleteSecurityPolicy( mUid, selAddrFamily, IpSecManager.DIRECTION_OUT, mOkey, 0xffffffff, mIfId); - netd.ipSecDeleteSecurityPolicy( + mNetd.ipSecDeleteSecurityPolicy( mUid, selAddrFamily, IpSecManager.DIRECTION_IN, @@ -1026,7 +1015,6 @@ public class IpSecService extends IIpSecService.Stub { static IpSecService create(Context context) throws InterruptedException { final IpSecService service = new IpSecService(context); - service.connectNativeNetdService(); return service; } @@ -1057,8 +1045,13 @@ public class IpSecService extends IIpSecService.Stub { @VisibleForTesting public IpSecService(Context context, Dependencies deps, UidFdTagger uidFdTagger) { mContext = context; - mDeps = deps; + mDeps = Objects.requireNonNull(deps, "Missing dependencies."); mUidFdTagger = uidFdTagger; + try { + mNetd = mDeps.getNetdInstance(mContext); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** Called by system server when system is ready. */ @@ -1070,25 +1063,12 @@ public class IpSecService extends IIpSecService.Stub { } } - private void connectNativeNetdService() { - // Avoid blocking the system server to do this - new Thread() { - @Override - public void run() { - synchronized (IpSecService.this) { - NetdService.get(NETD_FETCH_TIMEOUT_MS); - } - } - }.start(); - } - synchronized boolean isNetdAlive() { try { - final INetd netd = mDeps.getNetdInstance(mContext); - if (netd == null) { + if (mNetd == null) { return false; } - return netd.isAlive(); + return mNetd.isAlive(); } catch (RemoteException re) { return false; } @@ -1149,15 +1129,12 @@ public class IpSecService extends IIpSecService.Stub { IpSecManager.Status.RESOURCE_UNAVAILABLE, INVALID_RESOURCE_ID, spi); } - spi = - mDeps - .getNetdInstance(mContext) - .ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi); + spi = mNetd.ipSecAllocateSpi(callingUid, "", destinationAddress, requestedSpi); Log.d(TAG, "Allocated SPI " + spi); userRecord.mSpiRecords.put( resourceId, new RefcountedResource( - new SpiRecord(mContext, resourceId, "", + new SpiRecord(resourceId, "", destinationAddress, spi), binder)); } catch (ServiceSpecificException e) { if (e.errorCode == OsConstants.ENOENT) { @@ -1275,8 +1252,7 @@ public class IpSecService extends IIpSecService.Stub { OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mDeps.getNetdInstance(mContext).ipSecSetEncapSocketOwner( - new ParcelFileDescriptor(sockFd), callingUid); + mNetd.ipSecSetEncapSocketOwner(new ParcelFileDescriptor(sockFd), callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); Os.bind(sockFd, INADDR_ANY, port); @@ -1338,16 +1314,15 @@ public class IpSecService extends IIpSecService.Stub { // Create VTI // Add inbound/outbound global policies // (use reqid = 0) - final INetd netd = mDeps.getNetdInstance(mContext); - netd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); + mNetd.ipSecAddTunnelInterface(intfName, localAddr, remoteAddr, ikey, okey, resourceId); BinderUtils.withCleanCallingIdentity(() -> { - NetdUtils.setInterfaceUp(netd, intfName); + NetdUtils.setInterfaceUp(mNetd, intfName); }); for (int selAddrFamily : ADDRESS_FAMILIES) { // Always send down correct local/remote addresses for template. - netd.ipSecAddSecurityPolicy( + mNetd.ipSecAddSecurityPolicy( callerUid, selAddrFamily, IpSecManager.DIRECTION_OUT, @@ -1357,7 +1332,7 @@ public class IpSecService extends IIpSecService.Stub { okey, 0xffffffff, resourceId); - netd.ipSecAddSecurityPolicy( + mNetd.ipSecAddSecurityPolicy( callerUid, selAddrFamily, IpSecManager.DIRECTION_IN, @@ -1377,7 +1352,7 @@ public class IpSecService extends IIpSecService.Stub { // // This is necessary only on the tunnel interface, and not any the interface to // which traffic will be forwarded to. - netd.ipSecAddSecurityPolicy( + mNetd.ipSecAddSecurityPolicy( callerUid, selAddrFamily, IpSecManager.DIRECTION_FWD, @@ -1393,7 +1368,6 @@ public class IpSecService extends IIpSecService.Stub { resourceId, new RefcountedResource( new TunnelInterfaceRecord( - mContext, resourceId, intfName, underlyingNetwork, @@ -1435,12 +1409,10 @@ public class IpSecService extends IIpSecService.Stub { try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. - mDeps - .getNetdInstance(mContext) - .interfaceAddAddress( - tunnelInterfaceInfo.mInterfaceName, - localAddr.getAddress().getHostAddress(), - localAddr.getPrefixLength()); + mNetd.interfaceAddAddress( + tunnelInterfaceInfo.mInterfaceName, + localAddr.getAddress().getHostAddress(), + localAddr.getPrefixLength()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1464,9 +1436,7 @@ public class IpSecService extends IIpSecService.Stub { try { // We can assume general validity of the IP address, since we get them as a // LinkAddress, which does some validation. - mDeps - .getNetdInstance(mContext) - .interfaceDelAddress( + mNetd.interfaceDelAddress( tunnelInterfaceInfo.mInterfaceName, localAddr.getAddress().getHostAddress(), localAddr.getPrefixLength()); @@ -1679,30 +1649,28 @@ public class IpSecService extends IIpSecService.Stub { cryptName = crypt.getName(); } - mDeps - .getNetdInstance(mContext) - .ipSecAddSecurityAssociation( - Binder.getCallingUid(), - c.getMode(), - c.getSourceAddress(), - c.getDestinationAddress(), - (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0, - spiRecord.getSpi(), - c.getMarkValue(), - c.getMarkMask(), - (auth != null) ? auth.getName() : "", - (auth != null) ? auth.getKey() : new byte[] {}, - (auth != null) ? auth.getTruncationLengthBits() : 0, - cryptName, - (crypt != null) ? crypt.getKey() : new byte[] {}, - (crypt != null) ? crypt.getTruncationLengthBits() : 0, - (authCrypt != null) ? authCrypt.getName() : "", - (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, - (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, - encapType, - encapLocalPort, - encapRemotePort, - c.getXfrmInterfaceId()); + mNetd.ipSecAddSecurityAssociation( + Binder.getCallingUid(), + c.getMode(), + c.getSourceAddress(), + c.getDestinationAddress(), + (c.getNetwork() != null) ? c.getNetwork().getNetId() : 0, + spiRecord.getSpi(), + c.getMarkValue(), + c.getMarkMask(), + (auth != null) ? auth.getName() : "", + (auth != null) ? auth.getKey() : new byte[] {}, + (auth != null) ? auth.getTruncationLengthBits() : 0, + cryptName, + (crypt != null) ? crypt.getKey() : new byte[] {}, + (crypt != null) ? crypt.getTruncationLengthBits() : 0, + (authCrypt != null) ? authCrypt.getName() : "", + (authCrypt != null) ? authCrypt.getKey() : new byte[] {}, + (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0, + encapType, + encapLocalPort, + encapRemotePort, + c.getXfrmInterfaceId()); } /** @@ -1791,15 +1759,13 @@ public class IpSecService extends IIpSecService.Stub { c.getMode() == IpSecTransform.MODE_TRANSPORT, "Transform mode was not Transport mode; cannot be applied to a socket"); - mDeps - .getNetdInstance(mContext) - .ipSecApplyTransportModeTransform( - socket, - callingUid, - direction, - c.getSourceAddress(), - c.getDestinationAddress(), - info.getSpiRecord().getSpi()); + mNetd.ipSecApplyTransportModeTransform( + socket, + callingUid, + direction, + c.getSourceAddress(), + c.getDestinationAddress(), + info.getSpiRecord().getSpi()); } /** @@ -1811,9 +1777,7 @@ public class IpSecService extends IIpSecService.Stub { @Override public synchronized void removeTransportModeTransforms(ParcelFileDescriptor socket) throws RemoteException { - mDeps - .getNetdInstance(mContext) - .ipSecRemoveTransportModeTransform(socket); + mNetd.ipSecRemoveTransportModeTransform(socket); } /** @@ -1888,18 +1852,16 @@ public class IpSecService extends IIpSecService.Stub { // Always update the policy with the relevant XFRM_IF_ID for (int selAddrFamily : ADDRESS_FAMILIES) { - mDeps - .getNetdInstance(mContext) - .ipSecUpdateSecurityPolicy( - callingUid, - selAddrFamily, - direction, - transformInfo.getConfig().getSourceAddress(), - transformInfo.getConfig().getDestinationAddress(), - spi, // If outbound, also add SPI to the policy. - mark, // Must always set policy mark; ikey/okey for VTIs - 0xffffffff, - c.getXfrmInterfaceId()); + mNetd.ipSecUpdateSecurityPolicy( + callingUid, + selAddrFamily, + direction, + transformInfo.getConfig().getSourceAddress(), + transformInfo.getConfig().getDestinationAddress(), + spi, // If outbound, also add SPI to the policy. + mark, // Must always set policy mark; ikey/okey for VTIs + 0xffffffff, + c.getXfrmInterfaceId()); } // Update SA with tunnel mark (ikey or okey based on direction) From e6ab4493c6fc9e2a5af68b16cdb4b047edf6b048 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 9 Dec 2021 16:18:06 +0800 Subject: [PATCH 708/881] Remove isUnsafeBuild() from IpSecAlgorithm IpSec is going to move to Connectivity mainline module so hidden API usage should be removed. There's no formal API could be an alternative for Build.IS_ENG. Considering isUnsafeBuild() is not a really helpful method because it only prints the log in eng build. Therefore, remove it. Bug: 204153604 Test: FrameworksNetTests Change-Id: Ic354e12423629b0d72e8087843893953a0c8c465 --- framework-t/src/android/net/IpSecAlgorithm.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/framework-t/src/android/net/IpSecAlgorithm.java b/framework-t/src/android/net/IpSecAlgorithm.java index 840af28b77..5e647fe2f9 100644 --- a/framework-t/src/android/net/IpSecAlgorithm.java +++ b/framework-t/src/android/net/IpSecAlgorithm.java @@ -469,20 +469,12 @@ public final class IpSecAlgorithm implements Parcelable { } } - // Because encryption keys are sensitive and userdebug builds are used by large user pools - // such as beta testers, we only allow sensitive info such as keys on eng builds. - private static boolean isUnsafeBuild() { - return Build.IS_DEBUGGABLE && Build.IS_ENG; - } - @Override @NonNull public String toString() { return new StringBuilder() .append("{mName=") .append(mName) - .append(", mKey=") - .append(isUnsafeBuild() ? HexDump.toHexString(mKey) : "") .append(", mTruncLenBits=") .append(mTruncLenBits) .append("}") From 7ac844f41c29a3a99a2090d431aaf5159f4cb0eb Mon Sep 17 00:00:00 2001 From: Pavan Kumar M Date: Mon, 8 Feb 2021 21:17:20 +0530 Subject: [PATCH 709/881] Handle neighbor lost event Neighbor lost event is received when gateway is not reachable. Ethernet Factory currently doesn't handle the neighbor lost event and network will not be brought down. This results in loss of connectivity even if there are other networks like WiFi. Restart NetworkInterfaceState when neighbor lost event is received. If there is a better network like WiFi, it will become default and apps will be able to use internet. If ethernet gets connected again, and has backhaul connectivity, it will become default. Bug: 180077540 Tests: Builds, Boots, EthernetServiceTests Change-Id: I26d720994ecb35f6529358a53e115091e7817c2f --- .../server/ethernet/EthernetNetworkFactory.java | 16 ++++++++++++++++ .../ethernet/EthernetNetworkFactoryTest.java | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 26532d7355..2886cf1e3d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -346,6 +346,11 @@ public class EthernetNetworkFactory extends NetworkFactory { mHandler.post(() -> updateLinkProperties(newLp)); } + @Override + public void onReachabilityLost(String logMsg) { + mHandler.post(() -> updateNeighborLostEvent(logMsg)); + } + @Override public void onQuit() { mIpClient = null; @@ -479,6 +484,17 @@ public class EthernetNetworkFactory extends NetworkFactory { } } + void updateNeighborLostEvent(String logMsg) { + Log.i(TAG, "updateNeighborLostEvent " + logMsg); + // Reachability lost will be seen only if the gateway is not reachable. + // Since ethernet FW doesn't have the mechanism to scan for new networks + // like WiFi, simply restart. + // If there is a better network, that will become default and apps + // will be able to use internet. If ethernet gets connected again, + // and has backhaul connectivity, it will become default. + restart(); + } + /** Returns true if state has been modified */ boolean updateLinkState(boolean up) { if (mLinkUp == up) return false; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 0cd9c1811e..6422358068 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -434,4 +434,20 @@ public class EthernetNetworkFactoryTest { ConnectivityManager.TYPE_NONE); mNetFactory.removeInterface(iface); } + + @Test + public void testReachabilityLoss() throws Exception { + String iface = "eth0"; + createAndVerifyProvisionedInterface(iface); + + mIpClientCallbacks.onReachabilityLost("ReachabilityLost"); + mLooper.dispatchAll(); + + // Reachability loss should trigger a stop and start, since the interface is still there + verify(mIpClient).shutdown(); + verify(mNetworkAgent).unregister(); + + verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); + verify(mIpClient).startProvisioning(any()); + } } From 88c47a283bc68085b3137df59a28e3b6fb54c8ba Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Thu, 16 Dec 2021 02:38:40 +0000 Subject: [PATCH 710/881] Remove NetdService usage from EthernetTracker. Ethernet service related files are going to be moved into Connectivity module. So, NetdService won't be visible to EthernetTracker since it's a hidden class. Alternatively, get the INetd instance from system service instead. Bug: 210586283 Test: atest FrameworksNetTests Test: atest EthernetServiceTests Change-Id: Iea021ac25cbe4b8836fdab2cd6b4bd3ead5bf725 --- .../src/com/android/server/ethernet/EthernetTracker.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 86aefbcff2..beb950cb9d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -40,7 +40,6 @@ import android.os.ServiceManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; -import android.net.util.NetdService; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; @@ -124,7 +123,9 @@ final class EthernetTracker { // The services we use. IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); mNMService = INetworkManagementService.Stub.asInterface(b); - mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance"); + mNetd = INetd.Stub.asInterface( + (IBinder) context.getSystemService(Context.NETD_SERVICE)); + Objects.requireNonNull(mNetd, "could not get netd instance"); // Interface match regex. updateIfaceMatchRegexp(); From d3d8f41f2bc0595a634d16177b1ea5819dd55637 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Tue, 14 Dec 2021 09:38:32 +0000 Subject: [PATCH 711/881] Move Ethernet related files to f/b/packages/ConnectivityT. ethernet-service is going to be moved into Connectivity mainline module. Move all ethernet related files in f/b/ to f/b/packages/ConnectivityT so that it's easier to migrate these files to Connectivity module finally after clearing the hidden API usages. Below files to be moved: Ethernet framework related files: - EthernetManager.java - EthernetNetworkSpecifier.java - IEthernetManager.aidl - IEthernetServiceListener.aidl - ITetheredInterfaceCallback.aidl Ethernet service related files: - IpConfigStore.java(EthernetConfigStore has dependency on the class) For the ethernet-service related files, keep it as-is temproraliy and fix the hiden API dependencies in f/opt/net/ethernet/. After this work is done, then migrating the whole of ethernet folder to Connectivity module completely. This CL also fixes some minor errors of code style format to pass the code style check. Bug: 210586283 Test: build pass atest FrameworksNetTests atest EthernetServiceTests Change-Id: Ib359d29d5221105f648bc4194c6d6dbe4cc6e3e5 --- framework-t/Sources.bp | 18 +++++++++++ .../src}/android/net/EthernetManager.java | 0 .../android/net/EthernetNetworkSpecifier.java | 0 .../src}/android/net/IEthernetManager.aidl | 0 .../android/net/IEthernetServiceListener.aidl | 0 .../net/ITetheredInterfaceCallback.aidl | 0 service-t/Sources.bp | 14 ++++++++ .../com/android/server/net/IpConfigStore.java | 32 +++++++++++++------ 8 files changed, 54 insertions(+), 10 deletions(-) rename {core/java => framework-t/src}/android/net/EthernetManager.java (100%) rename {core/java => framework-t/src}/android/net/EthernetNetworkSpecifier.java (100%) rename {core/java => framework-t/src}/android/net/IEthernetManager.aidl (100%) rename {core/java => framework-t/src}/android/net/IEthernetServiceListener.aidl (100%) rename {core/java => framework-t/src}/android/net/ITetheredInterfaceCallback.aidl (100%) rename {services/core/java => service-t/src}/com/android/server/net/IpConfigStore.java (95%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 931a55b27d..0bda923f23 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -114,6 +114,23 @@ filegroup { ], } +// Ethernet related libraries. + +filegroup { + name: "framework-connectivity-ethernet-sources", + srcs: [ + "src/android/net/EthernetManager.java", + "src/android/net/EthernetNetworkSpecifier.java", + "src/android/net/IEthernetManager.aidl", + "src/android/net/IEthernetServiceListener.aidl", + "src/android/net/ITetheredInterfaceCallback.aidl", + ], + path: "src", + visibility: [ + "//visibility:private", + ], +} + // Connectivity-T common libraries. filegroup { @@ -130,6 +147,7 @@ filegroup { filegroup { name: "framework-connectivity-tiramisu-sources", srcs: [ + ":framework-connectivity-ethernet-sources", ":framework-connectivity-ipsec-sources", ":framework-connectivity-netstats-sources", ":framework-connectivity-nsd-sources", diff --git a/core/java/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java similarity index 100% rename from core/java/android/net/EthernetManager.java rename to framework-t/src/android/net/EthernetManager.java diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/framework-t/src/android/net/EthernetNetworkSpecifier.java similarity index 100% rename from core/java/android/net/EthernetNetworkSpecifier.java rename to framework-t/src/android/net/EthernetNetworkSpecifier.java diff --git a/core/java/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl similarity index 100% rename from core/java/android/net/IEthernetManager.aidl rename to framework-t/src/android/net/IEthernetManager.aidl diff --git a/core/java/android/net/IEthernetServiceListener.aidl b/framework-t/src/android/net/IEthernetServiceListener.aidl similarity index 100% rename from core/java/android/net/IEthernetServiceListener.aidl rename to framework-t/src/android/net/IEthernetServiceListener.aidl diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/framework-t/src/android/net/ITetheredInterfaceCallback.aidl similarity index 100% rename from core/java/android/net/ITetheredInterfaceCallback.aidl rename to framework-t/src/android/net/ITetheredInterfaceCallback.aidl diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 7b8817692b..97dfb64b33 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -61,11 +61,25 @@ filegroup { ], } +// Ethernet related libraries. + +filegroup { + name: "services.connectivity-ethernet-sources", + srcs: [ + "src/com/android/server/net/IpConfigStore.java", + ], + path: "src", + visibility: [ + "//frameworks/opt/net/ethernet", + ], +} + // Connectivity-T common libraries. filegroup { name: "services.connectivity-tiramisu-sources", srcs: [ + ":services.connectivity-ethernet-sources", ":services.connectivity-ipsec-sources", ":services.connectivity-netstats-sources", ":services.connectivity-nsd-sources", diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/service-t/src/com/android/server/net/IpConfigStore.java similarity index 95% rename from services/core/java/com/android/server/net/IpConfigStore.java rename to service-t/src/com/android/server/net/IpConfigStore.java index d17dbde496..3a9a544155 100644 --- a/services/core/java/com/android/server/net/IpConfigStore.java +++ b/service-t/src/com/android/server/net/IpConfigStore.java @@ -44,6 +44,9 @@ import java.net.InetAddress; import java.util.ArrayList; import java.util.List; +/** + * This class provides an API to store and manage L3 network IP configuration. + */ public class IpConfigStore { private static final String TAG = "IpConfigStore"; private static final boolean DBG = false; @@ -78,6 +81,9 @@ public class IpConfigStore { return writeConfig(out, configKey, config, IPCONFIG_FILE_VERSION); } + /** + * Write the IP configuration with the given parameters to {@link DataOutputStream}. + */ @VisibleForTesting public static boolean writeConfig(DataOutputStream out, String configKey, IpConfiguration config, int version) throws IOException { @@ -154,10 +160,10 @@ public class IpConfigStore { break; case UNASSIGNED: /* Ignore */ - break; - default: - loge("Ignore invalid proxy settings while writing"); - break; + break; + default: + loge("Ignore invalid proxy settings while writing"); + break; } if (written) { @@ -177,7 +183,7 @@ public class IpConfigStore { } /** - * @Deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead. + * @deprecated use {@link #writeIpConfigurations(String, ArrayMap)} instead. * New method uses string as network identifier which could be interface name or MAC address or * other token. */ @@ -186,22 +192,28 @@ public class IpConfigStore { final SparseArray networks) { mWriter.write(filePath, out -> { out.writeInt(IPCONFIG_FILE_VERSION); - for(int i = 0; i < networks.size(); i++) { + for (int i = 0; i < networks.size(); i++) { writeConfig(out, String.valueOf(networks.keyAt(i)), networks.valueAt(i)); } }); } + /** + * Write the IP configuration associated to the target networks to the destination path. + */ public void writeIpConfigurations(String filePath, ArrayMap networks) { mWriter.write(filePath, out -> { out.writeInt(IPCONFIG_FILE_VERSION); - for(int i = 0; i < networks.size(); i++) { + for (int i = 0; i < networks.size(); i++) { writeConfig(out, networks.keyAt(i), networks.valueAt(i)); } }); } + /** + * Read the IP configuration from the destination path to {@link BufferedInputStream}. + */ public static ArrayMap readIpConfigurations(String filePath) { BufferedInputStream bufferedInputStream; try { @@ -215,7 +227,7 @@ public class IpConfigStore { return readIpConfigurations(bufferedInputStream); } - /** @Deprecated use {@link #readIpConfigurations(String)} */ + /** @deprecated use {@link #readIpConfigurations(String)} */ @Deprecated public static SparseArray readIpAndProxyConfigurations(String filePath) { BufferedInputStream bufferedInputStream; @@ -230,7 +242,7 @@ public class IpConfigStore { return readIpAndProxyConfigurations(bufferedInputStream); } - /** @Deprecated use {@link #readIpConfigurations(InputStream)} */ + /** @deprecated use {@link #readIpConfigurations(InputStream)} */ @Deprecated public static SparseArray readIpAndProxyConfigurations( InputStream inputStream) { @@ -420,7 +432,7 @@ public class IpConfigStore { if (in != null) { try { in.close(); - } catch (Exception e) {} + } catch (Exception e) { } } } From a2a6b960a38f06564a78398cb4c4704f4bffd02d Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 14 Dec 2021 21:16:09 +0800 Subject: [PATCH 712/881] Remove unused import in IpSecAlgorithm HexDump is an internal class which cannot be visible to mainline module. Remove it since this is unused. Bug: 204153604 Test: FrameworksNetTests Change-Id: Ie65e7eff8464487719c3124005a097a500ba21c6 --- framework-t/src/android/net/IpSecAlgorithm.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework-t/src/android/net/IpSecAlgorithm.java b/framework-t/src/android/net/IpSecAlgorithm.java index 5e647fe2f9..a84e7a9c63 100644 --- a/framework-t/src/android/net/IpSecAlgorithm.java +++ b/framework-t/src/android/net/IpSecAlgorithm.java @@ -23,7 +23,6 @@ import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.HexDump; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; From 30a2b03042e26b9d42919e61f005fe3e1be8884f Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 15 Dec 2021 23:27:18 +0800 Subject: [PATCH 713/881] Make IpSecManager.DIRECTION_FWD @SystemApi IpSecManager.DIRECTION_FWD is used by VcnGatewayConnection and it will be not visible to platform after IpSec was moved into Connectivity mainline module. Therefore, make DIRECTION_FWD @SystemApi so that it can be used by VcnGatewayConnection. Bug: 204153604 Test: FrameworksNetTests Change-Id: I80dc2a5b4940504820cee0d8e2d2e59ef3fcca18 --- framework-t/src/android/net/IpSecManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java index 837629911c..0b266b226c 100644 --- a/framework-t/src/android/net/IpSecManager.java +++ b/framework-t/src/android/net/IpSecManager.java @@ -86,6 +86,7 @@ public final class IpSecManager { * * @hide */ + @SystemApi(client = MODULE_LIBRARIES) public static final int DIRECTION_FWD = 2; /** From 051de2cd49d1d134c8918d15a2eb87ad21d6ac16 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 17 Dec 2021 08:37:27 +0000 Subject: [PATCH 714/881] [MS05] Fix NetworkTemplate lint errors This change also defines some IntDef annotations that will be used in the follow-up CLs. Test: TH Bug: 204830222 Change-Id: Iba5e714a1304fdfd154379415dcc5d0f9b7b1b29 --- .../src/android/net/NetworkTemplate.java | 134 ++++++++++++++++-- 1 file changed, 126 insertions(+), 8 deletions(-) diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 8b9c14df7d..cb5a025278 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -24,6 +24,8 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.NetworkIdentity.OEM_NONE; +import static android.net.NetworkIdentity.OEM_PAID; +import static android.net.NetworkIdentity.OEM_PRIVATE; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; @@ -35,6 +37,7 @@ import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; import static android.net.wifi.WifiInfo.sanitizeSsid; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; @@ -48,6 +51,8 @@ import android.text.TextUtils; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -60,18 +65,58 @@ import java.util.Objects; * * @hide */ -public class NetworkTemplate implements Parcelable { - private static final String TAG = "NetworkTemplate"; +// @SystemApi(client = MODULE_LIBRARIES) +public final class NetworkTemplate implements Parcelable { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "MATCH_" }, value = { + MATCH_MOBILE, + MATCH_WIFI, + MATCH_ETHERNET, + MATCH_BLUETOOTH, + MATCH_CARRIER + }) + public @interface TemplateMatchRule{} + /** Match rule to match cellular networks with given Subscriber Ids. */ public static final int MATCH_MOBILE = 1; + /** Match rule to match wifi networks. */ public static final int MATCH_WIFI = 4; + /** Match rule to match ethernet networks. */ public static final int MATCH_ETHERNET = 5; + /** + * Match rule to match all cellular networks. + * + * @hide + */ public static final int MATCH_MOBILE_WILDCARD = 6; + /** + * Match rule to match all wifi networks. + * + * @hide + */ public static final int MATCH_WIFI_WILDCARD = 7; + /** Match rule to match bluetooth networks. */ public static final int MATCH_BLUETOOTH = 8; + /** + * Match rule to match networks with {@link Connectivity#TYPE_PROXY} as the legacy network type. + * + * @hide + */ public static final int MATCH_PROXY = 9; + /** + * Match rule to match all networks with subscriberId inside the template. Some carriers + * may offer non-cellular networks like WiFi, which will be matched by this rule. + */ public static final int MATCH_CARRIER = 10; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "SUBSCRIBER_ID_MATCH_RULE_" }, value = { + SUBSCRIBER_ID_MATCH_RULE_EXACT, + SUBSCRIBER_ID_MATCH_RULE_ALL + }) + public @interface SubscriberIdMatchRule{} /** * Value of the match rule of the subscriberId to match networks with specific subscriberId. */ @@ -92,8 +137,6 @@ public class NetworkTemplate implements Parcelable { /** * Include all network types when filtering. This is meant to merge in with the * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. - * - * @hide */ public static final int NETWORK_TYPE_ALL = -1; /** @@ -106,21 +149,37 @@ public class NetworkTemplate implements Parcelable { */ public static final int NETWORK_TYPE_5G_NSA = -2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "OEM_MANAGED_" }, value = { + OEM_MANAGED_ALL, + OEM_MANAGED_NO, + OEM_MANAGED_YES, + OEM_MANAGED_PAID, + OEM_MANAGED_PRIVATE + }) + public @interface OemManaged{} + /** * Value to match both OEM managed and unmanaged networks (all networks). - * @hide */ public static final int OEM_MANAGED_ALL = -1; /** * Value to match networks which are not OEM managed. - * @hide */ public static final int OEM_MANAGED_NO = OEM_NONE; /** * Value to match any OEM managed network. - * @hide */ public static final int OEM_MANAGED_YES = -2; + /** + * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}. + */ + public static final int OEM_MANAGED_PAID = OEM_PAID; + /** + * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}. + */ + public static final int OEM_MANAGED_PRIVATE = OEM_PRIVATE; private static boolean isKnownMatchRule(final int rule) { switch (rule) { @@ -142,6 +201,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with * the given IMSI. + * + * @hide */ @UnsupportedAppUsage public static NetworkTemplate buildTemplateMobileAll(String subscriberId) { @@ -152,6 +213,8 @@ public class NetworkTemplate implements Parcelable { * Template to match cellular networks with the given IMSI, {@code ratType} and * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}. + * + * @hide */ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, @NetworkType int ratType, int metered) { @@ -168,6 +231,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to match metered {@link ConnectivityManager#TYPE_MOBILE} networks, * regardless of IMSI. + * + * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static NetworkTemplate buildTemplateMobileWildcard() { @@ -177,6 +242,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks, * regardless of SSID. + * + * @hide */ @UnsupportedAppUsage public static NetworkTemplate buildTemplateWifiWildcard() { @@ -185,6 +252,7 @@ public class NetworkTemplate implements Parcelable { return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null); } + /** @hide */ @Deprecated @UnsupportedAppUsage public static NetworkTemplate buildTemplateWifi() { @@ -194,6 +262,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the * given SSID. + * + * @hide */ public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) { Objects.requireNonNull(networkId); @@ -221,6 +291,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to combine all {@link ConnectivityManager#TYPE_ETHERNET} style * networks together. + * + * @hide */ @UnsupportedAppUsage public static NetworkTemplate buildTemplateEthernet() { @@ -230,6 +302,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style * networks together. + * + * @hide */ public static NetworkTemplate buildTemplateBluetooth() { return new NetworkTemplate(MATCH_BLUETOOTH, null, null); @@ -238,6 +312,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to combine all {@link ConnectivityManager#TYPE_PROXY} style * networks together. + * + * @hide */ public static NetworkTemplate buildTemplateProxy() { return new NetworkTemplate(MATCH_PROXY, null, null); @@ -245,6 +321,8 @@ public class NetworkTemplate implements Parcelable { /** * Template to match all metered carrier networks with the given IMSI. + * + * @hide */ public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { Objects.requireNonNull(subscriberId); @@ -298,12 +376,14 @@ public class NetworkTemplate implements Parcelable { } } + /** @hide */ // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S) @UnsupportedAppUsage public NetworkTemplate(int matchRule, String subscriberId, String networkId) { this(matchRule, subscriberId, new String[] { subscriberId }, networkId); } + /** @hide */ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId) { // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates @@ -316,6 +396,7 @@ public class NetworkTemplate implements Parcelable { OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); } + /** @hide */ // TODO: Remove it after updating all of the caller. public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId, int metered, int roaming, int defaultNetwork, int subType, @@ -324,6 +405,7 @@ public class NetworkTemplate implements Parcelable { defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT); } + /** @hide */ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String networkId, int metered, int roaming, int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) { @@ -360,7 +442,7 @@ public class NetworkTemplate implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mMatchRule); dest.writeString(mSubscriberId); dest.writeStringArray(mMatchSubscriberIds); @@ -448,6 +530,7 @@ public class NetworkTemplate implements Parcelable { } } + /** @hide */ public boolean isMatchRuleMobile() { switch (mMatchRule) { case MATCH_MOBILE: @@ -458,6 +541,12 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Check if the template can be persisted into disk. + * + * @hide + */ + // TODO: Move to the NetworkPolicy. public boolean isPersistable() { switch (mMatchRule) { case MATCH_MOBILE_WILDCARD: @@ -476,11 +565,18 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Get match rule of the template. See {@code MATCH_*}. + */ @UnsupportedAppUsage public int getMatchRule() { return mMatchRule; } + /** + * Get subscriber Id of the template. + */ + @Nullable @UnsupportedAppUsage public String getSubscriberId() { return mSubscriberId; @@ -490,16 +586,25 @@ public class NetworkTemplate implements Parcelable { return mNetworkId; } + /** + * Get Subscriber Id Match Rule of the template. + */ public int getSubscriberIdMatchRule() { return mSubscriberIdMatchRule; } + /** + * Get meteredness filter of the template. + */ + @NetworkStats.Meteredness public int getMeteredness() { return mMetered; } /** * Test if given {@link NetworkIdentity} matches this template. + * + * @hide */ public boolean matches(NetworkIdentity ident) { if (!matchesMetered(ident)) return false; @@ -565,6 +670,8 @@ public class NetworkTemplate implements Parcelable { * Check if this template matches {@code subscriberId}. Returns true if this * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a * {@code mMatchSubscriberIds} array that contains {@code subscriberId}. + * + * @hide */ public boolean matchesSubscriberId(@Nullable String subscriberId) { return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL @@ -599,10 +706,13 @@ public class NetworkTemplate implements Parcelable { * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}. * * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. + * + * @hide */ // TODO: 1. Consider move this to TelephonyManager if used by other modules. // 2. Consider make this configurable. // 3. Use TelephonyManager APIs when available. + // TODO: @SystemApi when ready. public static int getCollapsedRatType(int ratType) { switch (ratType) { case TelephonyManager.NETWORK_TYPE_GPRS: @@ -639,7 +749,10 @@ public class NetworkTemplate implements Parcelable { /** * Return all supported collapsed RAT types that could be returned by * {@link #getCollapsedRatType(int)}. + * + * @hide */ + // TODO: @SystemApi when ready. @NonNull public static final int[] getAllCollapsedRatTypes() { final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); @@ -779,6 +892,8 @@ public class NetworkTemplate implements Parcelable { * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. * TODO: remove and use {@link #normalize(NetworkTemplate, List)}. + * + * @hide */ @UnsupportedAppUsage public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { @@ -797,7 +912,10 @@ public class NetworkTemplate implements Parcelable { * For example, given an incoming template matching B, and the currently * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. + * + * @hide */ + // TODO: @SystemApi when ready. public static NetworkTemplate normalize(NetworkTemplate template, List mergedList) { // Now there are several types of network which uses SubscriberId to store network // information. For instances: From 46429b7dedc44b3bcc9053d5016af9e2c78d6b1a Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 13 Dec 2021 07:52:45 +0000 Subject: [PATCH 715/881] [MS10.1] Move multiplySafeByRational to NetworkStatsUtils Since NetworkStats related code will be moved to the module. multiplySafeByRational in the NetworkUtilsInternal cannot be accessed after that. Thus, create another utils class that will be moved with NetworkStats code and put the function into it. Test: atest NetworkStaticLibTests:com.android.net.moduletests.util.NetworkStatsUtilsTest Bug: 204830222 Change-Id: I96f3ac02e57b7325ed53988285770f478dee529e --- framework-t/src/android/net/NetworkStats.java | 2 +- framework-t/src/android/net/NetworkStatsCollection.java | 2 +- framework-t/src/android/net/NetworkStatsHistory.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java index c7ffc19338..1986b83b12 100644 --- a/framework-t/src/android/net/NetworkStats.java +++ b/framework-t/src/android/net/NetworkStats.java @@ -16,7 +16,7 @@ package android.net; -import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; +import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; import android.annotation.IntDef; import android.annotation.NonNull; diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 0d3b9ed4e3..8d1347e25b 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -30,7 +30,7 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; import static android.text.format.DateUtils.WEEK_IN_MILLIS; -import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; +import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java index a875e1ad45..3eef4ee6f8 100644 --- a/framework-t/src/android/net/NetworkStatsHistory.java +++ b/framework-t/src/android/net/NetworkStatsHistory.java @@ -28,8 +28,8 @@ import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; import static android.text.format.DateUtils.SECOND_IN_MILLIS; -import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational; import static com.android.internal.util.ArrayUtils.total; +import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; From 155cb5cced030f245f1b6602b72b49e18cdb91c7 Mon Sep 17 00:00:00 2001 From: lifr Date: Tue, 21 Dec 2021 11:07:02 +0800 Subject: [PATCH 716/881] [DU02]Remove DevicePolicyManagerInternal from NetworkStatsAccess NetworkStatsAccess is using DevicePolicyManagerInternal APIs, which cannot be accessed after moving into the mainline module. So, replace and remove those hidden API usages. Bug: 207100745 Test: atest NetworkStatsAccessTest Change-Id: I0802148050869d92e1f09d1d657034380029f236 --- .../src/android/net/NetworkStatsAccess.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java index 3885a9e6d5..591605d952 100644 --- a/framework-t/src/android/net/NetworkStatsAccess.java +++ b/framework-t/src/android/net/NetworkStatsAccess.java @@ -24,7 +24,7 @@ import static android.net.TrafficStats.UID_TETHERING; import android.Manifest; import android.annotation.IntDef; import android.app.AppOpsManager; -import android.app.admin.DevicePolicyManagerInternal; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; @@ -32,8 +32,6 @@ import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; -import com.android.server.LocalServices; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -109,8 +107,7 @@ public final class NetworkStatsAccess { /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */ public static @NetworkStatsAccess.Level int checkAccessLevel( Context context, int callingUid, String callingPackage) { - final DevicePolicyManagerInternal dpmi = LocalServices.getService( - DevicePolicyManagerInternal.class); + final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class); final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); boolean hasCarrierPrivileges; @@ -123,8 +120,9 @@ public final class NetworkStatsAccess { Binder.restoreCallingIdentity(token); } - final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); + final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage); final int appId = UserHandle.getAppId(callingUid); + if (hasCarrierPrivileges || isDeviceOwner || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { // Carrier-privileged apps and device owners, and the system (including the @@ -139,8 +137,8 @@ public final class NetworkStatsAccess { } //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode. - boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid) - || dpmi.isActiveDeviceOwner(callingUid)); + boolean isProfileOwner = mDpm != null && (mDpm.isProfileOwnerApp(callingPackage) + || mDpm.isDeviceOwnerApp(callingPackage)); if (isProfileOwner) { // Apps with the AppOps permission, profile owners, and apps with the privileged // permission can access data usage for all apps in this user/profile. From 8cc97a830b69cd7bdf0ea48a4583380c890e0dc2 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Tue, 21 Dec 2021 07:09:39 +0000 Subject: [PATCH 717/881] Replace Preconditions.checkNotNull with Objects.requireNonNull. Ethernet service related files are going to be moved into Connectivity mainline module. Replace the Preconditions.checkNotNull usage in EthernetNetworkFactory with Objects.requireNonNull. Bug: 210586283 Test: atest EthernetServiceTests Change-Id: Ibeaf687f706e8400f825cb2ca97bb1341774a97d --- .../com/android/server/ethernet/EthernetNetworkFactory.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 2886cf1e3d..a9f8b47fa1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -16,8 +16,6 @@ package com.android.server.ethernet; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -370,7 +368,7 @@ public class EthernetNetworkFactory extends NetworkFactory { @NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory, Dependencies deps) { name = ifaceName; - mCapabilities = checkNotNull(capabilities); + mCapabilities = Objects.requireNonNull(capabilities); mHandler = handler; mContext = context; mNetworkFactory = networkFactory; From 6e1cb800117079740f4e0f68087f6a90ee4ffbbe Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Tue, 21 Dec 2021 07:35:11 +0000 Subject: [PATCH 718/881] Import InterfaceParams class from f/libs/net/common. Ethernet service related files are going to be moved into Connectivity mainline module. Import InterfaceParams class in EthernetNetworkFactory from f/libs/net/common, which is visible to Connectivity module. Bug: 210586283 Test: atest EthernetServiceTests Change-Id: I98ebb04cc3c2b685464e7f2689424794957088b3 --- .../src/com/android/server/ethernet/EthernetNetworkFactory.java | 2 +- .../com/android/server/ethernet/EthernetNetworkFactoryTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 2886cf1e3d..fc26a6c135 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -37,7 +37,6 @@ import android.net.ip.IIpClient; import android.net.ip.IpClientCallbacks; import android.net.ip.IpClientUtil; import android.net.shared.ProvisioningConfiguration; -import android.net.util.InterfaceParams; import android.os.ConditionVariable; import android.os.Handler; import android.os.Looper; @@ -49,6 +48,7 @@ import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; +import com.android.net.module.util.InterfaceParams; import java.io.FileDescriptor; import java.util.Objects; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 6422358068..4abdf030ac 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -44,7 +44,6 @@ import android.net.NetworkProvider; import android.net.NetworkRequest; import android.net.ip.IIpClient; import android.net.ip.IpClientCallbacks; -import android.net.util.InterfaceParams; import android.os.Handler; import android.os.Looper; import android.os.test.TestLooper; @@ -53,6 +52,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; +import com.android.net.module.util.InterfaceParams; import org.junit.After; import org.junit.Before; From 2c9441062097bf3501caabb60e5c876b9b3f7d85 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 16 Dec 2021 02:07:21 +0000 Subject: [PATCH 719/881] [MS12.1] Support NetworkTemplate builder In current design, NeworkTemplate has a lot of buildTemplate* functions to create various type of templates. These functions do not have any flexibility to add any dimension. Thus, if there is a need to add a dimension, the typical ways are: 1. Add one parameter to the buildTemplate* function and change all callers. 2. Use the NetworkTemplate constructors directly. And add one more parameter if it doesn't fulfill the needs. These codes are painful to maintain in the future if they are exposed as system api since they are lack of flexibility. Thus, introduce a builder class to NetworkTemplate to address this problem. Test: atest NetworkTemplateTest Bug: 204830222 Change-Id: I49fab236bac392563b1290d69573ad1415fda734 --- .../src/android/net/NetworkTemplate.java | 294 +++++++++++++++++- 1 file changed, 277 insertions(+), 17 deletions(-) diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index cb5a025278..7dd04c5d42 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -47,6 +47,7 @@ import android.os.Parcelable; import android.telephony.Annotation.NetworkType; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArraySet; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; @@ -58,6 +59,9 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; /** * Predicate used to match {@link NetworkIdentity}, usually when collecting @@ -119,21 +123,31 @@ public final class NetworkTemplate implements Parcelable { public @interface SubscriberIdMatchRule{} /** * Value of the match rule of the subscriberId to match networks with specific subscriberId. + * + * @hide */ public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0; /** * Value of the match rule of the subscriberId to match networks with any subscriberId which * includes null and non-null. + * + * @hide */ public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1; - /** - * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that - * should be fixed), so it's not possible to want to match null vs - * non-null. Therefore it's fine to use null as a sentinel for Network ID. - */ + // TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL. + /** @hide */ public static final String WIFI_NETWORKID_ALL = null; + /** + * Wi-Fi Network Key is never supposed to be null (if it is, it is a bug that + * should be fixed), so it's not possible to want to match null vs + * non-null. Therefore it's fine to use null as a sentinel for Wifi Network Key. + * + * @hide + */ + public static final String WIFI_NETWORK_KEY_ALL = WIFI_NETWORKID_ALL; + /** * Include all network types when filtering. This is meant to merge in with the * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. @@ -278,7 +292,10 @@ public final class NetworkTemplate implements Parcelable { * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID, * and IMSI. * - * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID. + * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code networkId} to get result regardless + * of SSID. + * + * @hide */ public static NetworkTemplate buildTemplateWifi(@Nullable String networkId, @Nullable String subscriberId) { @@ -345,6 +362,7 @@ public final class NetworkTemplate implements Parcelable { */ private final String[] mMatchSubscriberIds; + // TODO: Change variable name to match the Api surface. private final String mNetworkId; // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. @@ -361,14 +379,14 @@ public final class NetworkTemplate implements Parcelable { // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}. private final int mOemManaged; - private void checkValidSubscriberIdMatchRule() { - switch (mMatchRule) { + private static void checkValidSubscriberIdMatchRule(int matchRule, int subscriberIdMatchRule) { + switch (matchRule) { case MATCH_MOBILE: case MATCH_CARRIER: // MOBILE and CARRIER templates must always specify a subscriber ID. - if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { - throw new IllegalArgumentException("Invalid SubscriberIdMatchRule" - + "on match rule: " + getMatchRuleName(mMatchRule)); + if (subscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { + throw new IllegalArgumentException("Invalid SubscriberIdMatchRule " + + "on match rule: " + getMatchRuleName(matchRule)); } return; default: @@ -421,7 +439,7 @@ public final class NetworkTemplate implements Parcelable { mSubType = subType; mOemManaged = oemManaged; mSubscriberIdMatchRule = subscriberIdMatchRule; - checkValidSubscriberIdMatchRule(); + checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule); if (!isKnownMatchRule(matchRule)) { throw new IllegalArgumentException("Unknown network template rule " + matchRule + " will not match any identity."); @@ -519,7 +537,7 @@ public final class NetworkTemplate implements Parcelable { return false; } - private String subscriberIdMatchRuleToString(int rule) { + private static String subscriberIdMatchRuleToString(int rule) { switch (rule) { case SUBSCRIBER_ID_MATCH_RULE_EXACT: return "EXACT_MATCH"; @@ -555,7 +573,7 @@ public final class NetworkTemplate implements Parcelable { case MATCH_CARRIER: return mSubscriberId != null; case MATCH_WIFI: - if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) + if (Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL) && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { return false; } @@ -570,7 +588,16 @@ public final class NetworkTemplate implements Parcelable { */ @UnsupportedAppUsage public int getMatchRule() { - return mMatchRule; + // Wildcard rules are not exposed. For external callers, convert wildcard rules to + // exposed rules before returning. + switch (mMatchRule) { + case MATCH_MOBILE_WILDCARD: + return MATCH_MOBILE; + case MATCH_WIFI_WILDCARD: + return MATCH_WIFI; + default: + return mMatchRule; + } } /** @@ -582,12 +609,33 @@ public final class NetworkTemplate implements Parcelable { return mSubscriberId; } + /** + * Get set of subscriber Ids of the template. + */ + @NonNull + public Set getSubscriberIds() { + return new ArraySet<>(Arrays.asList(mMatchSubscriberIds)); + } + + /** + * Get Wifi Network Key of the template. See {@link WifiInfo#getCurrentNetworkKey()}. + */ + @Nullable + public String getWifiNetworkKey() { + return mNetworkId; + } + + /** @hide */ + // TODO: Remove this and replace all callers with {@link #getWifiNetworkKey()}. + @Nullable public String getNetworkId() { return mNetworkId; } /** * Get Subscriber Id Match Rule of the template. + * + * @hide */ public int getSubscriberIdMatchRule() { return mSubscriberIdMatchRule; @@ -601,6 +649,38 @@ public final class NetworkTemplate implements Parcelable { return mMetered; } + /** + * Get roaming filter of the template. + */ + @NetworkStats.Roaming + public int getRoaming() { + return mRoaming; + } + + /** + * Get the default network status filter of the template. + */ + @NetworkStats.DefaultNetwork + public int getDefaultNetworkStatus() { + return mDefaultNetwork; + } + + /** + * Get the Radio Access Technology(RAT) type filter of the template. + */ + public int getRatType() { + return mSubType; + } + + /** + * Get the OEM managed filter of the template. See {@code OEM_MANAGED_*} or + * {@code android.net.NetworkIdentity#OEM_*}. + */ + @OemManaged + public int getOemManaged() { + return mOemManaged; + } + /** * Test if given {@link NetworkIdentity} matches this template. * @@ -680,10 +760,10 @@ public final class NetworkTemplate implements Parcelable { /** * Check if network with matching SSID. Returns true when the SSID matches, or when - * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}. + * {@code mNetworkId} is {@code WIFI_NETWORK_KEY_ALL}. */ private boolean matchesWifiNetworkId(@Nullable String networkId) { - return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL) + return Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL) || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId)); } @@ -948,4 +1028,184 @@ public final class NetworkTemplate implements Parcelable { return new NetworkTemplate[size]; } }; + + /** + * Builder class for NetworkTemplate. + */ + public static final class Builder { + private final int mMatchRule; + // Use a SortedSet to provide a deterministic order when fetching the first one. + @NonNull + private final SortedSet mMatchSubscriberIds = new TreeSet<>(); + @Nullable + private String mWifiNetworkKey; + + // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. + private int mMetered; + private int mRoaming; + private int mDefaultNetwork; + private int mRatType; + + // Bitfield containing OEM network properties {@code NetworkIdentity#OEM_*}. + private int mOemManaged; + + /** + * Creates a new Builder with given match rule to construct NetworkTemplate objects. + * + * @param matchRule the match rule of the template, see {@code MATCH_*}. + */ + public Builder(@TemplateMatchRule final int matchRule) { + assertRequestableMatchRule(matchRule); + // Initialize members with default values. + mMatchRule = matchRule; + mWifiNetworkKey = WIFI_NETWORK_KEY_ALL; + mMetered = METERED_ALL; + mRoaming = ROAMING_ALL; + mDefaultNetwork = DEFAULT_NETWORK_ALL; + mRatType = NETWORK_TYPE_ALL; + mOemManaged = OEM_MANAGED_ALL; + } + + /** + * Set the Subscriber Ids. Calling this function with an empty set represents + * the intention of matching any Subscriber Ids. + * + * @param subscriberIds the list of Subscriber Ids. + * @return this builder. + */ + @NonNull + public Builder setSubscriberIds(@NonNull Set subscriberIds) { + Objects.requireNonNull(subscriberIds); + mMatchSubscriberIds.clear(); + mMatchSubscriberIds.addAll(subscriberIds); + return this; + } + + /** + * Set the Wifi Network Key. + * + * @param wifiNetworkKey the Wifi Network Key, see {@link WifiInfo#getCurrentNetworkKey()}. + * Or null to match all networks. + * @return this builder. + */ + @NonNull + public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) { + mWifiNetworkKey = wifiNetworkKey; + return this; + } + + /** + * Set the meteredness filter. + * + * @param metered the meteredness filter. + * @return this builder. + */ + @NonNull + public Builder setMeteredness(@NetworkStats.Meteredness int metered) { + mMetered = metered; + return this; + } + + /** + * Set the roaming filter. + * + * @param roaming the roaming filter. + * @return this builder. + */ + @NonNull + public Builder setRoaming(@NetworkStats.Roaming int roaming) { + mRoaming = roaming; + return this; + } + + /** + * Set the default network status filter. + * + * @param defaultNetwork the default network status filter. + * @return this builder. + */ + @NonNull + public Builder setDefaultNetworkStatus(@NetworkStats.DefaultNetwork int defaultNetwork) { + mDefaultNetwork = defaultNetwork; + return this; + } + + /** + * Set the Radio Access Technology(RAT) type filter. + * + * @param ratType the Radio Access Technology(RAT) type filter. Use + * {@link #NETWORK_TYPE_ALL} to include all network types when filtering. + * See {@code TelephonyManager.NETWORK_TYPE_*}. + * @return this builder. + */ + @NonNull + public Builder setRatType(@NetworkType int ratType) { + // Input will be validated with the match rule when building the template. + mRatType = ratType; + return this; + } + + /** + * Set the OEM managed filter. + * + * @param oemManaged the match rule to match different type of OEM managed network or + * unmanaged networks. See {@code OEM_MANAGED_*}. + * @return this builder. + */ + @NonNull + public Builder setOemManaged(@OemManaged int oemManaged) { + mOemManaged = oemManaged; + return this; + } + + /** + * Check whether the match rule is requestable. + * + * @param matchRule the target match rule to be checked. + */ + private static void assertRequestableMatchRule(final int matchRule) { + if (!isKnownMatchRule(matchRule) + || matchRule == MATCH_PROXY + || matchRule == MATCH_MOBILE_WILDCARD + || matchRule == MATCH_WIFI_WILDCARD) { + throw new IllegalArgumentException("Invalid match rule: " + + getMatchRuleName(matchRule)); + } + } + + private void assertRequestableParameters() { + // TODO: Check all the input are legitimate. + } + + /** + * For backward compatibility, deduce match rule to a wildcard match rule + * if the Subscriber Ids are empty. + */ + private int getWildcardDeducedMatchRule() { + if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) { + return MATCH_MOBILE_WILDCARD; + } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty() + && mWifiNetworkKey == WIFI_NETWORK_KEY_ALL) { + return MATCH_WIFI_WILDCARD; + } + return mMatchRule; + } + + /** + * Builds the instance of the NetworkTemplate. + * + * @return the built instance of NetworkTemplate. + */ + @NonNull + public NetworkTemplate build() { + assertRequestableParameters(); + final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty() + ? SUBSCRIBER_ID_MATCH_RULE_ALL : SUBSCRIBER_ID_MATCH_RULE_EXACT; + return new NetworkTemplate(getWildcardDeducedMatchRule(), + mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(), + mMatchSubscriberIds.toArray(new String[0]), + mWifiNetworkKey, mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, + subscriberIdMatchRule); + } + } } From 682bebbf6065a83681782b70e323830829761e68 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 20 Dec 2021 16:54:47 +0000 Subject: [PATCH 720/881] [MS14] Move isPersistable to NetworkPolicy Since the NetworkTemplate serialization is done in the platform code. To decide whether the template is persistable should be also inside the platform along with the serialization logic. Test: atest NetworkPolicyTest Bug: 204830222 Change-Id: I15d17dda77e6a3e1ae11275915e3d2f6e2888639 --- .../src/android/net/NetworkTemplate.java | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 7dd04c5d42..d85291318f 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -559,30 +559,6 @@ public final class NetworkTemplate implements Parcelable { } } - /** - * Check if the template can be persisted into disk. - * - * @hide - */ - // TODO: Move to the NetworkPolicy. - public boolean isPersistable() { - switch (mMatchRule) { - case MATCH_MOBILE_WILDCARD: - case MATCH_WIFI_WILDCARD: - return false; - case MATCH_CARRIER: - return mSubscriberId != null; - case MATCH_WIFI: - if (Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL) - && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { - return false; - } - return true; - default: - return true; - } - } - /** * Get match rule of the template. See {@code MATCH_*}. */ From eb50ef2da7b7f60001266199df5706053faaaf47 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 22 Dec 2021 16:35:13 +0800 Subject: [PATCH 721/881] Replace Preconditions.checkNotNull with Objects.requireNonNull IpSec service is going to be moved into Connectivity module. Replace Preconditions.checkNotNull with Objects.requireNonNull to remove hidden API usages. Bug: 204153604 Test: FrameworksNetTests Change-Id: Iff7f76844d4126b0e17b62b4ce821449b5b6ce44 --- framework-t/src/android/net/IpSecManager.java | 5 ++--- .../src/android/net/IpSecTransform.java | 20 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java index 837629911c..ca9be1cc40 100644 --- a/framework-t/src/android/net/IpSecManager.java +++ b/framework-t/src/android/net/IpSecManager.java @@ -17,8 +17,6 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.NonNull; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; @@ -46,6 +44,7 @@ import java.io.IOException; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; +import java.util.Objects; /** * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply @@ -988,7 +987,7 @@ public final class IpSecManager { */ public IpSecManager(Context ctx, IIpSecService service) { mContext = ctx; - mService = checkNotNull(service, "missing service"); + mService = Objects.requireNonNull(service, "missing service"); } private static void maybeHandleServiceSpecificException(ServiceSpecificException sse) { diff --git a/framework-t/src/android/net/IpSecTransform.java b/framework-t/src/android/net/IpSecTransform.java index b48c1fdaf1..36199a046c 100644 --- a/framework-t/src/android/net/IpSecTransform.java +++ b/framework-t/src/android/net/IpSecTransform.java @@ -33,7 +33,6 @@ import android.os.ServiceSpecificException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.Preconditions; import dalvik.system.CloseGuard; @@ -41,6 +40,7 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.InetAddress; +import java.util.Objects; /** * This class represents a transform, which roughly corresponds to an IPsec Security Association. @@ -255,7 +255,7 @@ public final class IpSecTransform implements AutoCloseable { @NonNull public IpSecTransform.Builder setEncryption(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an encryption algorithm. - Preconditions.checkNotNull(algo); + Objects.requireNonNull(algo); mConfig.setEncryption(algo); return this; } @@ -270,7 +270,7 @@ public final class IpSecTransform implements AutoCloseable { @NonNull public IpSecTransform.Builder setAuthentication(@NonNull IpSecAlgorithm algo) { // TODO: throw IllegalArgumentException if algo is not an authentication algorithm. - Preconditions.checkNotNull(algo); + Objects.requireNonNull(algo); mConfig.setAuthentication(algo); return this; } @@ -290,7 +290,7 @@ public final class IpSecTransform implements AutoCloseable { */ @NonNull public IpSecTransform.Builder setAuthenticatedEncryption(@NonNull IpSecAlgorithm algo) { - Preconditions.checkNotNull(algo); + Objects.requireNonNull(algo); mConfig.setAuthenticatedEncryption(algo); return this; } @@ -311,7 +311,7 @@ public final class IpSecTransform implements AutoCloseable { @NonNull public IpSecTransform.Builder setIpv4Encapsulation( @NonNull IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) { - Preconditions.checkNotNull(localSocket); + Objects.requireNonNull(localSocket); mConfig.setEncapType(ENCAP_ESPINUDP); if (localSocket.getResourceId() == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Invalid UdpEncapsulationSocket"); @@ -348,8 +348,8 @@ public final class IpSecTransform implements AutoCloseable { @NonNull IpSecManager.SecurityParameterIndex spi) throws IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException, IOException { - Preconditions.checkNotNull(sourceAddress); - Preconditions.checkNotNull(spi); + Objects.requireNonNull(sourceAddress); + Objects.requireNonNull(spi); if (spi.getResourceId() == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Invalid SecurityParameterIndex"); } @@ -387,8 +387,8 @@ public final class IpSecTransform implements AutoCloseable { @NonNull IpSecManager.SecurityParameterIndex spi) throws IpSecManager.ResourceUnavailableException, IpSecManager.SpiUnavailableException, IOException { - Preconditions.checkNotNull(sourceAddress); - Preconditions.checkNotNull(spi); + Objects.requireNonNull(sourceAddress); + Objects.requireNonNull(spi); if (spi.getResourceId() == INVALID_RESOURCE_ID) { throw new IllegalArgumentException("Invalid SecurityParameterIndex"); } @@ -404,7 +404,7 @@ public final class IpSecTransform implements AutoCloseable { * @param context current context */ public Builder(@NonNull Context context) { - Preconditions.checkNotNull(context); + Objects.requireNonNull(context); mContext = context; mConfig = new IpSecConfig(); } From 4451b45f702a82301498045b557adc43b77e710c Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 21 Dec 2021 06:57:14 +0000 Subject: [PATCH 722/881] [MS15.1] Remove get/setSubscriberIdMatchRule dependencies Subscriber Id Match Rule won't be exposed as system Api. Callers should use Builder#setSubscriberIds or NetworkTemplate#getSubscriberIds to set/get the Subscriber Ids filter. An empty set in the paremter or return value represents the intention of matching any Subscriber Ids. Test: atest NetworkPolicyManagerServiceTest \ FrameworksNetTests Bug: 204830222 Change-Id: I12c54280b44c71e4737e82859dfe869794cc9c29 --- .../src/android/net/NetworkTemplate.java | 57 +++++-------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index d85291318f..5da8e259d0 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -51,6 +51,7 @@ import android.util.ArraySet; import com.android.internal.util.ArrayUtils; import com.android.net.module.util.NetworkIdentityUtils; +import com.android.net.module.util.NetworkStatsUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -114,27 +115,6 @@ public final class NetworkTemplate implements Parcelable { */ public static final int MATCH_CARRIER = 10; - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "SUBSCRIBER_ID_MATCH_RULE_" }, value = { - SUBSCRIBER_ID_MATCH_RULE_EXACT, - SUBSCRIBER_ID_MATCH_RULE_ALL - }) - public @interface SubscriberIdMatchRule{} - /** - * Value of the match rule of the subscriberId to match networks with specific subscriberId. - * - * @hide - */ - public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0; - /** - * Value of the match rule of the subscriberId to match networks with any subscriberId which - * includes null and non-null. - * - * @hide - */ - public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1; - // TODO: Remove this and replace all callers with WIFI_NETWORK_KEY_ALL. /** @hide */ public static final String WIFI_NETWORKID_ALL = null; @@ -235,11 +215,11 @@ public final class NetworkTemplate implements Parcelable { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_EXACT); + NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_EXACT); + NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @@ -285,7 +265,7 @@ public final class NetworkTemplate implements Parcelable { new String[] { null } /* matchSubscriberIds */, networkId, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_ALL); + NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL); } /** @@ -302,7 +282,7 @@ public final class NetworkTemplate implements Parcelable { return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId }, networkId, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_EXACT); + NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @@ -346,7 +326,7 @@ public final class NetworkTemplate implements Parcelable { return new NetworkTemplate(MATCH_CARRIER, subscriberId, new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, - SUBSCRIBER_ID_MATCH_RULE_EXACT); + NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } private final int mMatchRule; @@ -384,7 +364,7 @@ public final class NetworkTemplate implements Parcelable { case MATCH_MOBILE: case MATCH_CARRIER: // MOBILE and CARRIER templates must always specify a subscriber ID. - if (subscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) { + if (subscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL) { throw new IllegalArgumentException("Invalid SubscriberIdMatchRule " + "on match rule: " + getMatchRuleName(matchRule)); } @@ -411,7 +391,7 @@ public final class NetworkTemplate implements Parcelable { this(matchRule, subscriberId, matchSubscriberIds, networkId, (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, - OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT); + OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @hide */ @@ -420,7 +400,8 @@ public final class NetworkTemplate implements Parcelable { String networkId, int metered, int roaming, int defaultNetwork, int subType, int oemManaged) { this(matchRule, subscriberId, matchSubscriberIds, networkId, metered, roaming, - defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT); + defaultNetwork, subType, oemManaged, + NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @hide */ @@ -539,9 +520,9 @@ public final class NetworkTemplate implements Parcelable { private static String subscriberIdMatchRuleToString(int rule) { switch (rule) { - case SUBSCRIBER_ID_MATCH_RULE_EXACT: + case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT: return "EXACT_MATCH"; - case SUBSCRIBER_ID_MATCH_RULE_ALL: + case NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL: return "ALL"; default: return "Unknown rule " + rule; @@ -608,15 +589,6 @@ public final class NetworkTemplate implements Parcelable { return mNetworkId; } - /** - * Get Subscriber Id Match Rule of the template. - * - * @hide - */ - public int getSubscriberIdMatchRule() { - return mSubscriberIdMatchRule; - } - /** * Get meteredness filter of the template. */ @@ -730,7 +702,7 @@ public final class NetworkTemplate implements Parcelable { * @hide */ public boolean matchesSubscriberId(@Nullable String subscriberId) { - return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL + return mSubscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL || ArrayUtils.contains(mMatchSubscriberIds, subscriberId); } @@ -1176,7 +1148,8 @@ public final class NetworkTemplate implements Parcelable { public NetworkTemplate build() { assertRequestableParameters(); final int subscriberIdMatchRule = mMatchSubscriberIds.isEmpty() - ? SUBSCRIBER_ID_MATCH_RULE_ALL : SUBSCRIBER_ID_MATCH_RULE_EXACT; + ? NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL + : NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT; return new NetworkTemplate(getWildcardDeducedMatchRule(), mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(), mMatchSubscriberIds.toArray(new String[0]), From 54dcee39e92c339e1f25ab036a5e23528fe9cc34 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 14 Dec 2021 18:26:18 -0800 Subject: [PATCH 723/881] Stubbed net mgmt API methods in eth service Stubbed API methods in EthernetServiceImpl to be used for network management. Bug: 210487086 Bug: 210485380 Test: make, flash and boot and atest EthernetServiceTests Change-Id: I8bd5a6eca07d00e0f155b71e2960371989a13013 --- .../server/ethernet/EthernetServiceImpl.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 504b3da6cd..840806af18 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -16,11 +16,15 @@ package com.android.server.ethernet; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; +import android.net.IInternalNetworkManagementListener; import android.net.ITetheredInterfaceCallback; +import android.net.InternalNetworkUpdateRequest; import android.net.IpConfiguration; import android.os.Binder; import android.os.Handler; @@ -209,4 +213,24 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mHandler.dump(new PrintWriterPrinter(pw), "EthernetServiceImpl"); pw.decreaseIndent(); } + + @Override + public void updateConfiguration(@NonNull final String iface, + @NonNull final InternalNetworkUpdateRequest request, + @Nullable final IInternalNetworkManagementListener listener) { + Log.i(TAG, "updateConfiguration called with: iface=" + iface + + ", request=" + request + ", listener=" + listener); + } + + @Override + public void connectNetwork(@NonNull final String iface, + @Nullable final IInternalNetworkManagementListener listener) { + Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); + } + + @Override + public void disconnectNetwork(@NonNull final String iface, + @Nullable final IInternalNetworkManagementListener listener) { + Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); + } } From d03aa846f3f159f5d0c47da35171a6c8ac5af946 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 14 Dec 2021 18:12:40 -0800 Subject: [PATCH 724/881] aidl and Parcelable defintions for eth management aidl and Parcelable definitions neccessary for internal network management APIs as related to ethernet interfaces. Bug: 210485380 Test: make, flash and boot Change-Id: I5908d21564014c56282dad001da441f5b900b523 --- .../InternalNetworkManagementException.aidl | 19 +++ .../InternalNetworkManagementException.java | 59 ++++++++++ .../net/InternalNetworkUpdateRequest.aidl | 19 +++ .../net/InternalNetworkUpdateRequest.java | 108 ++++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 core/java/android/net/InternalNetworkManagementException.aidl create mode 100644 core/java/android/net/InternalNetworkManagementException.java create mode 100644 core/java/android/net/InternalNetworkUpdateRequest.aidl create mode 100644 core/java/android/net/InternalNetworkUpdateRequest.java diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/core/java/android/net/InternalNetworkManagementException.aidl new file mode 100644 index 0000000000..dcce706989 --- /dev/null +++ b/core/java/android/net/InternalNetworkManagementException.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package android.net; + + parcelable InternalNetworkManagementException; \ No newline at end of file diff --git a/core/java/android/net/InternalNetworkManagementException.java b/core/java/android/net/InternalNetworkManagementException.java new file mode 100644 index 0000000000..7f4e403f22 --- /dev/null +++ b/core/java/android/net/InternalNetworkManagementException.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +/** @hide */ +public final class InternalNetworkManagementException + extends RuntimeException implements Parcelable { + + /* @hide */ + public InternalNetworkManagementException(@NonNull final Throwable t) { + super(t); + } + + private InternalNetworkManagementException(@NonNull final Parcel source) { + super(source.readString()); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(getCause().getMessage()); + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public InternalNetworkManagementException[] newArray(int size) { + return new InternalNetworkManagementException[size]; + } + + @Override + public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) { + return new InternalNetworkManagementException(source); + } + }; +} diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/core/java/android/net/InternalNetworkUpdateRequest.aidl new file mode 100644 index 0000000000..da00cb97af --- /dev/null +++ b/core/java/android/net/InternalNetworkUpdateRequest.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package android.net; + + parcelable InternalNetworkUpdateRequest; \ No newline at end of file diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/core/java/android/net/InternalNetworkUpdateRequest.java new file mode 100644 index 0000000000..6f093835fb --- /dev/null +++ b/core/java/android/net/InternalNetworkUpdateRequest.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** @hide */ +public final class InternalNetworkUpdateRequest implements Parcelable { + @NonNull + private final StaticIpConfiguration mIpConfig; + @Nullable + private final NetworkCapabilities mNetworkCapabilities; + + @NonNull + public StaticIpConfiguration getIpConfig() { + return new StaticIpConfiguration(mIpConfig); + } + + @NonNull + public NetworkCapabilities getNetworkCapabilities() { + return mNetworkCapabilities == null + ? null : new NetworkCapabilities(mNetworkCapabilities); + } + + /** @hide */ + public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, + @Nullable final NetworkCapabilities networkCapabilities) { + Objects.requireNonNull(ipConfig); + mIpConfig = new StaticIpConfiguration(ipConfig); + if (null == networkCapabilities) { + mNetworkCapabilities = null; + } else { + mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); + } + } + + private InternalNetworkUpdateRequest(@NonNull final Parcel source) { + Objects.requireNonNull(source); + mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source); + mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source); + } + + @Override + public String toString() { + return "InternalNetworkUpdateRequest{" + + "mIpConfig=" + mIpConfig + + ", mNetworkCapabilities=" + mNetworkCapabilities + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o; + + return Objects.equals(that.getIpConfig(), mIpConfig) + && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities); + } + + @Override + public int hashCode() { + return Objects.hash(mIpConfig, mNetworkCapabilities); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + mIpConfig.writeToParcel(dest, flags); + mNetworkCapabilities.writeToParcel(dest, flags); + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public InternalNetworkUpdateRequest[] newArray(int size) { + return new InternalNetworkUpdateRequest[size]; + } + + @Override + public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) { + return new InternalNetworkUpdateRequest(source); + } + }; +} From be91b5831e3c638021f84119e4308d2a17bbfb8e Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 14 Dec 2021 18:23:30 -0800 Subject: [PATCH 725/881] eth manager updates for network management APIs Private methods added to EthernetManager for network management to be made public when ready. Bug: 210485380 Test: make, flash and boot Change-Id: I7f484d373e05225c98bf0e6111afdc12be31764f --- .../src/android/net/EthernetManager.java | 82 +++++++++++++++++++ .../src/android/net/IEthernetManager.aidl | 6 ++ 2 files changed, 88 insertions(+) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 7cd63ef9cc..ece54df966 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -16,7 +16,9 @@ package android.net; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -32,6 +34,7 @@ import com.android.internal.os.BackgroundThread; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.function.BiConsumer; /** * A class representing the IP configuration of the Ethernet network. @@ -315,4 +318,83 @@ public class EthernetManager { } return new TetheredInterfaceRequest(mService, cbInternal); } + + private static final class InternalNetworkManagementListener + extends IInternalNetworkManagementListener.Stub { + @NonNull + private final Executor mExecutor; + @NonNull + private final BiConsumer mListener; + + InternalNetworkManagementListener( + @NonNull final Executor executor, + @NonNull final BiConsumer listener) { + Objects.requireNonNull(executor, "Pass a non-null executor"); + Objects.requireNonNull(listener, "Pass a non-null listener"); + mExecutor = executor; + mListener = listener; + } + + @Override + public void onComplete( + @Nullable final Network network, + @Nullable final InternalNetworkManagementException e) { + mExecutor.execute(() -> mListener.accept(network, e)); + } + } + + private InternalNetworkManagementListener getInternalNetworkManagementListener( + @Nullable final Executor executor, + @Nullable final BiConsumer listener) { + if (null != listener) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); + } + final InternalNetworkManagementListener proxy; + if (null == listener) { + proxy = null; + } else { + proxy = new InternalNetworkManagementListener(executor, listener); + } + return proxy; + } + + private void updateConfiguration( + @NonNull String iface, + @NonNull InternalNetworkUpdateRequest request, + @Nullable @CallbackExecutor Executor executor, + @Nullable BiConsumer listener) { + final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( + executor, listener); + try { + mService.updateConfiguration(iface, request, proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private void connectNetwork( + @NonNull String iface, + @Nullable @CallbackExecutor Executor executor, + @Nullable BiConsumer listener) { + final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( + executor, listener); + try { + mService.connectNetwork(iface, proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private void disconnectNetwork( + @NonNull String iface, + @Nullable @CallbackExecutor Executor executor, + @Nullable BiConsumer listener) { + final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( + executor, listener); + try { + mService.disconnectNetwork(iface, proxy); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index e058e5a70c..e688bea1cf 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -18,6 +18,8 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; +import android.net.IInternalNetworkManagementListener; +import android.net.InternalNetworkUpdateRequest; import android.net.ITetheredInterfaceCallback; /** @@ -36,4 +38,8 @@ interface IEthernetManager void setIncludeTestInterfaces(boolean include); void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); + void updateConfiguration(String iface, in InternalNetworkUpdateRequest request, + in IInternalNetworkManagementListener listener); + void connectNetwork(String iface, in IInternalNetworkManagementListener listener); + void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener); } From 654c1a61d54d533ebbc59e075245cde9a5b0ff0d Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 23 Dec 2021 03:27:59 +0000 Subject: [PATCH 726/881] [MS16.1] Prepare APIs for replacing getNetwork[Total|Uid]Bytes These internal methods are used in MultipathPolicyTracker and NetworkPolicyManagementService. getNetworkTotalBytes is used to query total bytes regarding to the specified NetworkPolicy, to see how much data quota is used. getNetworkUidBytes is used to find the app to blame for rapid data usage. These methods needs to be replaced by public APIs in follow-up patches. Test: TH Bug: 204830222 Change-Id: Iec9cc7a07397ec2bbc6c3d2559fc3680b149cb8a --- .../app/usage/NetworkStatsManager.java | 87 +++++++++++++++---- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index ca83309216..40b6371da7 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -170,16 +170,44 @@ public class NetworkStatsManager { } } - /** @hide */ - public Bucket querySummaryForDevice(NetworkTemplate template, - long startTime, long endTime) throws SecurityException, RemoteException { - Bucket bucket = null; - NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, - mService); - bucket = stats.getDeviceSummaryForNetwork(); - - stats.close(); - return bucket; + /** + * Query network usage statistics summaries. + * + * Result is summarised data usage for the whole + * device. Result is a single Bucket aggregated over time, state, uid, tag, metered, and + * roaming. This means the bucket's start and end timestamp will be the same as the + * 'startTime' and 'endTime' arguments. State is going to be + * {@link NetworkStats.Bucket#STATE_ALL}, uid {@link NetworkStats.Bucket#UID_ALL}, + * tag {@link NetworkStats.Bucket#TAG_NONE}, + * default network {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered {@link NetworkStats.Bucket#METERED_ALL}, + * and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. + * This may take a long time, and apps should avoid calling this on their main thread. + * + * @param template Template used to match networks. See {@link NetworkTemplate}. + * @param startTime Start of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @return Bucket Summarised data usage. + * + * @hide + */ + @NonNull + @WorkerThread + // @SystemApi(client = MODULE_LIBRARIES) + public Bucket querySummaryForDevice(@NonNull NetworkTemplate template, + long startTime, long endTime) { + try { + NetworkStats stats = + new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); + Bucket bucket = stats.getDeviceSummaryForNetwork(); + stats.close(); + return bucket; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return null; // To make the compiler happy. } /** @@ -323,14 +351,37 @@ public class NetworkStatsManager { return querySummary(template, startTime, endTime); } - /** @hide */ - public NetworkStats querySummary(NetworkTemplate template, long startTime, - long endTime) throws SecurityException, RemoteException { - NetworkStats result; - result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); - result.startSummaryEnumeration(); - - return result; + /** + * Query network usage statistics summaries. + * + * The results will only include traffic made by UIDs belonging to the calling user profile. + * The results are aggregated over time, so that all buckets will have the same start and + * end timestamps as the passed arguments. Not aggregated over state, uid, default network, + * metered, or roaming. + * This may take a long time, and apps should avoid calling this on their main thread. + * + * @param template Template used to match networks. See {@link NetworkTemplate}. + * @param startTime Start of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @return Statistics which is described above. + * @hide + */ + @Nullable + // @SystemApi(client = MODULE_LIBRARIES) + @WorkerThread + public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime, + long endTime) throws SecurityException { + try { + NetworkStats result = + new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); + result.startSummaryEnumeration(); + return result; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return null; // To make the compiler happy. } /** From 3c9ce1f1e329e863b519de10b42bbe67c08572d2 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Thu, 16 Dec 2021 04:11:43 +0000 Subject: [PATCH 727/881] Remove INetworkManagementService usage from EthernetTracker. Ethernet service related files are going to be moved into Connectivity module. INetworkManagementService won't be visible to EthernetTracker since it's a hidden class. Alternatively, use INetd APIs to replace INetworkManagementService usages, including below API changes: - mNMService.listInterfaces -> mNetd.interfaceGetList - mNMService.getInterfaceConfig -> NetdUtils.getInterfaceConfigParcel - remove InterfaceConfiguration usage, use NetdUtils APIs instead. - mNMService.registerObserver -> mNetd.registerUnsolicitedEventListener - for this API change, also replace the parameter BaseNetworkObserver class with BaseNetdUnsolicitedEventListener class. Bug: 210586283 Test: atest FrameworksNetTests Test: atest EthernetServiceTests Change-Id: Ic14c55a6a36b774006931a6fbcbfdec0c51a16e9 --- .../server/ethernet/EthernetTracker.java | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index beb950cb9d..65c3cefe0d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -24,7 +24,7 @@ import android.content.Context; import android.net.IEthernetServiceListener; import android.net.INetd; import android.net.ITetheredInterfaceCallback; -import android.net.InterfaceConfiguration; +import android.net.InterfaceConfigurationParcel; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -33,19 +33,18 @@ import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; import android.os.Handler; import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.RemoteCallbackList; import android.os.RemoteException; -import android.os.ServiceManager; +import android.os.ServiceSpecificException; import android.text.TextUtils; import android.util.ArrayMap; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; +import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.NetdUtils; import com.android.net.module.util.PermissionUtils; -import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; import java.net.InetAddress; @@ -72,8 +71,8 @@ final class EthernetTracker { private static final int INTERFACE_MODE_CLIENT = 1; private static final int INTERFACE_MODE_SERVER = 2; - private final static String TAG = EthernetTracker.class.getSimpleName(); - private final static boolean DBG = EthernetNetworkFactory.DBG; + private static final String TAG = EthernetTracker.class.getSimpleName(); + private static final boolean DBG = EthernetNetworkFactory.DBG; private static final String TEST_IFACE_REGEXP = TEST_TAP_PREFIX + "\\d+"; @@ -91,7 +90,6 @@ final class EthernetTracker { new ConcurrentHashMap<>(); private final Context mContext; - private final INetworkManagementService mNMService; private final INetd mNetd; private final Handler mHandler; private final EthernetNetworkFactory mFactory; @@ -109,7 +107,8 @@ final class EthernetTracker { private boolean mTetheredInterfaceWasAvailable = false; private volatile IpConfiguration mIpConfigForDefaultInterface; - private class TetheredInterfaceRequestList extends RemoteCallbackList { + private class TetheredInterfaceRequestList extends + RemoteCallbackList { @Override public void onCallbackDied(ITetheredInterfaceCallback cb, Object cookie) { mHandler.post(EthernetTracker.this::maybeUntetherDefaultInterface); @@ -121,8 +120,6 @@ final class EthernetTracker { mHandler = handler; // The services we use. - IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); - mNMService = INetworkManagementService.Stub.asInterface(b); mNetd = INetd.Stub.asInterface( (IBinder) context.getSystemService(Context.NETD_SERVICE)); Objects.requireNonNull(mNetd, "could not get netd instance"); @@ -155,8 +152,9 @@ final class EthernetTracker { } try { - mNMService.registerObserver(new InterfaceObserver()); - } catch (RemoteException e) { + PermissionUtils.enforceNetworkStackPermission(mContext); + mNetd.registerUnsolicitedEventListener(new InterfaceObserver()); + } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Could not register InterfaceObserver " + e); } @@ -286,24 +284,24 @@ final class EthernetTracker { } private void addInterface(String iface) { - InterfaceConfiguration config = null; + InterfaceConfigurationParcel config = null; // Bring up the interface so we get link status indications. try { PermissionUtils.enforceNetworkStackPermission(mContext); NetdUtils.setInterfaceUp(mNetd, iface); - config = mNMService.getInterfaceConfig(iface); - } catch (RemoteException | IllegalStateException e) { + config = NetdUtils.getInterfaceConfigParcel(mNetd, iface); + } catch (IllegalStateException e) { // Either the system is crashing or the interface has disappeared. Just ignore the // error; we haven't modified any state because we only do that if our calls succeed. Log.e(TAG, "Error upping interface " + iface, e); } if (config == null) { - Log.e(TAG, "Null interface config for " + iface + ". Bailing out."); + Log.e(TAG, "Null interface config parcelable for " + iface + ". Bailing out."); return; } - final String hwAddress = config.getHardwareAddress(); + final String hwAddress = config.hwAddr; NetworkCapabilities nc = mNetworkCapabilities.get(iface); if (nc == null) { @@ -331,7 +329,7 @@ final class EthernetTracker { // Note: if the interface already has link (e.g., if we crashed and got // restarted while it was running), we need to fake a link up notification so we // start configuring it. - if (config.hasFlag("running")) { + if (NetdUtils.hasFlag(config, "running")) { updateInterfaceState(iface, true); } } @@ -408,20 +406,19 @@ final class EthernetTracker { private void trackAvailableInterfaces() { try { - final String[] ifaces = mNMService.listInterfaces(); + final String[] ifaces = mNetd.interfaceGetList(); for (String iface : ifaces) { maybeTrackInterface(iface); } - } catch (RemoteException | IllegalStateException e) { + } catch (RemoteException | ServiceSpecificException e) { Log.e(TAG, "Could not get list of interfaces " + e); } } - - private class InterfaceObserver extends BaseNetworkObserver { + private class InterfaceObserver extends BaseNetdUnsolicitedEventListener { @Override - public void interfaceLinkStateChanged(String iface, boolean up) { + public void onInterfaceLinkStateChanged(String iface, boolean up) { if (DBG) { Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up); } @@ -429,12 +426,12 @@ final class EthernetTracker { } @Override - public void interfaceAdded(String iface) { + public void onInterfaceAdded(String iface) { mHandler.post(() -> maybeTrackInterface(iface)); } @Override - public void interfaceRemoved(String iface) { + public void onInterfaceRemoved(String iface) { mHandler.post(() -> stopTrackingInterface(iface)); } } @@ -484,9 +481,9 @@ final class EthernetTracker { .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); if (isTestIface) { - builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST); + builder.addTransportType(NetworkCapabilities.TRANSPORT_TEST); } else { - builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); } return builder.build(); From 366c1d7c4bd7c2298a181203f4f5a24ee77d39bb Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 24 Dec 2021 08:31:26 +0000 Subject: [PATCH 728/881] [MS18] Augment data usage by default Follow-up from ag/2815797, callers who uses the hidden API will have their data augmented by default, and the public API offers a way to opt-into augmentation. However, since the data usage is going to the module. All the hidden API usage must be eliminated. Also, from user perspective, it is better for UI and API to have aligned behavior. Thus, enable augment data usage for public API callers. Test: atest FrameworksNetTests \ android.app.usage.cts.NetworkUsageStatsTest Bug: 204830222 Change-Id: Ida254fac8d44c32d388f1886a866f7324a41ce75 --- framework-t/src/android/app/usage/NetworkStatsManager.java | 1 + service-t/src/com/android/server/net/NetworkStatsService.java | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 40b6371da7..2b9560e7ec 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -139,6 +139,7 @@ public class NetworkStatsManager { mContext = context; mService = service; setPollOnOpen(true); + setAugmentWithSubscriptionPlan(true); } /** @hide */ diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 2beca73ecd..df066c21d7 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -655,8 +655,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public INetworkStatsSession openSession() { - // NOTE: if callers want to get non-augmented data, they should go - // through the public API return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null); } @@ -876,8 +874,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { assertSystemReady(); - // NOTE: if callers want to get non-augmented data, they should go - // through the public API return internalGetSummaryForNetwork(template, NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end, NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes(); From fe925d8e2db1ca63f3320b856e6a4fc4896d9c8b Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 28 Dec 2021 02:33:53 +0800 Subject: [PATCH 729/881] Remove ServiceManager usage from IpSecTransform Remove ServiceManager hidden API dependency because this class is going to be moved into mainline module. Thus have IpSecTransform calls createTransform and deleteTransform through IpSecManager to remove the ServiceManager usage. Bug: 204153604 Test: FrameworksNetTests Change-Id: Iba48da4aecac1080684d5a7e7e7ca2e31219591a --- framework-t/src/android/net/IpSecManager.java | 24 +++++++++++++++++++ .../src/android/net/IpSecTransform.java | 24 ++++--------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java index 0d15dffae9..819ac6bdec 100644 --- a/framework-t/src/android/net/IpSecManager.java +++ b/framework-t/src/android/net/IpSecManager.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.annotations.PolicyDirection; import android.os.Binder; +import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -980,6 +981,29 @@ public final class IpSecManager { } } + /** + * @hide + */ + public IpSecTransformResponse createTransform(IpSecConfig config, IBinder binder, + String callingPackage) { + try { + return mService.createTransform(config, binder, callingPackage); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @hide + */ + public void deleteTransform(int resourceId) { + try { + mService.deleteTransform(resourceId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Construct an instance of IpSecManager within an application context. * diff --git a/framework-t/src/android/net/IpSecTransform.java b/framework-t/src/android/net/IpSecTransform.java index 36199a046c..68ae5de4ee 100644 --- a/framework-t/src/android/net/IpSecTransform.java +++ b/framework-t/src/android/net/IpSecTransform.java @@ -26,9 +26,6 @@ import android.annotation.SystemApi; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.util.Log; @@ -93,16 +90,9 @@ public final class IpSecTransform implements AutoCloseable { mResourceId = INVALID_RESOURCE_ID; } - private IIpSecService getIpSecService() { - IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE); - if (b == null) { - throw new RemoteException("Failed to connect to IpSecService") - .rethrowAsRuntimeException(); - } - - return IIpSecService.Stub.asInterface(b); + private IpSecManager getIpSecManager(Context context) { + return context.getSystemService(IpSecManager.class); } - /** * Checks the result status and throws an appropriate exception if the status is not Status.OK. */ @@ -130,8 +120,7 @@ public final class IpSecTransform implements AutoCloseable { IpSecManager.SpiUnavailableException { synchronized (this) { try { - IIpSecService svc = getIpSecService(); - IpSecTransformResponse result = svc.createTransform( + IpSecTransformResponse result = getIpSecManager(mContext).createTransform( mConfig, new Binder(), mContext.getOpPackageName()); int status = result.status; checkResultStatus(status); @@ -140,8 +129,6 @@ public final class IpSecTransform implements AutoCloseable { mCloseGuard.open("build"); } catch (ServiceSpecificException e) { throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); } } @@ -177,10 +164,7 @@ public final class IpSecTransform implements AutoCloseable { return; } try { - IIpSecService svc = getIpSecService(); - svc.deleteTransform(mResourceId); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); + getIpSecManager(mContext).deleteTransform(mResourceId); } catch (Exception e) { // On close we swallow all random exceptions since failure to close is not // actionable by the user. From 6c4fca78b0779a0791df0b71a522962bd27acb3f Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 27 Dec 2021 03:55:06 +0000 Subject: [PATCH 730/881] [MS19.1] Fix several hidden API dependencies This includes: 1. Use android.util.IndentingPrintWriter instead of the deprecated internal one. 2. Replace usages of IntArray with CollectionUtils and ArrayList. 3. Replace usages of ArrayUtils with CollectionUtils. 4. Refactor MathUtils.constrain functions into NetworkStatsUtils. 5. Replace Maps.newHashMap and Lists.newArrayList with public class constructors. 6. Replace Slog with Log. Test: FrameworksNetTests NetworkStaticLibTests Bug: 204830222 Change-Id: If009194ad5668a6d48dd341ea6d325028ce56d42 --- .../src/android/app/usage/NetworkStats.java | 8 +++-- framework-t/src/android/net/NetworkStats.java | 6 ++-- .../android/net/NetworkStatsCollection.java | 33 +++++++++---------- .../src/android/net/NetworkStatsHistory.java | 20 +++++++---- .../src/android/net/NetworkTemplate.java | 14 ++++---- 5 files changed, 43 insertions(+), 38 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java index 216a4a0987..f684a4d9d8 100644 --- a/framework-t/src/android/app/usage/NetworkStats.java +++ b/framework-t/src/android/app/usage/NetworkStats.java @@ -24,13 +24,15 @@ import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; import android.os.RemoteException; -import android.util.IntArray; import android.util.Log; +import com.android.net.module.util.CollectionUtils; + import dalvik.system.CloseGuard; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; /** * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects @@ -568,7 +570,7 @@ public final class NetworkStats implements AutoCloseable { // the filtering logic below can be removed. int[] uids = mSession.getRelevantUids(); // Filtering of uids with empty history. - IntArray filteredUids = new IntArray(uids.length); + final ArrayList filteredUids = new ArrayList<>(); for (int uid : uids) { try { NetworkStatsHistory history = mSession.getHistoryIntervalForUid(mTemplate, uid, @@ -581,7 +583,7 @@ public final class NetworkStats implements AutoCloseable { Log.w(TAG, "Error while getting history of uid " + uid, e); } } - mUids = filteredUids.toArray(); + mUids = CollectionUtils.toIntArray(filteredUids); mUidOrUidIndex = -1; stepHistory(); } diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java index 1986b83b12..181a594cbc 100644 --- a/framework-t/src/android/net/NetworkStats.java +++ b/framework-t/src/android/net/NetworkStats.java @@ -31,7 +31,7 @@ import android.os.SystemClock; import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; +import com.android.net.module.util.CollectionUtils; import libcore.util.EmptyArray; @@ -1185,7 +1185,7 @@ public final class NetworkStats implements Parcelable { * @hide */ public void removeUids(int[] uids) { - filter(e -> !ArrayUtils.contains(uids, e.uid)); + filter(e -> !CollectionUtils.contains(uids, e.uid)); } /** @@ -1218,7 +1218,7 @@ public final class NetworkStats implements Parcelable { filter(e -> (limitUid == UID_ALL || limitUid == e.uid) && (limitTag == TAG_ALL || limitTag == e.tag) && (limitIfaces == INTERFACES_ALL - || ArrayUtils.contains(limitIfaces, e.iface))); + || CollectionUtils.contains(limitIfaces, e.iface))); } /** diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 8d1347e25b..7935d28f30 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -40,21 +40,17 @@ import android.telephony.SubscriptionPlan; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.AtomicFile; -import android.util.IntArray; -import android.util.MathUtils; +import android.util.IndentingPrintWriter; +import android.util.Log; import android.util.Range; -import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastDataInput; import com.android.internal.util.FastDataOutput; import com.android.internal.util.FileRotator; -import com.android.internal.util.IndentingPrintWriter; - -import com.google.android.collect.Lists; -import com.google.android.collect.Maps; +import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.NetworkStatsUtils; import libcore.io.IoUtils; @@ -196,11 +192,11 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel, final int callerUid) { - IntArray uids = new IntArray(); + final ArrayList uids = new ArrayList<>(); for (int i = 0; i < mStats.size(); i++) { final Key key = mStats.keyAt(i); if (NetworkStatsAccess.isAccessibleToUser(key.uid, callerUid, accessLevel)) { - int j = uids.binarySearch(key.uid); + int j = Collections.binarySearch(uids, new Integer(key.uid)); if (j < 0) { j = ~j; @@ -208,7 +204,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } } - return uids.toArray(); + return CollectionUtils.toIntArray(uids); } /** @@ -225,7 +221,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W // 180 days of history should be enough for anyone; if we end up needing // more, we'll dynamically grow the history object. - final int bucketEstimate = (int) MathUtils.constrain(((end - start) / mBucketDuration), 0, + final int bucketEstimate = (int) NetworkStatsUtils.constrain( + ((end - start) / mBucketDuration), 0, (180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration); final NetworkStatsHistory combined = new NetworkStatsHistory( mBucketDuration, bucketEstimate, fields); @@ -316,7 +313,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W final long deltaTotal = combined.getTotalBytes() - beforeTotal; if (deltaTotal != 0) { - Slog.d(TAG, "Augmented network usage by " + deltaTotal + " bytes"); + Log.d(TAG, "Augmented network usage by " + deltaTotal + " bytes"); } // Finally we can slice data as originally requested @@ -489,11 +486,11 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private void write(DataOutput out) throws IOException { // cluster key lists grouped by ident - final HashMap> keysByIdent = Maps.newHashMap(); + final HashMap> keysByIdent = new HashMap<>(); for (Key key : mStats.keySet()) { ArrayList keys = keysByIdent.get(key.ident); if (keys == null) { - keys = Lists.newArrayList(); + keys = new ArrayList<>(); keysByIdent.put(key.ident, keys); } keys.add(key); @@ -640,12 +637,12 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * {@link TrafficStats#UID_REMOVED}. */ public void removeUids(int[] uids) { - final ArrayList knownKeys = Lists.newArrayList(); + final ArrayList knownKeys = new ArrayList<>(); knownKeys.addAll(mStats.keySet()); // migrate all UID stats into special "removed" bucket for (Key key : knownKeys) { - if (ArrayUtils.contains(uids, key.uid)) { + if (CollectionUtils.contains(uids, key.uid)) { // only migrate combined TAG_NONE history if (key.tag == TAG_NONE) { final NetworkStatsHistory uidHistory = mStats.get(key); @@ -672,7 +669,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } private ArrayList getSortedKeys() { - final ArrayList keys = Lists.newArrayList(); + final ArrayList keys = new ArrayList<>(); keys.addAll(mStats.keySet()); Collections.sort(keys); return keys; diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java index 3eef4ee6f8..428bc6df26 100644 --- a/framework-t/src/android/net/NetworkStatsHistory.java +++ b/framework-t/src/android/net/NetworkStatsHistory.java @@ -28,7 +28,6 @@ import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; import static android.text.format.DateUtils.SECOND_IN_MILLIS; -import static com.android.internal.util.ArrayUtils.total; import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; import android.compat.annotation.UnsupportedAppUsage; @@ -37,10 +36,11 @@ import android.os.Parcel; import android.os.Parcelable; import android.service.NetworkStatsHistoryBucketProto; import android.service.NetworkStatsHistoryProto; -import android.util.MathUtils; +import android.util.IndentingPrintWriter; import android.util.proto.ProtoOutputStream; -import com.android.internal.util.IndentingPrintWriter; +import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.NetworkStatsUtils; import libcore.util.EmptyArray; @@ -174,7 +174,7 @@ public class NetworkStatsHistory implements Parcelable { txPackets = new long[bucketStart.length]; operations = new long[bucketStart.length]; bucketCount = bucketStart.length; - totalBytes = total(rxBytes) + total(txBytes); + totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes); break; } case VERSION_ADD_PACKETS: @@ -189,7 +189,7 @@ public class NetworkStatsHistory implements Parcelable { txPackets = readVarLongArray(in); operations = readVarLongArray(in); bucketCount = bucketStart.length; - totalBytes = total(rxBytes) + total(txBytes); + totalBytes = CollectionUtils.total(rxBytes) + CollectionUtils.total(txBytes); break; } default: { @@ -267,7 +267,7 @@ public class NetworkStatsHistory implements Parcelable { } else { index -= 1; } - return MathUtils.constrain(index, 0, bucketCount - 1); + return NetworkStatsUtils.constrain(index, 0, bucketCount - 1); } /** @@ -281,7 +281,7 @@ public class NetworkStatsHistory implements Parcelable { } else { index += 1; } - return MathUtils.constrain(index, 0, bucketCount - 1); + return NetworkStatsUtils.constrain(index, 0, bucketCount - 1); } /** @@ -349,6 +349,9 @@ public class NetworkStatsHistory implements Parcelable { // create any buckets needed by this range ensureBuckets(start, end); + // Return fast if there is still no entry. This would typically happen when the start, + // end or duration are not valid values, e.g. start > end, negative duration value, etc. + if (bucketCount == 0) return; // distribute data usage into buckets long duration = end - start; @@ -560,6 +563,9 @@ public class NetworkStatsHistory implements Parcelable { entry.txPackets = txPackets != null ? 0 : UNKNOWN; entry.operations = operations != null ? 0 : UNKNOWN; + // Return fast if there is no entry. + if (bucketCount == 0) return entry; + final int startIndex = getIndexAfter(end); for (int i = startIndex; i >= 0; i--) { final long curStart = bucketStart[i]; diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 5da8e259d0..9fa777d27c 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -49,7 +49,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; -import com.android.internal.util.ArrayUtils; +import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkIdentityUtils; import com.android.net.module.util.NetworkStatsUtils; @@ -703,7 +703,7 @@ public final class NetworkTemplate implements Parcelable { */ public boolean matchesSubscriberId(@Nullable String subscriberId) { return mSubscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL - || ArrayUtils.contains(mMatchSubscriberIds, subscriberId); + || CollectionUtils.contains(mMatchSubscriberIds, subscriberId); } /** @@ -723,8 +723,8 @@ public final class NetworkTemplate implements Parcelable { // TODO: consider matching against WiMAX subscriber identity return true; } else { - return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds) - && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) + return ident.mType == TYPE_MOBILE && !CollectionUtils.isEmpty(mMatchSubscriberIds) + && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) && matchesCollapsedRatType(ident); } } @@ -835,8 +835,8 @@ public final class NetworkTemplate implements Parcelable { */ private boolean matchesCarrier(NetworkIdentity ident) { return ident.mSubscriberId != null - && !ArrayUtils.isEmpty(mMatchSubscriberIds) - && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); + && !CollectionUtils.isEmpty(mMatchSubscriberIds) + && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); } private boolean matchesMobileWildcard(NetworkIdentity ident) { @@ -953,7 +953,7 @@ public final class NetworkTemplate implements Parcelable { if (template.mSubscriberId == null) return template; for (String[] merged : mergedList) { - if (ArrayUtils.contains(merged, template.mSubscriberId)) { + if (CollectionUtils.contains(merged, template.mSubscriberId)) { // Requested template subscriber is part of the merge group; return // a template that matches all merged subscribers. return new NetworkTemplate(template.mMatchRule, merged[0], merged, From 989b2128db294a79986860c91576e4e239985782 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 27 Dec 2021 13:56:59 +0000 Subject: [PATCH 731/881] [MS21] Remove DataUnit dependency DataUnit is a hidden class, remove the references to it from files that about to be moved into the module. Test: TH Bug: 204830222 Change-Id: Ibfb82ab74f283686fb2af6c3a550d541440c890d --- .../src/android/app/usage/NetworkStatsManager.java | 3 +-- framework-t/src/android/net/TrafficStats.java | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index ca83309216..82c72ab1de 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -47,7 +47,6 @@ import android.os.Messenger; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.text.TextUtils; -import android.util.DataUnit; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -119,7 +118,7 @@ public class NetworkStatsManager { * is reached. * @hide */ - public static final long MIN_THRESHOLD_BYTES = DataUnit.MEBIBYTES.toBytes(2); + public static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB private final Context mContext; private final INetworkStatsService mService; diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java index fa650617f3..d8feb88f0f 100644 --- a/framework-t/src/android/net/TrafficStats.java +++ b/framework-t/src/android/net/TrafficStats.java @@ -29,7 +29,6 @@ import android.media.MediaPlayer; import android.os.Build; import android.os.RemoteException; import android.os.ServiceManager; -import android.util.DataUnit; import com.android.server.NetworkManagementSocketTagger; @@ -59,19 +58,19 @@ public class TrafficStats { */ public final static int UNSUPPORTED = -1; - /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */ @Deprecated public static final long KB_IN_BYTES = 1024; - /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */ @Deprecated public static final long MB_IN_BYTES = KB_IN_BYTES * 1024; - /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */ @Deprecated public static final long GB_IN_BYTES = MB_IN_BYTES * 1024; - /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */ @Deprecated public static final long TB_IN_BYTES = GB_IN_BYTES * 1024; - /** @hide @deprecated use {@link DataUnit} instead to clarify SI-vs-IEC */ + /** @hide @deprecated use {@code DataUnit} instead to clarify SI-vs-IEC */ @Deprecated public static final long PB_IN_BYTES = TB_IN_BYTES * 1024; From 4f84ff37091d05733eceb7867bdfb619aca65052 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 28 Dec 2021 09:03:07 +0000 Subject: [PATCH 732/881] [MS26.1] Remove Process.NETWORK_STACK_UID dependency Check NetworkStack permission instead. Test: NetworkStatsAccessTest Bug: 204830222 Change-Id: I052a1422d145af533b036b0f017ace485b67cbfe --- framework-t/src/android/net/NetworkStatsAccess.java | 9 +++++++-- .../src/com/android/server/net/NetworkStatsService.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java index 591605d952..779fdf94a0 100644 --- a/framework-t/src/android/net/NetworkStatsAccess.java +++ b/framework-t/src/android/net/NetworkStatsAccess.java @@ -17,6 +17,7 @@ package android.net; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; import static android.net.TrafficStats.UID_TETHERING; @@ -106,7 +107,7 @@ public final class NetworkStatsAccess { /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */ public static @NetworkStatsAccess.Level int checkAccessLevel( - Context context, int callingUid, String callingPackage) { + Context context, int callingPid, int callingUid, String callingPackage) { final DevicePolicyManager mDpm = context.getSystemService(DevicePolicyManager.class); final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); @@ -123,8 +124,12 @@ public final class NetworkStatsAccess { final boolean isDeviceOwner = mDpm != null && mDpm.isDeviceOwnerApp(callingPackage); final int appId = UserHandle.getAppId(callingUid); + final boolean isNetworkStack = context.checkPermission( + android.Manifest.permission.NETWORK_STACK, callingPid, callingUid) + == PERMISSION_GRANTED; + if (hasCarrierPrivileges || isDeviceOwner - || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { + || appId == Process.SYSTEM_UID || isNetworkStack) { // Carrier-privileged apps and device owners, and the system (including the // network stack) can access data usage for all apps on the device. return NetworkStatsAccess.Level.DEVICE; diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 2beca73ecd..748cc27d51 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -811,7 +811,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) { return NetworkStatsAccess.checkAccessLevel( - mContext, Binder.getCallingUid(), callingPackage); + mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage); } /** From 978ef03a6c830150e1520a069be55480316754f6 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 27 Dec 2021 15:40:22 +0000 Subject: [PATCH 733/881] [MS23] Remove UserHandle.getUserId dependencies Replaced with SystemApi. Test: TH Bug: 204830222 Change-Id: Ibc834489428c2036cd4ccd3284ba06c4c9e792b7 --- framework-t/src/android/net/NetworkStatsAccess.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java index 779fdf94a0..8980bbcbab 100644 --- a/framework-t/src/android/net/NetworkStatsAccess.java +++ b/framework-t/src/android/net/NetworkStatsAccess.java @@ -160,6 +160,8 @@ public final class NetworkStatsAccess { */ public static boolean isAccessibleToUser(int uid, int callerUid, @NetworkStatsAccess.Level int accessLevel) { + final int userId = UserHandle.getUserHandleForUid(uid).getIdentifier(); + final int callerUserId = UserHandle.getUserHandleForUid(callerUid).getIdentifier(); switch (accessLevel) { case NetworkStatsAccess.Level.DEVICE: // Device-level access - can access usage for any uid. @@ -170,13 +172,13 @@ public final class NetworkStatsAccess { // anonymized uids return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED || uid == UID_TETHERING || uid == UID_ALL - || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid); + || userId == callerUserId; case NetworkStatsAccess.Level.USER: // User-level access - can access usage for any app running in the same user, along // with some special uids (system, removed, or tethering). return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED || uid == UID_TETHERING - || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid); + || userId == callerUserId; case NetworkStatsAccess.Level.DEFAULT: default: // Default access level - can only access one's own usage. From 67b95e049e59d970f5f12d315082a389e0662503 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 28 Dec 2021 02:05:57 +0000 Subject: [PATCH 734/881] [MS25.1] Remove AppOpsManager.OP_GET_USAGE_STATS dependency Replaced by public interface. Test: TH Bug: 204830222 Change-Id: If7d17879b0ffdb6300373bc581cb07252fccfc7a --- framework-t/src/android/net/NetworkStatsAccess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/framework-t/src/android/net/NetworkStatsAccess.java b/framework-t/src/android/net/NetworkStatsAccess.java index 8980bbcbab..b64fbdba9a 100644 --- a/framework-t/src/android/net/NetworkStatsAccess.java +++ b/framework-t/src/android/net/NetworkStatsAccess.java @@ -192,8 +192,8 @@ public final class NetworkStatsAccess { AppOpsManager appOps = (AppOpsManager) context.getSystemService( Context.APP_OPS_SERVICE); - final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, - callingUid, callingPackage); + final int mode = appOps.noteOp(AppOpsManager.OPSTR_GET_USAGE_STATS, + callingUid, callingPackage, null /* attributionTag */, null /* message */); if (mode == AppOpsManager.MODE_DEFAULT) { // The default behavior here is to check if PackageManager has given the app // permission. From 04a367ebc1ce7725a6fddea0b94b863d1af2adad Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 30 Dec 2021 06:23:36 +0000 Subject: [PATCH 735/881] [MS28.1] Fix several hidden API dependencies This includes: 1. Replace Slog with Log 2. Use android.util.IndentingPrintWriter instead of the deprecated internal one. 3. Replace usages of ArrayUtils with CollectionUtils. 4. Reimplement DumpUtils#checkDumpPermission in PermissionUtils. 5. Replace MathUtils.constrain with NetworkStatsUtils.constrain Test: FrameworksNetTests Bug: 204830222 Change-Id: I2b064fc25497288d66018584e66da98c79bd208d --- .../server/net/NetworkStatsFactory.java | 4 +- .../server/net/NetworkStatsObservers.java | 27 ++++---- .../server/net/NetworkStatsRecorder.java | 11 ++-- .../server/net/NetworkStatsService.java | 62 ++++++++++--------- 4 files changed, 53 insertions(+), 51 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java index e6433db11d..c7c8893ed8 100644 --- a/service-t/src/com/android/server/net/NetworkStatsFactory.java +++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java @@ -35,8 +35,8 @@ import android.os.SystemClock; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; +import com.android.net.module.util.CollectionUtils; import libcore.io.IoUtils; @@ -434,7 +434,7 @@ public class NetworkStatsFactory { entry.txBytes = reader.nextLong(); entry.txPackets = reader.nextLong(); - if ((limitIfaces == null || ArrayUtils.contains(limitIfaces, entry.iface)) + if ((limitIfaces == null || CollectionUtils.contains(limitIfaces, entry.iface)) && (limitUid == UID_ALL || limitUid == entry.uid) && (limitTag == TAG_ALL || limitTag == entry.tag)) { stats.insertEntry(entry); diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java index 1a0866d2f9..9aa20a4830 100644 --- a/service-t/src/com/android/server/net/NetworkStatsObservers.java +++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java @@ -38,7 +38,7 @@ import android.os.Messenger; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; -import android.util.Slog; +import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; @@ -83,7 +83,7 @@ class NetworkStatsObservers { RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid, accessLevel); - if (LOGV) Slog.v(TAG, "Registering observer for " + request); + if (LOGV) Log.v(TAG, "Registering observer for " + request); getHandler().sendMessage(mHandler.obtainMessage(MSG_REGISTER, requestInfo)); return request; } @@ -116,7 +116,7 @@ class NetworkStatsObservers { if (mHandler == null) { synchronized (this) { if (mHandler == null) { - if (LOGV) Slog.v(TAG, "Creating handler"); + if (LOGV) Log.v(TAG, "Creating handler"); mHandler = new Handler(getHandlerLooperLocked(), mHandlerCallback); } } @@ -172,15 +172,15 @@ class NetworkStatsObservers { RequestInfo requestInfo; requestInfo = mDataUsageRequests.get(request.requestId); if (requestInfo == null) { - if (LOGV) Slog.v(TAG, "Trying to unregister unknown request " + request); + if (LOGV) Log.v(TAG, "Trying to unregister unknown request " + request); return; } if (Process.SYSTEM_UID != callingUid && requestInfo.mCallingUid != callingUid) { - Slog.w(TAG, "Caller uid " + callingUid + " is not owner of " + request); + Log.w(TAG, "Caller uid " + callingUid + " is not owner of " + request); return; } - if (LOGV) Slog.v(TAG, "Unregistering " + request); + if (LOGV) Log.v(TAG, "Unregistering " + request); mDataUsageRequests.remove(request.requestId); requestInfo.unlinkDeathRecipient(); requestInfo.callCallback(NetworkStatsManager.CALLBACK_RELEASED); @@ -201,7 +201,7 @@ class NetworkStatsObservers { // Cap the minimum threshold to a safe default to avoid too many callbacks long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes); if (thresholdInBytes < request.thresholdInBytes) { - Slog.w(TAG, "Threshold was too low for " + request + Log.w(TAG, "Threshold was too low for " + request + ". Overriding to a safer default of " + thresholdInBytes + " bytes"); } return new DataUsageRequest(mNextDataUsageRequestId.incrementAndGet(), @@ -255,8 +255,9 @@ class NetworkStatsObservers { @Override public void binderDied() { - if (LOGV) Slog.v(TAG, "RequestInfo binderDied(" - + mRequest + ", " + mBinder + ")"); + if (LOGV) { + Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")"); + } mStatsObserver.unregister(mRequest, Process.SYSTEM_UID); callCallback(NetworkStatsManager.CALLBACK_RELEASED); } @@ -299,13 +300,13 @@ class NetworkStatsObservers { msg.setData(bundle); try { if (LOGV) { - Slog.v(TAG, "sending notification " + callbackTypeToName(callbackType) + Log.v(TAG, "sending notification " + callbackTypeToName(callbackType) + " for " + mRequest); } mMessenger.send(msg); } catch (RemoteException e) { // May occur naturally in the race of binder death. - Slog.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest); + Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest); } } @@ -341,7 +342,7 @@ class NetworkStatsObservers { protected boolean checkStats() { long bytesSoFar = getTotalBytesForNetwork(mRequest.template); if (LOGV) { - Slog.v(TAG, bytesSoFar + " bytes so far since notification for " + Log.v(TAG, bytesSoFar + " bytes so far since notification for " + mRequest.template); } if (bytesSoFar > mRequest.thresholdInBytes) { @@ -416,7 +417,7 @@ class NetworkStatsObservers { return history.getTotalBytes(); } catch (SecurityException e) { if (LOGV) { - Slog.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid " + Log.w(TAG, "CallerUid " + mCallingUid + " may have lost access to uid " + uid); } return 0; diff --git a/service-t/src/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java index 5e27c776cc..cec6609dc4 100644 --- a/service-t/src/com/android/server/net/NetworkStatsRecorder.java +++ b/service-t/src/com/android/server/net/NetworkStatsRecorder.java @@ -32,13 +32,12 @@ import android.net.TrafficStats; import android.os.Binder; import android.os.DropBoxManager; import android.service.NetworkStatsRecorderProto; +import android.util.IndentingPrintWriter; import android.util.Log; import android.util.MathUtils; -import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.util.FileRotator; -import com.android.internal.util.IndentingPrintWriter; import com.google.android.collect.Sets; @@ -132,7 +131,7 @@ public class NetworkStatsRecorder { } public void setPersistThreshold(long thresholdBytes) { - if (LOGV) Slog.v(TAG, "setPersistThreshold() with " + thresholdBytes); + if (LOGV) Log.v(TAG, "setPersistThreshold() with " + thresholdBytes); mPersistThresholdBytes = MathUtils.constrain( thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES); } @@ -185,7 +184,7 @@ public class NetworkStatsRecorder { } private NetworkStatsCollection loadLocked(long start, long end) { - if (LOGD) Slog.d(TAG, "loadLocked() reading from disk for " + mCookie); + if (LOGD) Log.d(TAG, "loadLocked() reading from disk for " + mCookie); final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration); try { mRotator.readMatching(res, start, end); @@ -272,7 +271,7 @@ public class NetworkStatsRecorder { mLastSnapshot = snapshot; if (LOGV && unknownIfaces.size() > 0) { - Slog.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats"); + Log.w(TAG, "unknown interfaces " + unknownIfaces + ", ignoring those stats"); } } @@ -296,7 +295,7 @@ public class NetworkStatsRecorder { public void forcePersistLocked(long currentTimeMillis) { Objects.requireNonNull(mRotator, "missing FileRotator"); if (mPending.isDirty()) { - if (LOGD) Slog.d(TAG, "forcePersistLocked() writing for " + mCookie); + if (LOGD) Log.d(TAG, "forcePersistLocked() writing for " + mCookie); try { mRotator.rewriteActive(mPendingRewriter, currentTimeMillis); mRotator.maybeRotate(currentTimeMillis); diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 748cc27d51..44d7d1f668 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -141,19 +141,18 @@ import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; +import android.util.IndentingPrintWriter; import android.util.Log; -import android.util.MathUtils; -import android.util.Slog; import android.util.SparseIntArray; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; -import com.android.internal.util.DumpUtils; import com.android.internal.util.FileRotator; -import com.android.internal.util.IndentingPrintWriter; import com.android.net.module.util.BinderUtils; +import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.NetworkStatsUtils; +import com.android.net.module.util.PermissionUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; @@ -163,6 +162,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.time.Clock; import java.time.ZoneOffset; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -646,7 +646,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { try { mNetworkManager.setGlobalAlert(mGlobalAlertBytes); } catch (IllegalStateException e) { - Slog.w(TAG, "problem registering for global alert: " + e); + Log.w(TAG, "problem registering for global alert: " + e); } catch (RemoteException e) { // ignored; service lives in system_server } @@ -766,7 +766,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return stats; } catch (NullPointerException e) { // TODO: Track down and fix the cause of this crash and remove this catch block. - Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e); + Log.wtf(TAG, "NullPointerException in getSummaryForAllUid", e); throw e; } } @@ -823,7 +823,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { SubscriptionPlan plan = null; if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0 && mSettings.getAugmentEnabled()) { - if (LOGD) Slog.d(TAG, "Resolving plan for " + template); + if (LOGD) Log.d(TAG, "Resolving plan for " + template); final long token = Binder.clearCallingIdentity(); try { plan = LocalServices.getService(NetworkPolicyManagerInternal.class) @@ -831,7 +831,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } finally { Binder.restoreCallingIdentity(token); } - if (LOGD) Slog.d(TAG, "Resolved to plan " + plan); + if (LOGD) Log.d(TAG, "Resolved to plan " + plan); } return plan; } @@ -936,7 +936,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public String[] getMobileIfaces() { // TODO (b/192758557): Remove debug log. - if (ArrayUtils.contains(mMobileIfaces, null)) { + if (CollectionUtils.contains(mMobileIfaces, null)) { throw new NullPointerException( "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); } @@ -1014,9 +1014,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void advisePersistThreshold(long thresholdBytes) { // clamp threshold into safe range - mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES); + mPersistThreshold = NetworkStatsUtils.constrain(thresholdBytes, + 128 * KB_IN_BYTES, 2 * MB_IN_BYTES); if (LOGV) { - Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to " + Log.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to " + mPersistThreshold); } @@ -1279,7 +1280,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks, @NonNull NetworkStateSnapshot[] snapshots) { if (!mSystemReady) return; - if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()"); + if (LOGV) Log.v(TAG, "handleNotifyNetworkStatusLocked()"); // take one last stats snapshot before updating iface mapping. this // isn't perfect, since the kernel may already be counting traffic from @@ -1303,7 +1304,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int displayTransport = getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes()); final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); - final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.getNetwork()); + final boolean isDefault = CollectionUtils.contains( + mDefaultNetworks, snapshot.getNetwork()); final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED : getSubTypeForStateSnapshot(snapshot); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot, @@ -1386,7 +1388,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mMobileIfaces = mobileIfaces.toArray(new String[0]); // TODO (b/192758557): Remove debug log. - if (ArrayUtils.contains(mMobileIfaces, null)) { + if (CollectionUtils.contains(mMobileIfaces, null)) { throw new NullPointerException( "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); } @@ -1401,7 +1403,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (spec instanceof TelephonyNetworkSpecifier) { return ((TelephonyNetworkSpecifier) spec).getSubscriptionId(); } else { - Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier"); + Log.wtf(TAG, "getSubIdForState invalid NetworkSpecifier"); return INVALID_SUBSCRIPTION_ID; } } @@ -1485,7 +1487,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { try { recordSnapshotLocked(currentTime); } catch (IllegalStateException e) { - Slog.w(TAG, "problem reading network stats: " + e); + Log.w(TAG, "problem reading network stats: " + e); } catch (RemoteException e) { // ignored; service lives in system_server } @@ -1510,7 +1512,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private void performPollLocked(int flags) { if (!mSystemReady) return; - if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); + if (LOGV) Log.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked"); final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; @@ -1632,7 +1634,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ @GuardedBy("mStatsLock") private void removeUidsLocked(int... uids) { - if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids)); + if (LOGV) Log.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids)); // Perform one last poll before removing performPollLocked(FLAG_PERSIST_ALL); @@ -1651,19 +1653,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ @GuardedBy("mStatsLock") private void removeUserLocked(int userId) { - if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId); + if (LOGV) Log.v(TAG, "removeUserLocked() for userId=" + userId); // Build list of UIDs that we should clean up - int[] uids = new int[0]; + final ArrayList uids = new ArrayList<>(); final List apps = mContext.getPackageManager().getInstalledApplications( PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DISABLED_COMPONENTS); for (ApplicationInfo app : apps) { final int uid = UserHandle.getUid(userId, app.uid); - uids = ArrayUtils.appendInt(uids, uid); + uids.add(uid); } - removeUidsLocked(uids); + removeUidsLocked(CollectionUtils.toIntArray(uids)); } private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal { @@ -1706,7 +1708,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void setStatsProviderWarningAndLimitAsync( @NonNull String iface, long warning, long limit) { if (LOGV) { - Slog.v(TAG, "setStatsProviderWarningAndLimitAsync(" + Log.v(TAG, "setStatsProviderWarningAndLimitAsync(" + iface + "," + warning + "," + limit + ")"); } invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, @@ -1716,7 +1718,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return; + if (!PermissionUtils.checkDumpPermission(mContext, TAG, rawWriter)) return; long duration = DateUtils.DAY_IN_MILLIS; final HashSet argSet = new HashSet(); @@ -1777,15 +1779,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { pw.println("Configs:"); pw.increaseIndent(); - pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled()); + pw.print(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled()); pw.println(); pw.decreaseIndent(); pw.println("Active interfaces:"); pw.increaseIndent(); for (int i = 0; i < mActiveIfaces.size(); i++) { - pw.printPair("iface", mActiveIfaces.keyAt(i)); - pw.printPair("ident", mActiveIfaces.valueAt(i)); + pw.print("iface", mActiveIfaces.keyAt(i)); + pw.print("ident", mActiveIfaces.valueAt(i)); pw.println(); } pw.decreaseIndent(); @@ -1793,8 +1795,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { pw.println("Active UID interfaces:"); pw.increaseIndent(); for (int i = 0; i < mActiveUidIfaces.size(); i++) { - pw.printPair("iface", mActiveUidIfaces.keyAt(i)); - pw.printPair("ident", mActiveUidIfaces.valueAt(i)); + pw.print("iface", mActiveUidIfaces.keyAt(i)); + pw.print("ident", mActiveUidIfaces.valueAt(i)); pw.println(); } pw.decreaseIndent(); From c70871f60a3635b4ccf83155d970c076ebe533f3 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Thu, 23 Dec 2021 11:45:02 +0800 Subject: [PATCH 736/881] wifi data usage: replaced Wi-Fi SSID with a Wi-Fi network key 1. Used SSID to be a wifi network identity can't separate wifi data usage when there are two different network with same SSID. Use a new usage key from WifiInfo to replace wifi SSID to solve this issue. 2. To support to query wifi usage per configured Wifi network. Adding matchWifiNetworkKeys in NetworkTemplate to support querying multi networkKeys wifi data usage since each configured Wifi network configuration might be used to connect different Wifi network. (Replace mNetworkId with mMatchWifiNetworkKeys) 3. Updated callers who were using NetworkTemplate constructor. 4. Fixed SortedSet null order case. The null subscriberId is a valid input for matchSubscriberIds. 5. Replaced ArrayUtils with CollectionUtils. Bug: 197520752 Bug: 126299427 Test: atest -c NetworkTemplateTest Test: atest -c NetworkStatsServiceTest Test: atest -c NetworkPolicyManagerServiceTest Test: atest -c NetworkPolicyTest Change-Id: Ie20e7fb56597817901be4ce1d2a7afcbc9ded0c6 --- .../src/android/net/NetworkIdentity.java | 11 +- .../src/android/net/NetworkTemplate.java | 183 +++++++++++------- 2 files changed, 121 insertions(+), 73 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index eb8f43e3d0..8f1115e065 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -21,7 +21,6 @@ import static android.net.ConnectivityManager.TYPE_WIFI; import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; -import android.net.wifi.WifiManager; import android.service.NetworkIdentityProto; import android.telephony.Annotation.NetworkType; import android.util.proto.ProtoOutputStream; @@ -228,11 +227,11 @@ public class NetworkIdentity implements Comparable { final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities()); if (legacyType == TYPE_WIFI) { - networkId = snapshot.getNetworkCapabilities().getSsid(); - if (networkId == null) { - final WifiManager wifi = context.getSystemService(WifiManager.class); - final WifiInfo info = wifi.getConnectionInfo(); - networkId = info != null ? info.getSSID() : null; + final TransportInfo transportInfo = snapshot.getNetworkCapabilities() + .getTransportInfo(); + if (transportInfo instanceof WifiInfo) { + final WifiInfo info = (WifiInfo) transportInfo; + networkId = info != null ? info.getCurrentNetworkKey() : null; } } diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 5da8e259d0..659ad06039 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -35,7 +35,6 @@ import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_ALL; import static android.net.NetworkStats.ROAMING_NO; import static android.net.NetworkStats.ROAMING_YES; -import static android.net.wifi.WifiInfo.sanitizeSsid; import android.annotation.IntDef; import android.annotation.NonNull; @@ -49,7 +48,7 @@ import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; -import com.android.internal.util.ArrayUtils; +import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkIdentityUtils; import com.android.net.module.util.NetworkStatsUtils; @@ -57,6 +56,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.Collection; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -213,11 +213,14 @@ public final class NetworkTemplate implements Parcelable { public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, @NetworkType int ratType, int metered) { if (TextUtils.isEmpty(subscriberId)) { - return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null, - metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, + return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */, + null /* matchSubscriberIds */, + new String[0] /* matchWifiNetworkKeys */, metered, ROAMING_ALL, + DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } - return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null, + return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[] { subscriberId }, + new String[0] /* matchWifiNetworkKeys */, metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } @@ -235,7 +238,7 @@ public final class NetworkTemplate implements Parcelable { /** * Template to match all metered {@link ConnectivityManager#TYPE_WIFI} networks, - * regardless of SSID. + * regardless of key of the wifi network. * * @hide */ @@ -255,33 +258,40 @@ public final class NetworkTemplate implements Parcelable { /** * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the - * given SSID. + * given key of the wifi network. * + * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()} + * to know details about the key. * @hide */ - public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) { - Objects.requireNonNull(networkId); + public static NetworkTemplate buildTemplateWifi(@NonNull String wifiNetworkKey) { + Objects.requireNonNull(wifiNetworkKey); return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */, new String[] { null } /* matchSubscriberIds */, - networkId, METERED_ALL, ROAMING_ALL, + new String[] { wifiNetworkKey }, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL); } /** - * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID, - * and IMSI. + * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given + * key of the wifi network and IMSI. * - * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code networkId} to get result regardless - * of SSID. + * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless + * of key of the wifi network. + * + * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()} + * to know details about the key. + * @param subscriberId the IMSI associated to this wifi network. * * @hide */ - public static NetworkTemplate buildTemplateWifi(@Nullable String networkId, + public static NetworkTemplate buildTemplateWifi(@Nullable String wifiNetworkKey, @Nullable String subscriberId) { return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId }, - networkId, METERED_ALL, ROAMING_ALL, - DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, + wifiNetworkKey != null + ? new String[] { wifiNetworkKey } : new String[0], + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } @@ -324,7 +334,9 @@ public final class NetworkTemplate implements Parcelable { public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) { Objects.requireNonNull(subscriberId); return new NetworkTemplate(MATCH_CARRIER, subscriberId, - new String[] { subscriberId }, null /* networkId */, METERED_YES, ROAMING_ALL, + new String[] { subscriberId }, + new String[0] /* matchWifiNetworkKeys */, + METERED_YES, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } @@ -342,8 +354,8 @@ public final class NetworkTemplate implements Parcelable { */ private final String[] mMatchSubscriberIds; - // TODO: Change variable name to match the Api surface. - private final String mNetworkId; + @NonNull + private final String[] mMatchWifiNetworkKeys; // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. private final int mMetered; @@ -377,18 +389,19 @@ public final class NetworkTemplate implements Parcelable { /** @hide */ // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S) @UnsupportedAppUsage - public NetworkTemplate(int matchRule, String subscriberId, String networkId) { - this(matchRule, subscriberId, new String[] { subscriberId }, networkId); + public NetworkTemplate(int matchRule, String subscriberId, String wifiNetworkKey) { + this(matchRule, subscriberId, new String[] { subscriberId }, wifiNetworkKey); } /** @hide */ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String networkId) { + String wifiNetworkKey) { // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates // to metered networks. It is now possible to match mobile with any meteredness, but // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this //constructor passes METERED_YES for these types. - this(matchRule, subscriberId, matchSubscriberIds, networkId, + this(matchRule, subscriberId, matchSubscriberIds, + wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0], (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); @@ -397,23 +410,25 @@ public final class NetworkTemplate implements Parcelable { /** @hide */ // TODO: Remove it after updating all of the caller. public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String networkId, int metered, int roaming, int defaultNetwork, int subType, + String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int subType, int oemManaged) { - this(matchRule, subscriberId, matchSubscriberIds, networkId, metered, roaming, - defaultNetwork, subType, oemManaged, + this(matchRule, subscriberId, matchSubscriberIds, + wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0], + metered, roaming, defaultNetwork, subType, oemManaged, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @hide */ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String networkId, int metered, int roaming, int defaultNetwork, int subType, - int oemManaged, int subscriberIdMatchRule) { + String[] matchWifiNetworkKeys, int metered, int roaming, + int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) { + Objects.requireNonNull(matchWifiNetworkKeys); mMatchRule = matchRule; mSubscriberId = subscriberId; // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when // mSubscriberId is null mMatchSubscriberIds = matchSubscriberIds; - mNetworkId = networkId; + mMatchWifiNetworkKeys = matchWifiNetworkKeys; mMetered = metered; mRoaming = roaming; mDefaultNetwork = defaultNetwork; @@ -431,7 +446,7 @@ public final class NetworkTemplate implements Parcelable { mMatchRule = in.readInt(); mSubscriberId = in.readString(); mMatchSubscriberIds = in.createStringArray(); - mNetworkId = in.readString(); + mMatchWifiNetworkKeys = in.createStringArray(); mMetered = in.readInt(); mRoaming = in.readInt(); mDefaultNetwork = in.readInt(); @@ -445,7 +460,7 @@ public final class NetworkTemplate implements Parcelable { dest.writeInt(mMatchRule); dest.writeString(mSubscriberId); dest.writeStringArray(mMatchSubscriberIds); - dest.writeString(mNetworkId); + dest.writeStringArray(mMatchWifiNetworkKeys); dest.writeInt(mMetered); dest.writeInt(mRoaming); dest.writeInt(mDefaultNetwork); @@ -471,9 +486,7 @@ public final class NetworkTemplate implements Parcelable { builder.append(", matchSubscriberIds=").append( Arrays.toString(NetworkIdentityUtils.scrubSubscriberIds(mMatchSubscriberIds))); } - if (mNetworkId != null) { - builder.append(", networkId=").append(mNetworkId); - } + builder.append(", matchWifiNetworkKeys=").append(Arrays.toString(mMatchWifiNetworkKeys)); if (mMetered != METERED_ALL) { builder.append(", metered=").append(NetworkStats.meteredToString(mMetered)); } @@ -497,8 +510,8 @@ public final class NetworkTemplate implements Parcelable { @Override public int hashCode() { - return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming, - mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule); + return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys), + mMetered, mRoaming, mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule); } @Override @@ -507,13 +520,13 @@ public final class NetworkTemplate implements Parcelable { final NetworkTemplate other = (NetworkTemplate) obj; return mMatchRule == other.mMatchRule && Objects.equals(mSubscriberId, other.mSubscriberId) - && Objects.equals(mNetworkId, other.mNetworkId) && mMetered == other.mMetered && mRoaming == other.mRoaming && mDefaultNetwork == other.mDefaultNetwork && mSubType == other.mSubType && mOemManaged == other.mOemManaged - && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule; + && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule + && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys); } return false; } @@ -579,14 +592,22 @@ public final class NetworkTemplate implements Parcelable { */ @Nullable public String getWifiNetworkKey() { - return mNetworkId; + return CollectionUtils.isEmpty(mMatchWifiNetworkKeys) ? null : mMatchWifiNetworkKeys[0]; + } + + /** + * Get set of Wifi Network Keys of the template. + */ + @Nullable + public Set getWifiNetworkKeys() { + return new ArraySet<>(Arrays.asList(mMatchWifiNetworkKeys)); } /** @hide */ // TODO: Remove this and replace all callers with {@link #getWifiNetworkKey()}. @Nullable public String getNetworkId() { - return mNetworkId; + return getWifiNetworkKey(); } /** @@ -703,28 +724,33 @@ public final class NetworkTemplate implements Parcelable { */ public boolean matchesSubscriberId(@Nullable String subscriberId) { return mSubscriberIdMatchRule == NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_ALL - || ArrayUtils.contains(mMatchSubscriberIds, subscriberId); + || CollectionUtils.contains(mMatchSubscriberIds, subscriberId); } /** - * Check if network with matching SSID. Returns true when the SSID matches, or when - * {@code mNetworkId} is {@code WIFI_NETWORK_KEY_ALL}. + * Check if network matches key of the wifi network. + * Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is + * empty. + * + * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()} + * to know details about the key. */ - private boolean matchesWifiNetworkId(@Nullable String networkId) { - return Objects.equals(mNetworkId, WIFI_NETWORK_KEY_ALL) - || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId)); + private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) { + Objects.requireNonNull(wifiNetworkKey); + return CollectionUtils.isEmpty(mMatchWifiNetworkKeys) + || CollectionUtils.contains(mMatchWifiNetworkKeys, wifiNetworkKey); } /** - * Check if mobile network with matching IMSI. + * Check if mobile network matches IMSI. */ private boolean matchesMobile(NetworkIdentity ident) { if (ident.mType == TYPE_WIMAX) { // TODO: consider matching against WiMAX subscriber identity return true; } else { - return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds) - && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) + return ident.mType == TYPE_MOBILE && !CollectionUtils.isEmpty(mMatchSubscriberIds) + && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId) && matchesCollapsedRatType(ident); } } @@ -814,7 +840,7 @@ public final class NetworkTemplate implements Parcelable { switch (ident.mType) { case TYPE_WIFI: return matchesSubscriberId(ident.mSubscriberId) - && matchesWifiNetworkId(ident.mNetworkId); + && matchesWifiNetworkKey(ident.mNetworkId); default: return false; } @@ -835,8 +861,8 @@ public final class NetworkTemplate implements Parcelable { */ private boolean matchesCarrier(NetworkIdentity ident) { return ident.mSubscriberId != null - && !ArrayUtils.isEmpty(mMatchSubscriberIds) - && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); + && !CollectionUtils.isEmpty(mMatchSubscriberIds) + && CollectionUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); } private boolean matchesMobileWildcard(NetworkIdentity ident) { @@ -953,11 +979,13 @@ public final class NetworkTemplate implements Parcelable { if (template.mSubscriberId == null) return template; for (String[] merged : mergedList) { - if (ArrayUtils.contains(merged, template.mSubscriberId)) { + if (CollectionUtils.contains(merged, template.mSubscriberId)) { // Requested template subscriber is part of the merge group; return // a template that matches all merged subscribers. + final String[] matchWifiNetworkKeys = template.mMatchWifiNetworkKeys; return new NetworkTemplate(template.mMatchRule, merged[0], merged, - template.mNetworkId); + CollectionUtils.isEmpty(matchWifiNetworkKeys) + ? null : matchWifiNetworkKeys[0]); } } @@ -984,9 +1012,10 @@ public final class NetworkTemplate implements Parcelable { private final int mMatchRule; // Use a SortedSet to provide a deterministic order when fetching the first one. @NonNull - private final SortedSet mMatchSubscriberIds = new TreeSet<>(); - @Nullable - private String mWifiNetworkKey; + private final SortedSet mMatchSubscriberIds = + new TreeSet<>(Comparator.nullsFirst(Comparator.naturalOrder())); + @NonNull + private final SortedSet mMatchWifiNetworkKeys = new TreeSet<>(); // Matches for the NetworkStats constants METERED_*, ROAMING_* and DEFAULT_NETWORK_*. private int mMetered; @@ -1006,7 +1035,6 @@ public final class NetworkTemplate implements Parcelable { assertRequestableMatchRule(matchRule); // Initialize members with default values. mMatchRule = matchRule; - mWifiNetworkKey = WIFI_NETWORK_KEY_ALL; mMetered = METERED_ALL; mRoaming = ROAMING_ALL; mDefaultNetwork = DEFAULT_NETWORK_ALL; @@ -1030,15 +1058,28 @@ public final class NetworkTemplate implements Parcelable { } /** - * Set the Wifi Network Key. + * Set the Wifi Network Keys. Calling this function with an empty set represents + * the intention of matching any Wifi Network Key. * - * @param wifiNetworkKey the Wifi Network Key, see {@link WifiInfo#getCurrentNetworkKey()}. - * Or null to match all networks. + * @param wifiNetworkKeys the list of Wifi Network Key, + * see {@link WifiInfo#getCurrentNetworkKey()}. + * Or an empty list to match all networks. + * Note that {@code getCurrentNetworkKey()} might get null key + * when wifi disconnects. However, the caller should never invoke + * this function with a null Wifi Network Key since such statistics + * never exists. * @return this builder. */ @NonNull - public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) { - mWifiNetworkKey = wifiNetworkKey; + public Builder setWifiNetworkKeys(@NonNull Set wifiNetworkKeys) { + Objects.requireNonNull(wifiNetworkKeys); + for (String key : wifiNetworkKeys) { + if (key == null) { + throw new IllegalArgumentException("Null is not a valid key"); + } + } + mMatchWifiNetworkKeys.clear(); + mMatchWifiNetworkKeys.addAll(wifiNetworkKeys); return this; } @@ -1122,9 +1163,17 @@ public final class NetworkTemplate implements Parcelable { } private void assertRequestableParameters() { + validateWifiNetworkKeys(); // TODO: Check all the input are legitimate. } + private void validateWifiNetworkKeys() { + if (mMatchRule != MATCH_WIFI && !mMatchWifiNetworkKeys.isEmpty()) { + throw new IllegalArgumentException("Trying to build non wifi match rule: " + + mMatchRule + " with wifi network keys"); + } + } + /** * For backward compatibility, deduce match rule to a wildcard match rule * if the Subscriber Ids are empty. @@ -1133,7 +1182,7 @@ public final class NetworkTemplate implements Parcelable { if (mMatchRule == MATCH_MOBILE && mMatchSubscriberIds.isEmpty()) { return MATCH_MOBILE_WILDCARD; } else if (mMatchRule == MATCH_WIFI && mMatchSubscriberIds.isEmpty() - && mWifiNetworkKey == WIFI_NETWORK_KEY_ALL) { + && mMatchWifiNetworkKeys.isEmpty()) { return MATCH_WIFI_WILDCARD; } return mMatchRule; @@ -1153,8 +1202,8 @@ public final class NetworkTemplate implements Parcelable { return new NetworkTemplate(getWildcardDeducedMatchRule(), mMatchSubscriberIds.isEmpty() ? null : mMatchSubscriberIds.iterator().next(), mMatchSubscriberIds.toArray(new String[0]), - mWifiNetworkKey, mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, - subscriberIdMatchRule); + mMatchWifiNetworkKeys.toArray(new String[0]), mMetered, mRoaming, + mDefaultNetwork, mRatType, mOemManaged, subscriberIdMatchRule); } } } From 9426a6f03488c78f1581c13d9a1119bc1baee840 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 30 Dec 2021 10:49:29 +0000 Subject: [PATCH 737/881] [MS31] Fix several hidden API usages This includes: 1. Replace UserHandle.getUid(userId, appId) with public API 2. Remove Preconditions.checkArgument 3. Replace MathUtil.constrain with the one in NetworkStatsUtils 4. Remove Sets 5. Replace NetworkStack.checkNetworkStackPermission with the one in the PermissionUtils 6. Replace internal CollectionUtils with the one in the module 7. Inline ProtoOutputStream(fd) 8. Replace Intent.EXTRA_USER_HANDLE with Intent.EXTRA_USER Test: atest NetworkStatsSubscriptionsMonitorTest \ NetworkStatsServiceTest Bug: 204830222 Change-Id: If06a27b04ad15c29052b670eefc2f6dc0d199420 --- .../server/net/NetworkStatsObservers.java | 7 ++--- .../server/net/NetworkStatsRecorder.java | 8 +++--- .../server/net/NetworkStatsService.java | 20 +++++++------- .../net/NetworkStatsSubscriptionsMonitor.java | 26 ++++++++++--------- 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java index 9aa20a4830..b57a4f920b 100644 --- a/service-t/src/com/android/server/net/NetworkStatsObservers.java +++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java @@ -18,8 +18,6 @@ package com.android.server.net; import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES; -import static com.android.internal.util.Preconditions.checkArgument; - import android.app.usage.NetworkStatsManager; import android.net.DataUsageRequest; import android.net.NetworkIdentitySet; @@ -216,7 +214,10 @@ class NetworkStatsObservers { accessLevel); } else { // Safety check in case a new access level is added and we forgot to update this - checkArgument(accessLevel >= NetworkStatsAccess.Level.DEVICESUMMARY); + if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) { + throw new IllegalArgumentException( + "accessLevel " + accessLevel + " is less than DEVICESUMMARY."); + } return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid, accessLevel); } diff --git a/service-t/src/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java index cec6609dc4..c371f0859a 100644 --- a/service-t/src/com/android/server/net/NetworkStatsRecorder.java +++ b/service-t/src/com/android/server/net/NetworkStatsRecorder.java @@ -34,12 +34,10 @@ import android.os.DropBoxManager; import android.service.NetworkStatsRecorderProto; import android.util.IndentingPrintWriter; import android.util.Log; -import android.util.MathUtils; import android.util.proto.ProtoOutputStream; import com.android.internal.util.FileRotator; - -import com.google.android.collect.Sets; +import com.android.net.module.util.NetworkStatsUtils; import libcore.io.IoUtils; @@ -132,7 +130,7 @@ public class NetworkStatsRecorder { public void setPersistThreshold(long thresholdBytes) { if (LOGV) Log.v(TAG, "setPersistThreshold() with " + thresholdBytes); - mPersistThresholdBytes = MathUtils.constrain( + mPersistThresholdBytes = NetworkStatsUtils.constrain( thresholdBytes, 1 * KB_IN_BYTES, 100 * MB_IN_BYTES); } @@ -206,7 +204,7 @@ public class NetworkStatsRecorder { */ public void recordSnapshotLocked(NetworkStats snapshot, Map ifaceIdent, long currentTimeMillis) { - final HashSet unknownIfaces = Sets.newHashSet(); + final HashSet unknownIfaces = new HashSet<>(); // skip recording when snapshot missing if (snapshot == null) return; diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 44d7d1f668..4fd62c1ad5 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -25,7 +25,6 @@ import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.NetworkIdentity.SUBTYPE_COMBINED; -import static android.net.NetworkStack.checkNetworkStackPermission; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.IFACE_VT; @@ -158,6 +157,7 @@ import com.android.server.LocalServices; import java.io.File; import java.io.FileDescriptor; +import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.time.Clock; @@ -985,7 +985,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull NetworkStateSnapshot[] networkStates, @Nullable String activeIface, @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) { - checkNetworkStackPermission(mContext); + PermissionUtils.enforceNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); try { @@ -1201,13 +1201,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // On background handler thread, and USER_REMOVED is protected // broadcast. - final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userId == -1) return; + final UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER); + if (userHandle == null) return; synchronized (mStatsLock) { mWakeLock.acquire(); try { - removeUserLocked(userId); + removeUserLocked(userHandle); } finally { mWakeLock.release(); } @@ -1232,7 +1232,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void limitReached(String limitName, String iface) { // only someone like NMS should be calling us - NetworkStack.checkNetworkStackPermission(mContext); + PermissionUtils.enforceNetworkStackPermission(mContext); if (LIMIT_GLOBAL_ALERT.equals(limitName)) { // kick off background poll to collect network stats unless there is already @@ -1652,8 +1652,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Clean up {@link #mUidRecorder} after user is removed. */ @GuardedBy("mStatsLock") - private void removeUserLocked(int userId) { - if (LOGV) Log.v(TAG, "removeUserLocked() for userId=" + userId); + private void removeUserLocked(@NonNull UserHandle userHandle) { + if (LOGV) Log.v(TAG, "removeUserLocked() for UserHandle=" + userHandle); // Build list of UIDs that we should clean up final ArrayList uids = new ArrayList<>(); @@ -1661,7 +1661,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { PackageManager.MATCH_ANY_USER | PackageManager.MATCH_DISABLED_COMPONENTS); for (ApplicationInfo app : apps) { - final int uid = UserHandle.getUid(userId, app.uid); + final int uid = userHandle.getUid(app.uid); uids.add(uid); } @@ -1869,7 +1869,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private void dumpProtoLocked(FileDescriptor fd) { - final ProtoOutputStream proto = new ProtoOutputStream(fd); + final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd)); // TODO Right now it writes all history. Should it limit to the "since-boot" log? diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 5646c752fc..93d0ae7da0 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -33,7 +33,7 @@ import android.util.Log; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.CollectionUtils; +import com.android.net.module.util.CollectionUtils; import java.util.ArrayList; import java.util.List; @@ -99,18 +99,19 @@ public class NetworkStatsSubscriptionsMonitor extends // prevent binder call to telephony when querying RAT. Keep listener registration with empty // IMSI is meaningless since the RAT type changed is ambiguous for multi-SIM if reported // with empty IMSI. So filter the subs w/o a valid IMSI to prevent such registration. - final List> filteredNewSubs = - CollectionUtils.mapNotNull(newSubs, subId -> { - final String subscriberId = mTeleManager.getSubscriberId(subId); - return TextUtils.isEmpty(subscriberId) ? null : new Pair(subId, subscriberId); - }); + final List> filteredNewSubs = new ArrayList<>(); + for (final int subId : newSubs) { + final String subscriberId = mTeleManager.getSubscriberId(subId); + if (!TextUtils.isEmpty(subscriberId)) { + filteredNewSubs.add(new Pair(subId, subscriberId)); + } + } for (final Pair sub : filteredNewSubs) { // Fully match listener with subId and IMSI, since in some rare cases, IMSI might be // suddenly change regardless of subId, such as switch IMSI feature in modem side. // If that happens, register new listener with new IMSI and remove old one later. - if (CollectionUtils.find(mRatListeners, - it -> it.equalsKey(sub.first, sub.second)) != null) { + if (CollectionUtils.any(mRatListeners, it -> it.equalsKey(sub.first, sub.second))) { continue; } @@ -126,8 +127,8 @@ public class NetworkStatsSubscriptionsMonitor extends for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { // If there is no subId and IMSI matched the listener, removes it. - if (CollectionUtils.find(filteredNewSubs, - it -> listener.equalsKey(it.first, it.second)) == null) { + if (!CollectionUtils.any(filteredNewSubs, + it -> listener.equalsKey(it.first, it.second))) { handleRemoveRatTypeListener(listener); } } @@ -148,9 +149,10 @@ public class NetworkStatsSubscriptionsMonitor extends * @return collapsed RatType for the given subscriberId */ public int getRatTypeForSubscriberId(@NonNull String subscriberId) { - final RatTypeListener match = CollectionUtils.find(mRatListeners, + final int index = CollectionUtils.indexOf(mRatListeners, it -> TextUtils.equals(subscriberId, it.mSubscriberId)); - return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN; + return index != -1 ? mRatListeners.get(index).mLastCollapsedRatType + : TelephonyManager.NETWORK_TYPE_UNKNOWN; } /** From 1d1c2d22c78d2d96712460f5d0e916fcedcfd722 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 3 Jan 2022 12:30:03 +0000 Subject: [PATCH 738/881] [MS33.1] Remove NetdService dependency This change pass INetd to NetworkStatsFactory to replace NetdService#getNetdInstance. Test: atest FrameworksNetTests Bug: 204830222 Change-Id: I39b278989cea06dd316f21214380b5c4b54d2d50 --- .../android/server/net/NetworkStatsFactory.java | 16 +++++++--------- .../android/server/net/NetworkStatsService.java | 6 ++++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java index c7c8893ed8..bb123a38eb 100644 --- a/service-t/src/com/android/server/net/NetworkStatsFactory.java +++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java @@ -24,11 +24,11 @@ import static android.net.NetworkStats.UID_ALL; import static com.android.server.NetworkManagementSocketTagger.kernelToTag; +import android.annotation.NonNull; import android.annotation.Nullable; import android.net.INetd; import android.net.NetworkStats; import android.net.UnderlyingNetworkInfo; -import android.net.util.NetdService; import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemClock; @@ -70,7 +70,7 @@ public class NetworkStatsFactory { private final boolean mUseBpfStats; - private INetd mNetdService; + private final INetd mNetd; /** * Guards persistent data access in this class @@ -158,12 +158,12 @@ public class NetworkStatsFactory { NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces); } - public NetworkStatsFactory() { - this(new File("/proc/"), true); + public NetworkStatsFactory(@NonNull INetd netd) { + this(new File("/proc/"), true, netd); } @VisibleForTesting - public NetworkStatsFactory(File procRoot, boolean useBpfStats) { + public NetworkStatsFactory(File procRoot, boolean useBpfStats, @NonNull INetd netd) { mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); @@ -172,6 +172,7 @@ public class NetworkStatsFactory { mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } + mNetd = netd; } public NetworkStats readBpfNetworkStatsDev() throws IOException { @@ -298,10 +299,7 @@ public class NetworkStatsFactory { // Ask netd to do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map // without race problem. - if (mNetdService == null) { - mNetdService = NetdService.getInstance(); - } - mNetdService.trafficSwapActiveStatsMap(); + mNetd.trafficSwapActiveStatsMap(); } /** diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index a3de9e4ba7..ef84ce02e2 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -89,6 +89,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.database.ContentObserver; import android.net.DataUsageRequest; +import android.net.INetd; import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; @@ -410,10 +411,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - + final INetd netd = INetd.Stub.asInterface( + (IBinder) context.getSystemService(Context.NETD_SERVICE)); final NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, wakeLock, getDefaultClock(), - new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), + new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); service.registerLocalService(); From 9c6fd5266e1628c3b6c9a5e99c329ac97b811d24 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Sun, 26 Dec 2021 12:43:03 -0800 Subject: [PATCH 739/881] Eth Service updates to validate net mgmt calls Updates to ethernet service code to validate calls to ethernet network management APIs. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I66b91c6d12e6859de33760ab21bb00f1477720e8 --- .../server/ethernet/EthernetServiceImpl.java | 46 +++++- .../ethernet/EthernetServiceImplTest.java | 142 ++++++++++++++++++ 2 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 840806af18..fd690b5547 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -33,6 +33,7 @@ import android.os.RemoteException; import android.util.Log; import android.util.PrintWriterPrinter; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.net.module.util.PermissionUtils; @@ -49,7 +50,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { private static final String TAG = "EthernetServiceImpl"; private final Context mContext; - private final AtomicBoolean mStarted = new AtomicBoolean(false); + @VisibleForTesting + final AtomicBoolean mStarted = new AtomicBoolean(false); private Handler mHandler; private EthernetTracker mTracker; @@ -70,6 +72,17 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { "ConnectivityService"); } + private void enforceAutomotiveDevice(final @NonNull String methodName) { + PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE, + methodName + " is only available on automotive devices."); + } + + private void enforceInterfaceIsTracked(final @NonNull String iface) { + if(!mTracker.isTrackingInterface(iface)) { + throw new UnsupportedOperationException("The given iface is not currently tracked."); + } + } + private boolean checkUseRestrictedNetworksPermission() { return mContext.checkCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS) @@ -89,6 +102,12 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mStarted.set(true); } + private void logIfEthernetNotStarted() { + if (!mStarted.get()) { + throw new IllegalStateException("System isn't ready to change ethernet configurations"); + } + } + @Override public String[] getAvailableInterfaces() throws RemoteException { enforceAccessPermission(); @@ -116,9 +135,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { */ @Override public void setConfiguration(String iface, IpConfiguration config) { - if (!mStarted.get()) { - Log.w(TAG, "System isn't ready enough to change ethernet configuration"); - } + logIfEthernetNotStarted(); PermissionUtils.enforceNetworkStackPermission(mContext); @@ -214,23 +231,44 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { pw.decreaseIndent(); } + /** + * Validate the state of ethernet for APIs tied to network management. + * + * @param iface the ethernet interface name to operate on. + * @param methodName the name of the calling method. + */ + private void validateNetworkManagementState(@NonNull final String iface, + final @NonNull String methodName) { + logIfEthernetNotStarted(); + + // TODO: add permission check here for MANAGE_INTERNAL_NETWORKS when it's available. + Objects.requireNonNull(iface, "Pass a non-null iface."); + Objects.requireNonNull(methodName, "Pass a non-null methodName."); + enforceAutomotiveDevice(methodName); + enforceInterfaceIsTracked(iface); + } + @Override public void updateConfiguration(@NonNull final String iface, @NonNull final InternalNetworkUpdateRequest request, @Nullable final IInternalNetworkManagementListener listener) { Log.i(TAG, "updateConfiguration called with: iface=" + iface + ", request=" + request + ", listener=" + listener); + validateNetworkManagementState(iface, "updateConfiguration()"); + // TODO: validate that iface is listed in overlay config_ethernet_interfaces } @Override public void connectNetwork(@NonNull final String iface, @Nullable final IInternalNetworkManagementListener listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); + validateNetworkManagementState(iface, "connectNetwork()"); } @Override public void disconnectNetwork(@NonNull final String iface, @Nullable final IInternalNetworkManagementListener listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); + validateNetworkManagementState(iface, "disconnectNetwork()"); } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java new file mode 100644 index 0000000000..9869b82cb2 --- /dev/null +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.ethernet; + +import static org.junit.Assert.assertThrows; + +import static org.mockito.Mockito.doReturn; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.net.InternalNetworkUpdateRequest; +import android.net.IpConfiguration; +import android.net.StaticIpConfiguration; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class EthernetServiceImplTest { + private EthernetServiceImpl mEthernetServiceImpl; + @Mock private Context mContext; + @Mock private PackageManager mPackageManager; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + doReturn(mPackageManager).when(mContext).getPackageManager(); + mEthernetServiceImpl = new EthernetServiceImpl(mContext); + mEthernetServiceImpl.mStarted.set(true); + } + + @Test + public void testSetConfigurationRejectsWhenEthNotStarted() { + mEthernetServiceImpl.mStarted.set(false); + assertThrows(IllegalStateException.class, () -> { + mEthernetServiceImpl.setConfiguration("" /* iface */, new IpConfiguration()); + }); + } + + @Test + public void testUpdateConfigurationRejectsWhenEthNotStarted() { + mEthernetServiceImpl.mStarted.set(false); + assertThrows(IllegalStateException.class, () -> { + final InternalNetworkUpdateRequest r = + new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); + + mEthernetServiceImpl.updateConfiguration("" /* iface */, r, null /* listener */); + }); + } + + @Test + public void testConnectNetworkRejectsWhenEthNotStarted() { + mEthernetServiceImpl.mStarted.set(false); + assertThrows(IllegalStateException.class, () -> { + mEthernetServiceImpl.connectNetwork("" /* iface */, null /* listener */); + }); + } + + @Test + public void testDisconnectNetworkRejectsWhenEthNotStarted() { + mEthernetServiceImpl.mStarted.set(false); + assertThrows(IllegalStateException.class, () -> { + mEthernetServiceImpl.disconnectNetwork("" /* iface */, null /* listener */); + }); + } + + @Test + public void testUpdateConfigurationRejectsNullIface() { + assertThrows(NullPointerException.class, () -> { + final InternalNetworkUpdateRequest r = + new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); + + mEthernetServiceImpl.updateConfiguration(null /* iface */, r, null /* listener */); + }); + } + + @Test + public void testConnectNetworkRejectsNullIface() { + assertThrows(NullPointerException.class, () -> { + mEthernetServiceImpl.connectNetwork(null /* iface */, null /* listener */); + }); + } + + @Test + public void testDisconnectNetworkRejectsNullIface() { + assertThrows(NullPointerException.class, () -> { + mEthernetServiceImpl.disconnectNetwork(null /* iface */, null /* listener */); + }); + } + + @Test + public void testUpdateConfigurationRejectsWithoutAutomotiveFeature() { + disableAutomotiveFeature(); + assertThrows(UnsupportedOperationException.class, () -> { + final InternalNetworkUpdateRequest r = + new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); + + mEthernetServiceImpl.updateConfiguration("" /* iface */, r, null /* listener */); + }); + } + + @Test + public void testConnectNetworkRejectsWithoutAutomotiveFeature() { + disableAutomotiveFeature(); + assertThrows(UnsupportedOperationException.class, () -> { + mEthernetServiceImpl.connectNetwork("" /* iface */, null /* listener */); + }); + } + + @Test + public void testDisconnectNetworkRejectsWithoutAutomotiveFeature() { + disableAutomotiveFeature(); + assertThrows(UnsupportedOperationException.class, () -> { + mEthernetServiceImpl.disconnectNetwork("" /* iface */, null /* listener */); + }); + } + + private void disableAutomotiveFeature() { + doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); + } +} From 1daccdcb497575afd65061113308b895696d1665 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 28 Dec 2021 15:04:44 -0800 Subject: [PATCH 740/881] Changes to make eth service methods more testable Updates to make methods in EthernetServiceImpl that rely on EthernetTracker unit testable. This CL also includes added tests for such methods in EthernetServiceImplTest. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I63969b60cc4cf9d391e2cd21d02e1bdc8988aba8 --- .../server/ethernet/EthernetService.java | 11 +++- .../server/ethernet/EthernetServiceImpl.java | 20 +++----- .../server/ethernet/EthernetTracker.java | 10 ++-- .../ethernet/EthernetServiceImplTest.java | 51 ++++++++++++++++--- 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetService.java b/service-t/src/com/android/server/ethernet/EthernetService.java index 2448146ed5..467ab677d8 100644 --- a/service-t/src/com/android/server/ethernet/EthernetService.java +++ b/service-t/src/com/android/server/ethernet/EthernetService.java @@ -17,17 +17,24 @@ package com.android.server.ethernet; import android.content.Context; +import android.os.Handler; +import android.os.HandlerThread; import android.util.Log; import com.android.server.SystemService; public final class EthernetService extends SystemService { private static final String TAG = "EthernetService"; - final EthernetServiceImpl mImpl; + private static final String THREAD_NAME = "EthernetServiceThread"; + private final EthernetServiceImpl mImpl; public EthernetService(Context context) { super(context); - mImpl = new EthernetServiceImpl(context); + final HandlerThread handlerThread = new HandlerThread(THREAD_NAME); + handlerThread.start(); + mImpl = new EthernetServiceImpl( + context, handlerThread.getThreadHandler(), + new EthernetTracker(context, handlerThread.getThreadHandler())); } @Override diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index fd690b5547..3479ea4722 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -28,7 +28,6 @@ import android.net.InternalNetworkUpdateRequest; import android.net.IpConfiguration; import android.os.Binder; import android.os.Handler; -import android.os.HandlerThread; import android.os.RemoteException; import android.util.Log; import android.util.PrintWriterPrinter; @@ -49,15 +48,17 @@ import java.util.concurrent.atomic.AtomicBoolean; public class EthernetServiceImpl extends IEthernetManager.Stub { private static final String TAG = "EthernetServiceImpl"; - private final Context mContext; @VisibleForTesting final AtomicBoolean mStarted = new AtomicBoolean(false); + private final Context mContext; + private final Handler mHandler; + private final EthernetTracker mTracker; - private Handler mHandler; - private EthernetTracker mTracker; - - public EthernetServiceImpl(Context context) { + EthernetServiceImpl(@NonNull final Context context, @NonNull final Handler handler, + @NonNull final EthernetTracker tracker) { mContext = context; + mHandler = handler; + mTracker = tracker; } private void enforceAccessPermission() { @@ -91,14 +92,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { public void start() { Log.i(TAG, "Starting Ethernet service"); - - HandlerThread handlerThread = new HandlerThread("EthernetServiceThread"); - handlerThread.start(); - mHandler = new Handler(handlerThread.getLooper()); - - mTracker = new EthernetTracker(mContext, mHandler); mTracker.start(); - mStarted.set(true); } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 65c3cefe0d..9660194508 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -18,6 +18,8 @@ package com.android.server.ethernet; import static android.net.TestNetworkManager.TEST_TAP_PREFIX; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -67,7 +69,8 @@ import java.util.concurrent.ConcurrentHashMap; * *

All public or package private methods must be thread-safe unless stated otherwise. */ -final class EthernetTracker { +@VisibleForTesting(visibility = PACKAGE) +public class EthernetTracker { private static final int INTERFACE_MODE_CLIENT = 1; private static final int INTERFACE_MODE_SERVER = 2; @@ -138,10 +141,10 @@ final class EthernetTracker { NetworkCapabilities nc = createNetworkCapabilities(true /* clear default capabilities */); mFactory = new EthernetNetworkFactory(handler, context, nc); - mFactory.register(); } void start() { + mFactory.register(); mConfigStore.read(); // Default interface is just the first one we want to track. @@ -176,7 +179,8 @@ final class EthernetTracker { return mIpConfigurations.get(iface); } - boolean isTrackingInterface(String iface) { + @VisibleForTesting(visibility = PACKAGE) + protected boolean isTrackingInterface(String iface) { return mFactory.hasInterface(iface); } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 9869b82cb2..516e574522 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -20,11 +20,13 @@ import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.doReturn; +import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; import android.net.InternalNetworkUpdateRequest; import android.net.IpConfiguration; import android.net.StaticIpConfiguration; +import android.os.Handler; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -38,16 +40,21 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) @SmallTest public class EthernetServiceImplTest { + private static final String TEST_IFACE = "test123"; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; + @Mock private Handler mHandler; + @Mock private EthernetTracker mEthernetTracker; @Mock private PackageManager mPackageManager; @Before public void setup() { MockitoAnnotations.initMocks(this); doReturn(mPackageManager).when(mContext).getPackageManager(); - mEthernetServiceImpl = new EthernetServiceImpl(mContext); + mEthernetServiceImpl = new EthernetServiceImpl(mContext, mHandler, mEthernetTracker); mEthernetServiceImpl.mStarted.set(true); + toggleAutomotiveFeature(true); + shouldTrackIface(TEST_IFACE, true); } @Test @@ -111,7 +118,7 @@ public class EthernetServiceImplTest { @Test public void testUpdateConfigurationRejectsWithoutAutomotiveFeature() { - disableAutomotiveFeature(); + toggleAutomotiveFeature(false); assertThrows(UnsupportedOperationException.class, () -> { final InternalNetworkUpdateRequest r = new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); @@ -122,7 +129,7 @@ public class EthernetServiceImplTest { @Test public void testConnectNetworkRejectsWithoutAutomotiveFeature() { - disableAutomotiveFeature(); + toggleAutomotiveFeature(false); assertThrows(UnsupportedOperationException.class, () -> { mEthernetServiceImpl.connectNetwork("" /* iface */, null /* listener */); }); @@ -130,13 +137,45 @@ public class EthernetServiceImplTest { @Test public void testDisconnectNetworkRejectsWithoutAutomotiveFeature() { - disableAutomotiveFeature(); + toggleAutomotiveFeature(false); assertThrows(UnsupportedOperationException.class, () -> { mEthernetServiceImpl.disconnectNetwork("" /* iface */, null /* listener */); }); } - private void disableAutomotiveFeature() { - doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); + private void toggleAutomotiveFeature(final boolean isEnabled) { + doReturn(isEnabled) + .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); + } + + @Test + public void testUpdateConfigurationRejectsWithUntrackedIface() { + shouldTrackIface(TEST_IFACE, false); + assertThrows(UnsupportedOperationException.class, () -> { + final InternalNetworkUpdateRequest r = + new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); + + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, r, null /* listener */); + }); + } + + @Test + public void testConnectNetworkRejectsWithUntrackedIface() { + shouldTrackIface(TEST_IFACE, false); + assertThrows(UnsupportedOperationException.class, () -> { + mEthernetServiceImpl.connectNetwork(TEST_IFACE, null /* listener */); + }); + } + + @Test + public void testDisconnectNetworkRejectsWithUntrackedIface() { + shouldTrackIface(TEST_IFACE, false); + assertThrows(UnsupportedOperationException.class, () -> { + mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, null /* listener */); + }); + } + + private void shouldTrackIface(@NonNull final String iface, final boolean shouldTrack) { + doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface); } } From 284b25cce3a8bcdb7f7ce9cb88bc2918238b6cc2 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 28 Dec 2021 18:24:42 -0800 Subject: [PATCH 741/881] Using PermissionUtils for common net permissions Code clean-up to use PermissionUtils for common networking permissions. Should be a no-op. Bug: 210485380 Test: make, flash and boot Change-Id: I4be08243156e9d04f4b3b44ab7328d0f6f7fdda1 --- .../server/ethernet/EthernetServiceImpl.java | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 3479ea4722..f107865c30 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -61,18 +61,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker = tracker; } - private void enforceAccessPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.ACCESS_NETWORK_STATE, - "EthernetService"); - } - - private void enforceUseRestrictedNetworksPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS, - "ConnectivityService"); - } - private void enforceAutomotiveDevice(final @NonNull String methodName) { PermissionUtils.enforceSystemFeature(mContext, PackageManager.FEATURE_AUTOMOTIVE, methodName + " is only available on automotive devices."); @@ -85,9 +73,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { } private boolean checkUseRestrictedNetworksPermission() { - return mContext.checkCallingOrSelfPermission( - android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS) - == PackageManager.PERMISSION_GRANTED; + return PermissionUtils.checkAnyPermissionOf(mContext, + android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS); } public void start() { @@ -104,8 +91,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public String[] getAvailableInterfaces() throws RemoteException { - enforceAccessPermission(); - + PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); return mTracker.getInterfaces(checkUseRestrictedNetworksPermission()); } @@ -115,10 +101,9 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { */ @Override public IpConfiguration getConfiguration(String iface) { - enforceAccessPermission(); - + PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); if (mTracker.isRestrictedInterface(iface)) { - enforceUseRestrictedNetworksPermission(); + PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG); } return new IpConfiguration(mTracker.getIpConfiguration(iface)); @@ -132,9 +117,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { logIfEthernetNotStarted(); PermissionUtils.enforceNetworkStackPermission(mContext); - if (mTracker.isRestrictedInterface(iface)) { - enforceUseRestrictedNetworksPermission(); + PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG); } // TODO: this does not check proxy settings, gateways, etc. @@ -147,10 +131,9 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { */ @Override public boolean isAvailable(String iface) { - enforceAccessPermission(); - + PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); if (mTracker.isRestrictedInterface(iface)) { - enforceUseRestrictedNetworksPermission(); + PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG); } return mTracker.isTrackingInterface(iface); @@ -164,7 +147,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } - enforceAccessPermission(); + PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); mTracker.addListener(listener, checkUseRestrictedNetworksPermission()); } @@ -176,7 +159,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } - enforceAccessPermission(); + PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); mTracker.removeListener(listener); } From e2359604218fa243404ee246e5c45dcd1be440f5 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Fri, 31 Dec 2021 15:54:23 -0800 Subject: [PATCH 742/881] Code cleanup on EthernetNetworkFactoryTest Code cleanup on EthernetNetworkFactoryTest. Bug: 210485380 Test: atest EthernetServiceTests: com.android.server.ethernet.EthernetNetworkFactoryTest Change-Id: I38c568d0760e4273f1ca8540bac268f07876b67f --- .../ethernet/EthernetNetworkFactoryTest.java | 173 +++++++++--------- 1 file changed, 85 insertions(+), 88 deletions(-) diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 4abdf030ac..08a70a6f40 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -64,11 +64,11 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) @SmallTest public class EthernetNetworkFactoryTest { - private TestLooper mLooper = new TestLooper(); + private static final String TEST_IFACE = "test123"; + private final TestLooper mLooper = new TestLooper(); private Handler mHandler; private EthernetNetworkFactory mNetFactory = null; private IpClientCallbacks mIpClientCallbacks; - private int mNetworkRequestCount = 0; @Mock private Context mContext; @Mock private Resources mResources; @Mock private EthernetNetworkFactory.Dependencies mDeps; @@ -79,10 +79,7 @@ public class EthernetNetworkFactoryTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mHandler = new Handler(mLooper.getLooper()); - mNetworkRequestCount = 0; - mNetFactory = new EthernetNetworkFactory(mHandler, mContext, createDefaultFilterCaps(), mDeps); @@ -129,10 +126,24 @@ public class EthernetNetworkFactoryTest { }).when(mIpClient).shutdown(); } + private void triggerOnProvisioningSuccess() { + mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); + mLooper.dispatchAll(); + } + + private void triggerOnProvisioningFailure() { + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + } + + private void triggerOnReachabilityLost() { + mIpClientCallbacks.onReachabilityLost("ReachabilityLost"); + mLooper.dispatchAll(); + } + private void setupContext() { when(mContext.getResources()).thenReturn(mResources); - when(mResources.getString(R.string.config_ethernet_tcp_buffers)).thenReturn( - "524288,1048576,3145728,524288,1048576,2097152"); + when(mResources.getString(R.string.config_ethernet_tcp_buffers)).thenReturn(""); } @After @@ -184,8 +195,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.addInterface(iface, iface, createInterfaceCapsBuilder(transportType).build(), createDefaultIpConfig()); assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); - verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); - verify(mIpClient).startProvisioning(any()); + verifyStart(); clearInvocations(mDeps); clearInvocations(mIpClient); } @@ -197,18 +207,23 @@ public class EthernetNetworkFactoryTest { ConnectivityManager.TYPE_ETHERNET); } + private void createVerifyAndRemoveProvisionedInterface(final int transportType, + final int expectedLegacyType) throws Exception { + createAndVerifyProvisionedInterface(TEST_IFACE, transportType, + expectedLegacyType); + mNetFactory.removeInterface(TEST_IFACE); + } + private void createAndVerifyProvisionedInterface( @NonNull final String iface, final int transportType, final int expectedLegacyType) throws Exception { createInterfaceUndergoingProvisioning(iface, transportType); - mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); - mLooper.dispatchAll(); + triggerOnProvisioningSuccess(); // provisioning succeeded, verify that the network agent is created, registered, marked // as connected and legacy type are correctly set. verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), argThat(x -> x.getLegacyType() == expectedLegacyType), any(), any()); - verify(mNetworkAgent).register(); - verify(mNetworkAgent).markConnected(); + verifyNetworkAgentRegistersAndConnects(); clearInvocations(mDeps); clearInvocations(mNetworkAgent); } @@ -228,8 +243,7 @@ public class EthernetNetworkFactoryTest { verify(mNetworkAgent, never()).register(); mNetFactory.releaseNetworkFor(createDefaultRequest()); - verify(mIpClient).shutdown(); - verify(mNetworkAgent).unregister(); + verifyStop(); clearInvocations(mIpClient); clearInvocations(mNetworkAgent); @@ -237,7 +251,7 @@ public class EthernetNetworkFactoryTest { @Test public void testAcceptRequest() throws Exception { - createInterfaceUndergoingProvisioning("eth0"); + createInterfaceUndergoingProvisioning(TEST_IFACE); assertTrue(mNetFactory.acceptRequest(createDefaultRequest())); NetworkRequest wifiRequest = createDefaultRequestBuilder() @@ -248,27 +262,23 @@ public class EthernetNetworkFactoryTest { @Test public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception { - String iface = "eth0"; - createInterfaceUndergoingProvisioning(iface); + createInterfaceUndergoingProvisioning(TEST_IFACE); // verify that the IpClient gets shut down when interface state changes to down. - assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); + assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); verify(mIpClient).shutdown(); } @Test public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception { - String iface = "eth0"; - createAndVerifyProvisionedInterface(iface); - assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); - verify(mIpClient).shutdown(); - verify(mNetworkAgent).unregister(); + createAndVerifyProvisionedInterface(TEST_IFACE); + assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + verifyStop(); } @Test public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception { - String iface = "eth0"; - createUnprovisionedInterface(iface); - assertTrue(mNetFactory.updateInterfaceLinkState(iface, false)); + createUnprovisionedInterface(TEST_IFACE); + assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); // There should not be an active IPClient or NetworkAgent. verify(mDeps, never()).makeIpClient(any(), any(), any()); verify(mDeps, never()) @@ -284,75 +294,64 @@ public class EthernetNetworkFactoryTest { @Test public void testNeedNetworkForOnProvisionedInterface() throws Exception { - createAndVerifyProvisionedInterface("eth0"); + createAndVerifyProvisionedInterface(TEST_IFACE); mNetFactory.needNetworkFor(createDefaultRequest()); verify(mIpClient, never()).startProvisioning(any()); } @Test public void testNeedNetworkForOnUnprovisionedInterface() throws Exception { - createUnprovisionedInterface("eth0"); + createUnprovisionedInterface(TEST_IFACE); mNetFactory.needNetworkFor(createDefaultRequest()); verify(mIpClient).startProvisioning(any()); - mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); - mLooper.dispatchAll(); - verify(mNetworkAgent).register(); - verify(mNetworkAgent).markConnected(); + triggerOnProvisioningSuccess(); + verifyNetworkAgentRegistersAndConnects(); } @Test public void testNeedNetworkForOnInterfaceUndergoingProvisioning() throws Exception { - createInterfaceUndergoingProvisioning("eth0"); + createInterfaceUndergoingProvisioning(TEST_IFACE); mNetFactory.needNetworkFor(createDefaultRequest()); verify(mIpClient, never()).startProvisioning(any()); - mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); - mLooper.dispatchAll(); - verify(mNetworkAgent).register(); - verify(mNetworkAgent).markConnected(); + triggerOnProvisioningSuccess(); + verifyNetworkAgentRegistersAndConnects(); } @Test public void testProvisioningLoss() throws Exception { - String iface = "eth0"; - when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams); - createAndVerifyProvisionedInterface(iface); + when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); + createAndVerifyProvisionedInterface(TEST_IFACE); - mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); - mLooper.dispatchAll(); - verify(mIpClient).shutdown(); - verify(mNetworkAgent).unregister(); + triggerOnProvisioningFailure(); + verifyStop(); // provisioning loss should trigger a retry, since the interface is still there verify(mIpClient).startProvisioning(any()); } @Test public void testProvisioningLossForDisappearedInterface() throws Exception { - String iface = "eth0"; // mocked method returns null by default, but just to be explicit in the test: - when(mDeps.getNetworkInterfaceByName(eq(iface))).thenReturn(null); + when(mDeps.getNetworkInterfaceByName(eq(TEST_IFACE))).thenReturn(null); - createAndVerifyProvisionedInterface(iface); - mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); - mLooper.dispatchAll(); - verify(mIpClient).shutdown(); - verify(mNetworkAgent).unregister(); + createAndVerifyProvisionedInterface(TEST_IFACE); + triggerOnProvisioningFailure(); + verifyStop(); // the interface disappeared and getNetworkInterfaceByName returns null, we should not retry verify(mIpClient, never()).startProvisioning(any()); } @Test public void testIpClientIsNotStartedWhenLinkIsDown() throws Exception { - String iface = "eth0"; - createUnprovisionedInterface(iface); - mNetFactory.updateInterfaceLinkState(iface, false); + createUnprovisionedInterface(TEST_IFACE); + mNetFactory.updateInterfaceLinkState(TEST_IFACE, false); mNetFactory.needNetworkFor(createDefaultRequest()); NetworkRequest specificNetRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .setNetworkSpecifier(new EthernetNetworkSpecifier(iface)) + .setNetworkSpecifier(new EthernetNetworkSpecifier(TEST_IFACE)) .build(); mNetFactory.needNetworkFor(specificNetRequest); @@ -363,7 +362,7 @@ public class EthernetNetworkFactoryTest { @Test public void testLinkPropertiesChanged() throws Exception { - createAndVerifyProvisionedInterface("eth0"); + createAndVerifyProvisionedInterface(TEST_IFACE); LinkProperties lp = new LinkProperties(); mIpClientCallbacks.onLinkPropertiesChange(lp); @@ -373,30 +372,26 @@ public class EthernetNetworkFactoryTest { @Test public void testNetworkUnwanted() throws Exception { - createAndVerifyProvisionedInterface("eth0"); + createAndVerifyProvisionedInterface(TEST_IFACE); mNetworkAgent.getCallbacks().onNetworkUnwanted(); mLooper.dispatchAll(); - verify(mIpClient).shutdown(); - verify(mNetworkAgent).unregister(); + verifyStop(); } @Test public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception { - String iface = "eth0"; // ensures provisioning is restarted after provisioning loss - when(mDeps.getNetworkInterfaceByName(iface)).thenReturn(mInterfaceParams); - createAndVerifyProvisionedInterface(iface); + when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); + createAndVerifyProvisionedInterface(TEST_IFACE); EthernetNetworkAgent.Callbacks oldCbs = mNetworkAgent.getCallbacks(); // replace network agent in EthernetNetworkFactory // Loss of provisioning will restart the ip client and network agent. - mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); - mLooper.dispatchAll(); + triggerOnProvisioningFailure(); verify(mDeps).makeIpClient(any(), any(), any()); - mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); - mLooper.dispatchAll(); + triggerOnProvisioningSuccess(); verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); // verify that unwanted is ignored @@ -409,45 +404,47 @@ public class EthernetNetworkFactoryTest { @Test public void testTransportOverrideIsCorrectlySet() throws Exception { - final String iface = "eth0"; // createProvisionedInterface() has verifications in place for transport override // functionality which for EthernetNetworkFactory is network score and legacy type mappings. - createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_ETHERNET, + createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_ETHERNET, ConnectivityManager.TYPE_ETHERNET); - mNetFactory.removeInterface(iface); - createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_BLUETOOTH, + createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_BLUETOOTH, ConnectivityManager.TYPE_BLUETOOTH); - mNetFactory.removeInterface(iface); - createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_WIFI, + createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_WIFI, ConnectivityManager.TYPE_WIFI); - mNetFactory.removeInterface(iface); - createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_CELLULAR, + createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_CELLULAR, ConnectivityManager.TYPE_MOBILE); - mNetFactory.removeInterface(iface); - createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_LOWPAN, + createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_LOWPAN, ConnectivityManager.TYPE_NONE); - mNetFactory.removeInterface(iface); - createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_WIFI_AWARE, + createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_WIFI_AWARE, ConnectivityManager.TYPE_NONE); - mNetFactory.removeInterface(iface); - createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_TEST, + createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_TEST, ConnectivityManager.TYPE_NONE); - mNetFactory.removeInterface(iface); } @Test public void testReachabilityLoss() throws Exception { - String iface = "eth0"; - createAndVerifyProvisionedInterface(iface); + createAndVerifyProvisionedInterface(TEST_IFACE); - mIpClientCallbacks.onReachabilityLost("ReachabilityLost"); - mLooper.dispatchAll(); + triggerOnReachabilityLost(); // Reachability loss should trigger a stop and start, since the interface is still there - verify(mIpClient).shutdown(); - verify(mNetworkAgent).unregister(); + verifyStop(); + verifyStart(); + } + private void verifyStart() throws Exception { verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); verify(mIpClient).startProvisioning(any()); } + + private void verifyStop() throws Exception { + verify(mIpClient).shutdown(); + verify(mNetworkAgent).unregister(); + } + + private void verifyNetworkAgentRegistersAndConnects() { + verify(mNetworkAgent).register(); + verify(mNetworkAgent).markConnected(); + } } From d8118aec3fb453f27283ea624205bf42af9c9815 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Sun, 2 Jan 2022 19:53:39 -0800 Subject: [PATCH 743/881] Replacing IIpClient with Manager in ethNetFactory Replacing IIpClient with IpClientManager to reduce code duplication, increase readability and maintainability as well as making EthernetNetworkFactory easier to unit test. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I283653171c0cc47ad94a67d6dbd65b924cdf1ada --- .../ethernet/EthernetNetworkFactory.java | 59 +++++++------------ .../ethernet/EthernetNetworkFactoryTest.java | 16 ++--- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 53928f7519..d7800c027a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -33,6 +33,7 @@ import android.net.NetworkRequest; import android.net.NetworkSpecifier; import android.net.ip.IIpClient; import android.net.ip.IpClientCallbacks; +import android.net.ip.IpClientManager; import android.net.ip.IpClientUtil; import android.net.shared.ProvisioningConfiguration; import android.os.ConditionVariable; @@ -76,6 +77,10 @@ public class EthernetNetworkFactory extends NetworkFactory { IpClientUtil.makeIpClient(context, iface, callbacks); } + public IpClientManager makeIpClientManager(@NonNull final IIpClient ipClient) { + return new IpClientManager(ipClient, TAG); + } + public EthernetNetworkAgent makeEthernetNetworkAgent(Context context, Looper looper, NetworkCapabilities nc, LinkProperties lp, NetworkAgentConfig config, NetworkProvider provider, EthernetNetworkAgent.Callbacks cb) { @@ -283,7 +288,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private boolean mLinkUp; private LinkProperties mLinkProperties = new LinkProperties(); - private volatile @Nullable IIpClient mIpClient; + private volatile @Nullable IpClientManager mIpClient; private @Nullable IpClientCallbacksImpl mIpClientCallback; private @Nullable EthernetNetworkAgent mNetworkAgent; private @Nullable IpConfiguration mIpConfig; @@ -317,7 +322,7 @@ public class EthernetNetworkFactory extends NetworkFactory { @Override public void onIpClientCreated(IIpClient ipClient) { - mIpClient = ipClient; + mIpClient = mDeps.makeIpClientManager(ipClient); mIpClientStartCv.open(); } @@ -356,14 +361,6 @@ public class EthernetNetworkFactory extends NetworkFactory { } } - private static void shutdownIpClient(IIpClient ipClient) { - try { - ipClient.shutdown(); - } catch (RemoteException e) { - Log.e(TAG, "Error stopping IpClient", e); - } - } - NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, @NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory, Dependencies deps) { @@ -509,7 +506,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void stop() { // Invalidate all previous start requests if (mIpClient != null) { - shutdownIpClient(mIpClient); + mIpClient.shutdown(); mIpClientCallback.awaitIpClientShutdown(); mIpClient = null; } @@ -522,41 +519,30 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkProperties.clear(); } - private static void provisionIpClient(IIpClient ipClient, IpConfiguration config, - String tcpBufferSizes) { + private static void provisionIpClient(@NonNull final IpClientManager ipClient, + @NonNull final IpConfiguration config, @NonNull final String tcpBufferSizes) { if (config.getProxySettings() == ProxySettings.STATIC || config.getProxySettings() == ProxySettings.PAC) { - try { - ipClient.setHttpProxy(config.getHttpProxy()); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } + ipClient.setHttpProxy(config.getHttpProxy()); } if (!TextUtils.isEmpty(tcpBufferSizes)) { - try { - ipClient.setTcpBufferSizes(tcpBufferSizes); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } + ipClient.setTcpBufferSizes(tcpBufferSizes); } - final ProvisioningConfiguration provisioningConfiguration; + ipClient.startProvisioning(createProvisioningConfiguration(config)); + } + + private static ProvisioningConfiguration createProvisioningConfiguration( + @NonNull final IpConfiguration config) { if (config.getIpAssignment() == IpAssignment.STATIC) { - provisioningConfiguration = new ProvisioningConfiguration.Builder() + return new ProvisioningConfiguration.Builder() .withStaticConfiguration(config.getStaticIpConfiguration()) .build(); - } else { - provisioningConfiguration = new ProvisioningConfiguration.Builder() + } + return new ProvisioningConfiguration.Builder() .withProvisioningTimeoutMs(0) .build(); - } - - try { - ipClient.startProvisioning(provisioningConfiguration.toStableParcelable()); - } catch (RemoteException e) { - e.rethrowFromSystemServer(); - } } void restart(){ @@ -589,10 +575,7 @@ public class EthernetNetworkFactory extends NetworkFactory { NetworkInterfaceState ifaceState = mTrackingInterfaces.get(iface); pw.println(iface + ":" + ifaceState); pw.increaseIndent(); - final IIpClient ipClient = ifaceState.mIpClient; - if (ipClient != null) { - IpClientUtil.dumpIpClient(ipClient, fd, pw, args); - } else { + if (null == ifaceState.mIpClient) { pw.println("IpClient is null"); } pw.decreaseIndent(); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 08a70a6f40..990ee5fee7 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -42,8 +42,8 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkProvider; import android.net.NetworkRequest; -import android.net.ip.IIpClient; import android.net.ip.IpClientCallbacks; +import android.net.ip.IpClientManager; import android.os.Handler; import android.os.Looper; import android.os.test.TestLooper; @@ -72,7 +72,7 @@ public class EthernetNetworkFactoryTest { @Mock private Context mContext; @Mock private Resources mResources; @Mock private EthernetNetworkFactory.Dependencies mDeps; - @Mock private IIpClient mIpClient; + @Mock private IpClientManager mIpClient; @Mock private EthernetNetworkAgent mNetworkAgent; @Mock private InterfaceParams mInterfaceParams; @@ -113,7 +113,7 @@ public class EthernetNetworkFactoryTest { assertNull("An IpClient has already been created.", mIpClientCallbacks); mIpClientCallbacks = inv.getArgument(2); - mIpClientCallbacks.onIpClientCreated(mIpClient); + mIpClientCallbacks.onIpClientCreated(null); mLooper.dispatchAll(); return null; }).when(mDeps).makeIpClient(any(Context.class), anyString(), any()); @@ -124,6 +124,8 @@ public class EthernetNetworkFactoryTest { mIpClientCallbacks = null; return null; }).when(mIpClient).shutdown(); + + when(mDeps.makeIpClientManager(any())).thenReturn(mIpClient); } private void triggerOnProvisioningSuccess() { @@ -185,13 +187,13 @@ public class EthernetNetworkFactoryTest { // creates an interface with provisioning in progress (since updating the interface link state // automatically starts the provisioning process) - private void createInterfaceUndergoingProvisioning(String iface) throws Exception { + private void createInterfaceUndergoingProvisioning(String iface) { // Default to the ethernet transport type. createInterfaceUndergoingProvisioning(iface, NetworkCapabilities.TRANSPORT_ETHERNET); } private void createInterfaceUndergoingProvisioning( - @NonNull final String iface, final int transportType) throws Exception { + @NonNull final String iface, final int transportType) { mNetFactory.addInterface(iface, iface, createInterfaceCapsBuilder(transportType).build(), createDefaultIpConfig()); assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); @@ -433,12 +435,12 @@ public class EthernetNetworkFactoryTest { verifyStart(); } - private void verifyStart() throws Exception { + private void verifyStart() { verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); verify(mIpClient).startProvisioning(any()); } - private void verifyStop() throws Exception { + private void verifyStop() { verify(mIpClient).shutdown(); verify(mNetworkAgent).unregister(); } From 0dbd0c8d26252c44b5a30c3d8c76620b6326e96e Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 5 Jan 2022 08:09:16 +0000 Subject: [PATCH 744/881] [MS40.1] Remove Clock dependencies from NetworkStatsService This includes: 1. Re-implement the BestClock in the static library. 2. Expose SystemClock#currentNetworkTimeClock as public Api Test: TH Bug: 204830222 CTS-Coverage-Bug: 213393821 Exempt-From-Owner-Approval: 1. Owner approved the change with explicitly granted submission after adderessing the straight-forward comment. 2. Owner is OOO for 3 months. Change-Id: I08c0162a7101cc6184f3eca3d4a59211183fb843 --- service-t/src/com/android/server/net/NetworkStatsService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index ef84ce02e2..5584293b7d 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -113,7 +113,6 @@ import android.net.Uri; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; -import android.os.BestClock; import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; @@ -149,6 +148,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FileRotator; +import com.android.net.module.util.BestClock; import com.android.net.module.util.BinderUtils; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkStatsUtils; From 5bef63756c51e6232ceee81f2b40a200ef16aa69 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 3 Jan 2022 14:05:45 +0000 Subject: [PATCH 745/881] [MS34.1] Replace TelephonyManager#getSubscriberId(subId) with public API Test: atest com.android.server.net.NetworkStatsSubscriptionsMonitorTest Bug: 204830222 Change-Id: I57aa4470aea1715217fa7d74f2c9067b096d1bae --- .../android/server/net/NetworkStatsSubscriptionsMonitor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 93d0ae7da0..9bb7bb8078 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -101,7 +101,8 @@ public class NetworkStatsSubscriptionsMonitor extends // with empty IMSI. So filter the subs w/o a valid IMSI to prevent such registration. final List> filteredNewSubs = new ArrayList<>(); for (final int subId : newSubs) { - final String subscriberId = mTeleManager.getSubscriberId(subId); + final String subscriberId = + mTeleManager.createForSubscriptionId(subId).getSubscriberId(); if (!TextUtils.isEmpty(subscriberId)) { filteredNewSubs.add(new Pair(subId, subscriberId)); } From e7c835b3ad96eab1a03bec2da4a38664fc8e1e61 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 4 Jan 2022 10:23:47 +0000 Subject: [PATCH 746/881] [MS09] Expose NetworkTemplate APIs which are needed by NetworkPolicy This change also remove getWifiNetworkKey which should not be exposed as system API. Test: atest NetworkTemplateTest Bug: 204830222 Change-Id: I924f62025a8672167f778ff790cd208c74eed878 --- framework-t/src/android/net/NetworkStats.java | 23 ++++--------------- .../src/android/net/NetworkTemplate.java | 23 ++++++++----------- 2 files changed, 14 insertions(+), 32 deletions(-) diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java index 181a594cbc..b00fea4de2 100644 --- a/framework-t/src/android/net/NetworkStats.java +++ b/framework-t/src/android/net/NetworkStats.java @@ -83,10 +83,7 @@ public final class NetworkStats implements Parcelable { */ // TODO: Rename TAG_ALL to TAG_ANY. public static final int TAG_ALL = -1; - /** - * {@link #set} value for all sets combined, not including debug sets. - * @hide - */ + /** {@link #set} value for all sets combined, not including debug sets. */ public static final int SET_ALL = -1; /** {@link #set} value where background data is accounted. */ public static final int SET_DEFAULT = 0; @@ -114,9 +111,6 @@ public final class NetworkStats implements Parcelable { SET_ALL, SET_DEFAULT, SET_FOREGROUND, - SET_DEBUG_START, - SET_DBG_VPN_IN, - SET_DBG_VPN_OUT }) public @interface State { } @@ -131,10 +125,7 @@ public final class NetworkStats implements Parcelable { // TODO: Rename TAG_NONE to TAG_ALL. public static final int TAG_NONE = 0; - /** - * {@link #metered} value to account for all metered states. - * @hide - */ + /** {@link #metered} value to account for all metered states. */ public static final int METERED_ALL = -1; /** {@link #metered} value where native, unmetered data is accounted. */ public static final int METERED_NO = 0; @@ -152,10 +143,7 @@ public final class NetworkStats implements Parcelable { } - /** - * {@link #roaming} value to account for all roaming states. - * @hide - */ + /** {@link #roaming} value to account for all roaming states. */ public static final int ROAMING_ALL = -1; /** {@link #roaming} value where native, non-roaming data is accounted. */ public static final int ROAMING_NO = 0; @@ -172,10 +160,7 @@ public final class NetworkStats implements Parcelable { public @interface Roaming { } - /** - * {@link #onDefaultNetwork} value to account for all default network states. - * @hide - */ + /** {@link #onDefaultNetwork} value to account for all default network states. */ public static final int DEFAULT_NETWORK_ALL = -1; /** {@link #onDefaultNetwork} value to account for usage while not the default network. */ public static final int DEFAULT_NETWORK_NO = 0; diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 659ad06039..e9084b0196 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -16,6 +16,7 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.ConnectivityManager.TYPE_BLUETOOTH; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; @@ -39,7 +40,9 @@ import static android.net.NetworkStats.ROAMING_YES; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; +import android.net.wifi.WifiInfo; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -70,7 +73,7 @@ import java.util.TreeSet; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) +@SystemApi(client = MODULE_LIBRARIES) public final class NetworkTemplate implements Parcelable { /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -572,6 +575,7 @@ public final class NetworkTemplate implements Parcelable { /** * Get subscriber Id of the template. + * @hide */ @Nullable @UnsupportedAppUsage @@ -588,26 +592,19 @@ public final class NetworkTemplate implements Parcelable { } /** - * Get Wifi Network Key of the template. See {@link WifiInfo#getCurrentNetworkKey()}. + * Get the set of Wifi Network Keys of the template. + * See {@link WifiInfo#getCurrentNetworkKey()}. */ - @Nullable - public String getWifiNetworkKey() { - return CollectionUtils.isEmpty(mMatchWifiNetworkKeys) ? null : mMatchWifiNetworkKeys[0]; - } - - /** - * Get set of Wifi Network Keys of the template. - */ - @Nullable + @NonNull public Set getWifiNetworkKeys() { return new ArraySet<>(Arrays.asList(mMatchWifiNetworkKeys)); } /** @hide */ - // TODO: Remove this and replace all callers with {@link #getWifiNetworkKey()}. + // TODO: Remove this and replace all callers with {@link #getWifiNetworkKeys()}. @Nullable public String getNetworkId() { - return getWifiNetworkKey(); + return getWifiNetworkKeys().isEmpty() ? null : getWifiNetworkKeys().iterator().next(); } /** From 1ea62cdab4e4c869bac4035640ff23ecf47e496a Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 3 Jan 2022 07:39:55 +0000 Subject: [PATCH 747/881] [MS32.1] Remove TetheringManager#ACTION_TETHER_STATE_CHANGED usage Replace intent receiver with callback listener. Test: atest com.android.server.net.NetworkStatsServiceTest Bug: 204830222 Change-Id: I585b2bb471b59cbca3cce1c01ce527dff87f42da --- .../server/net/NetworkStatsService.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 5584293b7d..ced2e22f14 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -42,7 +42,6 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; -import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.TrafficStats.UNSUPPORTED; @@ -107,6 +106,7 @@ import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; +import android.net.TetheringManager; import android.net.TrafficStats; import android.net.UnderlyingNetworkInfo; import android.net.Uri; @@ -531,8 +531,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // watch for tethering changes - final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED); - mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler); + final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class); + tetheringManager.registerTetheringEventCallback( + new HandlerExecutor(mHandler), mTetherListener); // listen for periodic polling events final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); @@ -588,7 +589,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private void shutdownLocked() { - mContext.unregisterReceiver(mTetherReceiver); + final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class); + tetheringManager.unregisterTetheringEventCallback(mTetherListener); mContext.unregisterReceiver(mPollReceiver); mContext.unregisterReceiver(mRemovedReceiver); mContext.unregisterReceiver(mUserReceiver); @@ -1152,14 +1154,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Receiver that watches for {@link Tethering} to claim interface pairs. + * Listener that watches for {@link TetheringManager} to claim interface pairs. */ - private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - performPoll(FLAG_PERSIST_NETWORK); - } - }; + private final TetheringManager.TetheringEventCallback mTetherListener = + new TetheringManager.TetheringEventCallback() { + @Override + public void onUpstreamChanged(@Nullable Network network) { + performPoll(FLAG_PERSIST_NETWORK); + } + }; private BroadcastReceiver mPollReceiver = new BroadcastReceiver() { @Override From 76b8f884287231b3a8e6839d19b42f074de9fe78 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 23 Dec 2021 10:47:05 +0800 Subject: [PATCH 748/881] Remove ParcelFileDescriptor hidden API usage from IpSecService IpSec service is going to be a part of Connectivity mainline module and ParcelFileDescriptor(FileDescriptor) is a hidden API that cannot be used by mainline module. Therefore, use ParcelFileDescriptor.dup(FileDescriptor) to get a ParcelFileDescriptor instead. Bug: 204153604 Test: FrameworksNetTests Change-Id: I0ccabdfc5060f4b635e9a7009a67fbd5d32002fd --- .../src/com/android/server/IpSecService.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java index d1e432e80f..179d9459fd 100644 --- a/service-t/src/com/android/server/IpSecService.java +++ b/service-t/src/com/android/server/IpSecService.java @@ -1236,37 +1236,53 @@ public class IpSecService extends IIpSecService.Stub { int callingUid = Binder.getCallingUid(); UserRecord userRecord = mUserResourceTracker.getUserRecord(callingUid); final int resourceId = mNextResourceId++; - FileDescriptor sockFd = null; + + ParcelFileDescriptor pFd = null; try { if (!userRecord.mSocketQuotaTracker.isAvailable()) { return new IpSecUdpEncapResponse(IpSecManager.Status.RESOURCE_UNAVAILABLE); } - sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - mUidFdTagger.tag(sockFd, callingUid); + FileDescriptor sockFd = null; + try { + sockFd = Os.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + pFd = ParcelFileDescriptor.dup(sockFd); + } finally { + IoUtils.closeQuietly(sockFd); + } + mUidFdTagger.tag(pFd.getFileDescriptor(), callingUid); // This code is common to both the unspecified and specified port cases Os.setsockoptInt( - sockFd, + pFd.getFileDescriptor(), OsConstants.IPPROTO_UDP, OsConstants.UDP_ENCAP, OsConstants.UDP_ENCAP_ESPINUDP); - mNetd.ipSecSetEncapSocketOwner(new ParcelFileDescriptor(sockFd), callingUid); + mNetd.ipSecSetEncapSocketOwner(pFd, callingUid); if (port != 0) { Log.v(TAG, "Binding to port " + port); - Os.bind(sockFd, INADDR_ANY, port); + Os.bind(pFd.getFileDescriptor(), INADDR_ANY, port); } else { - port = bindToRandomPort(sockFd); + port = bindToRandomPort(pFd.getFileDescriptor()); } userRecord.mEncapSocketRecords.put( resourceId, new RefcountedResource( - new EncapSocketRecord(resourceId, sockFd, port), binder)); - return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port, sockFd); + new EncapSocketRecord(resourceId, pFd.getFileDescriptor(), port), + binder)); + return new IpSecUdpEncapResponse(IpSecManager.Status.OK, resourceId, port, + pFd.getFileDescriptor()); } catch (IOException | ErrnoException e) { - IoUtils.closeQuietly(sockFd); + try { + if (pFd != null) { + pFd.close(); + } + } catch (IOException ex) { + // Nothing can be done at this point + Log.e(TAG, "Failed to close pFd."); + } } // If we make it to here, then something has gone wrong and we couldn't open a socket. // The only reasonable condition that would cause that is resource unavailable. From 19332960f6b560ca90d76a1e452550119e2e0620 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 27 Dec 2021 13:56:00 +0000 Subject: [PATCH 749/881] [MS22] Move NetworkManagementSocketTagger into the module This is heavily used by TrafficStats, and no other modules are using it. Hence it should be moved to the module as well. Test: TH Bug: 204830222 Change-Id: I7ea1ccb916e796c786c29d53e4ecf3970a8af6dd --- framework-t/Sources.bp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 0bda923f23..90bb76a87d 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -25,15 +25,21 @@ filegroup { name: "framework-connectivity-netstats-internal-sources", srcs: [ "src/android/app/usage/*.java", - "src/android/net/DataUsage*.*", - "src/android/net/INetworkStats*.*", - "src/android/net/NetworkIdentity*.java", + "src/android/net/DataUsageRequest.*", + "src/android/net/INetworkStatsService.aidl", + "src/android/net/INetworkStatsSession.aidl", + "src/android/net/NetworkIdentity.java", + "src/android/net/NetworkIdentitySet.java", "src/android/net/NetworkStateSnapshot.*", - "src/android/net/NetworkStats*.*", + "src/android/net/NetworkStats.*", + "src/android/net/NetworkStatsAccess.*", + "src/android/net/NetworkStatsCollection.*", + "src/android/net/NetworkStatsHistory.*", "src/android/net/NetworkTemplate.*", "src/android/net/TrafficStats.java", "src/android/net/UnderlyingNetworkInfo.*", "src/android/net/netstats/**/*.*", + "src/com/android/server/NetworkManagementSocketTagger.java", ], path: "src", visibility: [ From 30eb3cc54a93c44edc7895c49e02a9571176a432 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 5 Jan 2022 07:35:49 +0000 Subject: [PATCH 750/881] [MS39.1] Remove the looper from NetworkStatsSubscriptionMonitor OnSubscriptionsChangedListenerHandler(Looper looper) is hidden, there is no way to pass a looper to it in the test. This change partially revert aosp/1340040 to fix hidden API dependency. And will use a different approach to address this problem in later stages. Test: atest NetworkStatsSubscriptionMonitorTest Bug: 204830222 Bug: 213280079 Change-Id: I429be3578d599de9a5a3f78b02387c20744b37d3 --- .../src/com/android/server/net/NetworkStatsService.java | 7 +++---- .../server/net/NetworkStatsSubscriptionsMonitor.java | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index ced2e22f14..97281ed424 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -448,7 +448,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, - mHandler.getLooper(), new HandlerExecutor(mHandler), this); + new HandlerExecutor(mHandler), this); mContentResolver = mContext.getContentResolver(); mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, mNetworkStatsSubscriptionsMonitor); @@ -474,11 +474,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ @NonNull public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, - @NonNull Looper looper, @NonNull Executor executor, - @NonNull NetworkStatsService service) { + @NonNull Executor executor, @NonNull NetworkStatsService service) { // TODO: Update RatType passively in NSS, instead of querying into the monitor // when notifyNetworkStatus. - return new NetworkStatsSubscriptionsMonitor(context, looper, executor, + return new NetworkStatsSubscriptionsMonitor(context, executor, (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged()); } diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 9bb7bb8078..6df6de32da 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -21,7 +21,6 @@ import static android.net.NetworkTemplate.getCollapsedRatType; import android.annotation.NonNull; import android.content.Context; -import android.os.Looper; import android.telephony.Annotation; import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; @@ -79,9 +78,9 @@ public class NetworkStatsSubscriptionsMonitor extends @NonNull private final Executor mExecutor; - NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Looper looper, + NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor, @NonNull Delegate delegate) { - super(looper); + super(); mSubscriptionManager = (SubscriptionManager) context.getSystemService( Context.TELEPHONY_SUBSCRIPTION_SERVICE); mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); From 14a3baf2444378a9aa387cf389c6eb9885189399 Mon Sep 17 00:00:00 2001 From: lifr Date: Mon, 13 Dec 2021 16:15:51 +0800 Subject: [PATCH 751/881] [DU01]Remove INetworkManagementService from NetworkStatsService NetworkStatsService is using INetworkManagementService APIs, which cannot be accessed after moving into the mainline module. So, replace and remove those hidden API usages. Bug: 209738761 Test: atest NetworkStatsServiceTest Change-Id: I5740f6d8a54e9a06c6dbb93203cb4c954383c3c8 --- .../server/net/NetworkStatsService.java | 109 ++++++++++-------- 1 file changed, 64 insertions(+), 45 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index ced2e22f14..51e3f501b8 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -44,6 +44,7 @@ import static android.net.NetworkTemplate.buildTemplateMobileWildcard; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; +import static android.net.TrafficStats.UID_TETHERING; import static android.net.TrafficStats.UNSUPPORTED; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; @@ -70,7 +71,7 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport; -import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; +import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; @@ -89,7 +90,6 @@ import android.content.pm.PackageManager; import android.database.ContentObserver; import android.net.DataUsageRequest; import android.net.INetd; -import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.Network; @@ -106,6 +106,7 @@ import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TelephonyNetworkSpecifier; +import android.net.TetherStatsParcel; import android.net.TetheringManager; import android.net.TrafficStats; import android.net.UnderlyingNetworkInfo; @@ -120,12 +121,12 @@ import android.os.Handler; import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.IBinder; -import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.RemoteException; +import android.os.ServiceSpecificException; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; @@ -148,6 +149,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FileRotator; +import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.BestClock; import com.android.net.module.util.BinderUtils; import com.android.net.module.util.CollectionUtils; @@ -208,7 +210,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String TAG_NETSTATS_ERROR = "netstats_error"; private final Context mContext; - private final INetworkManagementService mNetworkManager; private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; private final Clock mClock; @@ -223,6 +224,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final ContentObserver mContentObserver; private final ContentResolver mContentResolver; + protected INetd mNetd; + private final AlertObserver mAlertObserver = new AlertObserver(); + @VisibleForTesting public static final String ACTION_NETWORK_STATS_POLL = "com.android.server.action.NETWORK_STATS_POLL"; @@ -405,15 +409,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public static NetworkStatsService create(Context context, - INetworkManagementService networkManager) { + /** Creates a new NetworkStatsService */ + public static NetworkStatsService create(Context context) { AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); final INetd netd = INetd.Stub.asInterface( (IBinder) context.getSystemService(Context.NETD_SERVICE)); - final NetworkStatsService service = new NetworkStatsService(context, networkManager, + final NetworkStatsService service = new NetworkStatsService(context, + INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)), alarmManager, wakeLock, getDefaultClock(), new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), @@ -426,14 +431,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // This must not be called outside of tests, even within the same package, as this constructor // does not register the local service. Use the create() helper above. @VisibleForTesting - NetworkStatsService(Context context, INetworkManagementService networkManager, - AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, - NetworkStatsSettings settings, NetworkStatsFactory factory, - NetworkStatsObservers statsObservers, File systemDir, File baseDir, - @NonNull Dependencies deps) { + NetworkStatsService(Context context, INetd netd, AlarmManager alarmManager, + PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings, + NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, + File baseDir, @NonNull Dependencies deps) { mContext = Objects.requireNonNull(context, "missing Context"); - mNetworkManager = Objects.requireNonNull(networkManager, - "missing INetworkManagementService"); + mNetd = Objects.requireNonNull(netd, "missing Netd"); mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager"); mClock = Objects.requireNonNull(clock, "missing Clock"); mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings"); @@ -507,6 +510,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { new NetworkStatsManagerInternalImpl()); } + /** + * Observer that watches for {@link INetdUnsolicitedEventListener} alerts. + */ + @VisibleForTesting + public class AlertObserver extends BaseNetdUnsolicitedEventListener { + @Override + public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) { + PermissionUtils.enforceNetworkStackPermission(mContext); + + if (LIMIT_GLOBAL_ALERT.equals(alertName)) { + // kick off background poll to collect network stats unless there is already + // such a call pending; UID stats are handled during normal polling interval. + if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) { + mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT, + mSettings.getPollDelay()); + } + } + } + } + public void systemReady() { synchronized (mStatsLock) { mSystemReady = true; @@ -552,9 +575,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.registerReceiver(mShutdownReceiver, shutdownFilter); try { - mNetworkManager.registerObserver(mAlertObserver); - } catch (RemoteException e) { - // ignored; service lives in system_server + mNetd.registerUnsolicitedEventListener(mAlertObserver); + } catch (RemoteException | ServiceSpecificException e) { + Log.wtf(TAG, "Error registering event listener :", e); } // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}. @@ -642,13 +665,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * Register for a global alert that is delivered through {@link INetworkManagementEventObserver} + * Register for a global alert that is delivered through {@link AlertObserver} * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has * been transferred. */ private void registerGlobalAlert() { try { - mNetworkManager.setGlobalAlert(mGlobalAlertBytes); + mNetd.bandwidthSetGlobalAlert(mGlobalAlertBytes); } catch (IllegalStateException e) { Log.w(TAG, "problem registering for global alert: " + e); } catch (RemoteException e) { @@ -1226,26 +1249,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; - /** - * Observer that watches for {@link INetworkManagementService} alerts. - */ - private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() { - @Override - public void limitReached(String limitName, String iface) { - // only someone like NMS should be calling us - PermissionUtils.enforceNetworkStackPermission(mContext); - - if (LIMIT_GLOBAL_ALERT.equals(limitName)) { - // kick off background poll to collect network stats unless there is already - // such a call pending; UID stats are handled during normal polling interval. - if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) { - mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT, - mSettings.getPollDelay()); - } - } - } - }; - /** * Handle collapsed RAT type changed event. */ @@ -1957,13 +1960,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded // tethering stats. - private NetworkStats getNetworkStatsTethering(int how) throws RemoteException { + private @NonNull NetworkStats getNetworkStatsTethering(int how) throws RemoteException { + // We only need to return per-UID stats. Per-device stats are already counted by + // interface counters. + if (how != STATS_PER_UID) { + return new NetworkStats(SystemClock.elapsedRealtime(), 0); + } + + final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); try { - return mNetworkManager.getNetworkStatsTethering(how); + final TetherStatsParcel[] tetherStatsParcels = mNetd.tetherGetStats(); + for (TetherStatsParcel tetherStats : tetherStatsParcels) { + try { + stats.combineValues(new NetworkStats.Entry(tetherStats.iface, UID_TETHERING, + SET_DEFAULT, TAG_NONE, tetherStats.rxBytes, tetherStats.rxPackets, + tetherStats.txBytes, tetherStats.txPackets, 0L)); + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalStateException("invalid tethering stats " + e); + } + } } catch (IllegalStateException e) { Log.wtf(TAG, "problem reading network stats", e); - return new NetworkStats(0L, 10); } + return stats; } // TODO: It is copied from ConnectivityService, consider refactor these check permission @@ -2045,7 +2064,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull final INetworkStatsProvider mProvider; @NonNull private final Semaphore mSemaphore; - @NonNull final INetworkManagementEventObserver mAlertObserver; + @NonNull final AlertObserver mAlertObserver; @NonNull final CopyOnWriteArrayList mStatsProviderCbList; @NonNull private final Object mProviderStatsLock = new Object(); @@ -2059,7 +2078,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStatsProviderCallbackImpl( @NonNull String tag, @NonNull INetworkStatsProvider provider, @NonNull Semaphore semaphore, - @NonNull INetworkManagementEventObserver alertObserver, + @NonNull AlertObserver alertObserver, @NonNull CopyOnWriteArrayList cbList) throws RemoteException { mTag = tag; @@ -2107,7 +2126,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // This binder object can only have been obtained by a process that holds // NETWORK_STATS_PROVIDER. Thus, no additional permission check is required. BinderUtils.withCleanCallingIdentity(() -> - mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */)); + mAlertObserver.onQuotaLimitReached(LIMIT_GLOBAL_ALERT, null /* unused */)); } @Override From e75b506df26b66362296697ca88a7fd9c4a1db19 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Sat, 8 Jan 2022 17:16:24 -0800 Subject: [PATCH 752/881] Making NetworkCapabilities @NonNull Updating InternalNetworkUpdateRequest to require non-null network capabilities. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I660d039166451c22ffe5b5e603c649a43b71ebf1 --- .../android/net/InternalNetworkUpdateRequest.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/core/java/android/net/InternalNetworkUpdateRequest.java index 6f093835fb..f42c4b7c42 100644 --- a/core/java/android/net/InternalNetworkUpdateRequest.java +++ b/core/java/android/net/InternalNetworkUpdateRequest.java @@ -17,7 +17,6 @@ package android.net; import android.annotation.NonNull; -import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; @@ -27,7 +26,7 @@ import java.util.Objects; public final class InternalNetworkUpdateRequest implements Parcelable { @NonNull private final StaticIpConfiguration mIpConfig; - @Nullable + @NonNull private final NetworkCapabilities mNetworkCapabilities; @NonNull @@ -37,20 +36,16 @@ public final class InternalNetworkUpdateRequest implements Parcelable { @NonNull public NetworkCapabilities getNetworkCapabilities() { - return mNetworkCapabilities == null - ? null : new NetworkCapabilities(mNetworkCapabilities); + return new NetworkCapabilities(mNetworkCapabilities); } /** @hide */ public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, - @Nullable final NetworkCapabilities networkCapabilities) { + @NonNull final NetworkCapabilities networkCapabilities) { Objects.requireNonNull(ipConfig); + Objects.requireNonNull(networkCapabilities); mIpConfig = new StaticIpConfiguration(ipConfig); - if (null == networkCapabilities) { - mNetworkCapabilities = null; - } else { - mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); - } + mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); } private InternalNetworkUpdateRequest(@NonNull final Parcel source) { From c44e042f070e90f7c527a1e7d0759d0be7297989 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 6 Jan 2022 01:12:47 +0000 Subject: [PATCH 753/881] [MS42.1] Replace PhoneStateListener with DisplayInfoListener Several methods and constants are hidden in PhoneStateListener and ServiceState to track Radio Access Technology(RAT) types. Replace them with public API instead. Test: atest NetworkStatsSubscriptionsMonitorTest Fix: 213021103 Change-Id: I588398da7f2b031910a8350a7d84405ff101232d --- .../net/NetworkStatsSubscriptionsMonitor.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 6df6de32da..4875f1cf5a 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -18,14 +18,16 @@ package com.android.server.net; import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; import static android.net.NetworkTemplate.getCollapsedRatType; +import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED; +import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; +import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; import android.annotation.NonNull; import android.content.Context; import android.telephony.Annotation; -import android.telephony.NetworkRegistrationInfo; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.SubscriptionManager; +import android.telephony.TelephonyCallback; +import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -63,7 +65,7 @@ public class NetworkStatsSubscriptionsMonitor extends private final Delegate mDelegate; /** - * Receivers that watches for {@link ServiceState} changes for each subscription, to + * Receivers that watches for {@link TelephonyDisplayInfo} changes for each subscription, to * monitor the transitioning between Radio Access Technology(RAT) types for each sub. */ @NonNull @@ -115,13 +117,12 @@ public class NetworkStatsSubscriptionsMonitor extends continue; } - final RatTypeListener listener = - new RatTypeListener(mExecutor, this, sub.first, sub.second); + final RatTypeListener listener = new RatTypeListener(this, sub.first, sub.second); mRatListeners.add(listener); // Register listener to the telephony manager that associated with specific sub. mTeleManager.createForSubscriptionId(sub.first) - .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + .registerTelephonyCallback(mExecutor, listener); Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first); } @@ -175,7 +176,7 @@ public class NetworkStatsSubscriptionsMonitor extends private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { mTeleManager.createForSubscriptionId(listener.mSubId) - .listen(listener, PhoneStateListener.LISTEN_NONE); + .unregisterTelephonyCallback(listener); Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId); mRatListeners.remove(listener); @@ -185,7 +186,8 @@ public class NetworkStatsSubscriptionsMonitor extends listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN); } - static class RatTypeListener extends PhoneStateListener { + static class RatTypeListener extends TelephonyCallback + implements TelephonyCallback.DisplayInfoListener { // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}. @NonNull private final int mSubId; @@ -199,29 +201,27 @@ public class NetworkStatsSubscriptionsMonitor extends @NonNull private final NetworkStatsSubscriptionsMonitor mMonitor; - RatTypeListener(@NonNull Executor executor, - @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, + RatTypeListener(@NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, @NonNull String subscriberId) { - super(executor); mSubId = subId; mSubscriberId = subscriberId; mMonitor = monitor; } @Override - public void onServiceStateChanged(@NonNull ServiceState ss) { + public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) { // In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony // would report RAT = 5G_NR. // However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and // network allocates a secondary 5G cell so telephony reports RAT = LTE along with // NR state as connected. In such case, attributes the data usage to NR. // See b/160727498. - final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE - || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) - && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED; + final boolean is5GNsa = displayInfo.getNetworkType() == NETWORK_TYPE_LTE + && (displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_NSA + || displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_ADVANCED); final int networkType = - (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType()); + (is5GNsa ? NETWORK_TYPE_5G_NSA : displayInfo.getNetworkType()); final int collapsedRatType = getCollapsedRatType(networkType); if (collapsedRatType == mLastCollapsedRatType) return; From 947b8f0a0873d6b50daf762a82462e4d1767bb46 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Wed, 29 Dec 2021 16:52:34 -0800 Subject: [PATCH 754/881] Implementation of Eth Service updateConfiguration EthernetServiceImpl#updateConfiguration API implementation to allow for dynamically updating the network capability or ip configuration of an ethernet based interface. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: Idd3b7875a24643d245d0f4bb6f2f4c459898116e --- .../ethernet/EthernetNetworkFactory.java | 182 ++++++++++++------ .../server/ethernet/EthernetService.java | 17 +- .../server/ethernet/EthernetServiceImpl.java | 3 + .../server/ethernet/EthernetTracker.java | 61 +++--- tests/ethernet/Android.bp | 2 + .../ethernet/EthernetNetworkFactoryTest.java | 111 ++++++++++- .../ethernet/EthernetServiceImplTest.java | 50 ++--- .../server/ethernet/EthernetTrackerTest.java | 69 ++++++- 8 files changed, 378 insertions(+), 117 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index d7800c027a..b556f6c949 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.content.Context; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; +import android.net.IInternalNetworkManagementListener; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -98,14 +99,13 @@ public class EthernetNetworkFactory extends NetworkFactory { } } - public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) { - this(handler, context, filter, new Dependencies()); + public EthernetNetworkFactory(Handler handler, Context context) { + this(handler, context, new Dependencies()); } @VisibleForTesting - EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter, - Dependencies deps) { - super(handler.getLooper(), context, NETWORK_TYPE, filter); + EthernetNetworkFactory(Handler handler, Context context, Dependencies deps) { + super(handler.getLooper(), context, NETWORK_TYPE, createDefaultNetworkCapabilities()); mHandler = handler; mContext = context; @@ -166,8 +166,9 @@ public class EthernetNetworkFactory extends NetworkFactory { .toArray(String[]::new); } - void addInterface(String ifaceName, String hwAddress, NetworkCapabilities capabilities, - IpConfiguration ipConfiguration) { + void addInterface(@NonNull final String ifaceName, @NonNull final String hwAddress, + @NonNull final IpConfiguration ipConfig, + @NonNull final NetworkCapabilities capabilities) { if (mTrackingInterfaces.containsKey(ifaceName)) { Log.e(TAG, "Interface with name " + ifaceName + " already exists."); return; @@ -177,14 +178,48 @@ public class EthernetNetworkFactory extends NetworkFactory { Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities); } - NetworkInterfaceState iface = new NetworkInterfaceState( - ifaceName, hwAddress, mHandler, mContext, capabilities, this, mDeps); - iface.setIpConfig(ipConfiguration); + final NetworkInterfaceState iface = new NetworkInterfaceState( + ifaceName, hwAddress, mHandler, mContext, ipConfig, capabilities, this, mDeps); mTrackingInterfaces.put(ifaceName, iface); - updateCapabilityFilter(); } + /** + * Update a network's configuration and restart it if necessary. + * + * @param ifaceName the interface name of the network to be updated. + * @param ipConfig the desired {@link IpConfiguration} for the given network. + * @param capabilities the desired {@link NetworkCapabilities} for the given network. If + * {@code null} is passed, then the network's current + * {@link NetworkCapabilities} will be used in support of existing APIs as + * the public API does not allow this. + * @param listener an optional {@link IInternalNetworkManagementListener} to notify callers of + * completion. + */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + protected void updateInterface(@NonNull final String ifaceName, + @NonNull final IpConfiguration ipConfig, + @Nullable final NetworkCapabilities capabilities, + @Nullable final IInternalNetworkManagementListener listener) { + enforceInterfaceIsTracked(ifaceName); + final NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName); + // TODO: The listener will have issues if called in quick succession for the same interface + // before the IP layer restarts. Update the listener logic to address multiple successive + // calls for a particular interface. + iface.mNetworkManagementListener = listener; + if (iface.updateInterface(ipConfig, capabilities)) { + mTrackingInterfaces.put(ifaceName, iface); + updateCapabilityFilter(); + } + } + + private void enforceInterfaceIsTracked(@NonNull final String ifaceName) { + if (!hasInterface(ifaceName)) { + throw new UnsupportedOperationException( + "Interface with name " + ifaceName + " is not being tracked."); + } + } + private static NetworkCapabilities mixInCapabilities(NetworkCapabilities nc, NetworkCapabilities addedNc) { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(nc); @@ -194,11 +229,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void updateCapabilityFilter() { - NetworkCapabilities capabilitiesFilter = - NetworkCapabilities.Builder.withoutDefaultCapabilities() - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .build(); - + NetworkCapabilities capabilitiesFilter = createDefaultNetworkCapabilities(); for (NetworkInterfaceState iface: mTrackingInterfaces.values()) { capabilitiesFilter = mixInCapabilities(capabilitiesFilter, iface.mCapabilities); } @@ -207,6 +238,12 @@ public class EthernetNetworkFactory extends NetworkFactory { setCapabilityFilter(capabilitiesFilter); } + private static NetworkCapabilities createDefaultNetworkCapabilities() { + return NetworkCapabilities.Builder + .withoutDefaultCapabilities() + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET).build(); + } + void removeInterface(String interfaceName) { NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName); if (iface != null) { @@ -230,15 +267,8 @@ public class EthernetNetworkFactory extends NetworkFactory { return iface.updateLinkState(up); } - boolean hasInterface(String interfacName) { - return mTrackingInterfaces.containsKey(interfacName); - } - - void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) { - NetworkInterfaceState network = mTrackingInterfaces.get(iface); - if (network != null) { - network.setIpConfig(ipConfiguration); - } + boolean hasInterface(String ifaceName) { + return mTrackingInterfaces.containsKey(ifaceName); } private NetworkInterfaceState networkForRequest(NetworkRequest request) { @@ -272,24 +302,26 @@ public class EthernetNetworkFactory extends NetworkFactory { return network; } - private static class NetworkInterfaceState { + @VisibleForTesting + static class NetworkInterfaceState { final String name; private final String mHwAddress; - private final NetworkCapabilities mCapabilities; private final Handler mHandler; private final Context mContext; private final NetworkFactory mNetworkFactory; private final Dependencies mDeps; - private final int mLegacyType; private static String sTcpBufferSizes = null; // Lazy initialized. private boolean mLinkUp; + private int mLegacyType; private LinkProperties mLinkProperties = new LinkProperties(); private volatile @Nullable IpClientManager mIpClient; + private @NonNull NetworkCapabilities mCapabilities; private @Nullable IpClientCallbacksImpl mIpClientCallback; + private @Nullable IInternalNetworkManagementListener mNetworkManagementListener; private @Nullable EthernetNetworkAgent mNetworkAgent; private @Nullable IpConfiguration mIpConfig; @@ -362,42 +394,17 @@ public class EthernetNetworkFactory extends NetworkFactory { } NetworkInterfaceState(String ifaceName, String hwAddress, Handler handler, Context context, - @NonNull NetworkCapabilities capabilities, NetworkFactory networkFactory, - Dependencies deps) { + @NonNull IpConfiguration ipConfig, @NonNull NetworkCapabilities capabilities, + NetworkFactory networkFactory, Dependencies deps) { name = ifaceName; + mIpConfig = Objects.requireNonNull(ipConfig); mCapabilities = Objects.requireNonNull(capabilities); + mLegacyType = getLegacyType(mCapabilities); mHandler = handler; mContext = context; mNetworkFactory = networkFactory; mDeps = deps; - final int legacyType; - int[] transportTypes = mCapabilities.getTransportTypes(); - - if (transportTypes.length > 0) { - legacyType = getLegacyType(transportTypes[0]); - } else { - // Should never happen as transport is always one of ETHERNET or a valid override - throw new ConfigurationException("Network Capabilities do not have an associated " - + "transport type."); - } - mHwAddress = hwAddress; - mLegacyType = legacyType; - } - - void setIpConfig(IpConfiguration ipConfig) { - if (Objects.equals(this.mIpConfig, ipConfig)) { - if (DBG) Log.d(TAG, "ipConfig have not changed,so ignore setIpConfig"); - return; - } - this.mIpConfig = ipConfig; - if (mNetworkAgent != null) { - restart(); - } - } - - boolean isRestricted() { - return !mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); } /** @@ -408,6 +415,52 @@ public class EthernetNetworkFactory extends NetworkFactory { return sTransports.get(transport, ConnectivityManager.TYPE_NONE); } + private static int getLegacyType(@NonNull final NetworkCapabilities capabilities) { + final int[] transportTypes = capabilities.getTransportTypes(); + if (transportTypes.length > 0) { + return getLegacyType(transportTypes[0]); + } + + // Should never happen as transport is always one of ETHERNET or a valid override + throw new ConfigurationException("Network Capabilities do not have an associated " + + "transport type."); + } + + private void setCapabilities(@NonNull final NetworkCapabilities capabilities) { + mCapabilities = new NetworkCapabilities(capabilities); + mLegacyType = getLegacyType(mCapabilities); + } + + boolean updateInterface(@NonNull final IpConfiguration ipConfig, + @Nullable final NetworkCapabilities capabilities) { + final boolean shouldUpdateIpConfig = !Objects.equals(mIpConfig, ipConfig); + final boolean shouldUpdateCapabilities = null != capabilities + && !Objects.equals(mCapabilities, capabilities); + if (DBG) { + Log.d(TAG, "updateInterface, iface: " + name + + ", shouldUpdateIpConfig: " + shouldUpdateIpConfig + + ", shouldUpdateCapabilities: " + shouldUpdateCapabilities + + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig + + ", capabilities: " + capabilities + ", old capabilities: " + mCapabilities + ); + } + + if (shouldUpdateIpConfig) { mIpConfig = ipConfig; }; + if (shouldUpdateCapabilities) { setCapabilities(capabilities); }; + if (shouldUpdateIpConfig || shouldUpdateCapabilities) { + // TODO: Update this logic to only do a restart if required. Although a restart may + // be required due to the capabilities or ipConfiguration values, not all + // capabilities changes require a restart. + restart(); + return true; + } + return false; + } + + boolean isRestricted() { + return !mCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + } + private void start() { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); @@ -459,6 +512,19 @@ public class EthernetNetworkFactory extends NetworkFactory { }); mNetworkAgent.register(); mNetworkAgent.markConnected(); + sendNetworkManagementCallback(); + } + + private void sendNetworkManagementCallback() { + if (null != mNetworkManagementListener) { + try { + mNetworkManagementListener.onComplete(mNetworkAgent.getNetwork(), null); + } catch (RemoteException e) { + Log.e(TAG, "Can't send onComplete for network management callback", e); + } finally { + mNetworkManagementListener = null; + } + } } void onIpLayerStopped(LinkProperties linkProperties) { @@ -546,7 +612,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } void restart(){ - if (DBG) Log.d(TAG, "reconnecting Etherent"); + if (DBG) Log.d(TAG, "reconnecting Ethernet"); stop(); start(); } diff --git a/service-t/src/com/android/server/ethernet/EthernetService.java b/service-t/src/com/android/server/ethernet/EthernetService.java index 467ab677d8..492a55aff1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetService.java +++ b/service-t/src/com/android/server/ethernet/EthernetService.java @@ -17,11 +17,16 @@ package com.android.server.ethernet; import android.content.Context; +import android.net.INetd; +import android.net.util.NetdService; import android.os.Handler; import android.os.HandlerThread; +import android.os.IBinder; import android.util.Log; import com.android.server.SystemService; +import java.util.Objects; + public final class EthernetService extends SystemService { private static final String TAG = "EthernetService"; @@ -32,9 +37,17 @@ public final class EthernetService extends SystemService { super(context); final HandlerThread handlerThread = new HandlerThread(THREAD_NAME); handlerThread.start(); + final Handler handler = handlerThread.getThreadHandler(); + final EthernetNetworkFactory factory = new EthernetNetworkFactory(handler, context); mImpl = new EthernetServiceImpl( - context, handlerThread.getThreadHandler(), - new EthernetTracker(context, handlerThread.getThreadHandler())); + context, handler, + new EthernetTracker(context, handler, factory, getNetd())); + } + + private INetd getNetd() { + final INetd netd = NetdService.getInstance(); + Objects.requireNonNull(netd, "could not get netd instance"); + return netd; } @Override diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index f107865c30..b2844779c8 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -233,6 +233,9 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { + ", request=" + request + ", listener=" + listener); validateNetworkManagementState(iface, "updateConfiguration()"); // TODO: validate that iface is listed in overlay config_ethernet_interfaces + + mTracker.updateConfiguration( + iface, request.getIpConfig(), request.getNetworkCapabilities(), listener); } @Override diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 9660194508..0b6547d145 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; +import android.net.IInternalNetworkManagementListener; import android.net.INetd; import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfigurationParcel; @@ -34,7 +35,6 @@ import android.net.LinkAddress; import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; import android.os.Handler; -import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -118,14 +118,12 @@ public class EthernetTracker { } } - EthernetTracker(Context context, Handler handler) { + EthernetTracker(@NonNull final Context context, @NonNull final Handler handler, + @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd) { mContext = context; mHandler = handler; - - // The services we use. - mNetd = INetd.Stub.asInterface( - (IBinder) context.getSystemService(Context.NETD_SERVICE)); - Objects.requireNonNull(mNetd, "could not get netd instance"); + mFactory = factory; + mNetd = netd; // Interface match regex. updateIfaceMatchRegexp(); @@ -138,9 +136,6 @@ public class EthernetTracker { } mConfigStore = new EthernetConfigStore(); - - NetworkCapabilities nc = createNetworkCapabilities(true /* clear default capabilities */); - mFactory = new EthernetNetworkFactory(handler, context, nc); } void start() { @@ -168,11 +163,30 @@ public class EthernetTracker { if (DBG) { Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration); } + writeIpConfiguration(iface, ipConfiguration); + mHandler.post(() -> mFactory.updateInterface(iface, ipConfiguration, null, null)); + } - mConfigStore.write(iface, ipConfiguration); - mIpConfigurations.put(iface, ipConfiguration); + private void writeIpConfiguration(@NonNull final String iface, + @NonNull final IpConfiguration ipConfig) { + mConfigStore.write(iface, ipConfig); + mIpConfigurations.put(iface, ipConfig); + } - mHandler.post(() -> mFactory.updateIpConfiguration(iface, ipConfiguration)); + @VisibleForTesting(visibility = PACKAGE) + protected void updateConfiguration(@NonNull final String iface, + @NonNull final StaticIpConfiguration staticIpConfig, + @NonNull final NetworkCapabilities capabilities, + @Nullable final IInternalNetworkManagementListener listener) { + if (DBG) { + Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities + + ", staticIpConfig: " + staticIpConfig); + } + final IpConfiguration ipConfig = createIpConfiguration(staticIpConfig); + writeIpConfiguration(iface, ipConfig); + mNetworkCapabilities.put(iface, capabilities); + mHandler.post(() -> + mFactory.updateInterface(iface, ipConfig, capabilities, listener)); } IpConfiguration getIpConfiguration(String iface) { @@ -325,7 +339,7 @@ public class EthernetTracker { } Log.d(TAG, "Tracking interface in client mode: " + iface); - mFactory.addInterface(iface, hwAddress, nc, ipConfiguration); + mFactory.addInterface(iface, hwAddress, ipConfiguration, nc); } else { maybeUpdateServerModeInterfaceState(iface, true); } @@ -460,11 +474,11 @@ public class EthernetTracker { NetworkCapabilities nc = createNetworkCapabilities( !TextUtils.isEmpty(config.mCapabilities) /* clear default capabilities */, config.mCapabilities, config.mTransport).build(); - mNetworkCapabilities.put(config.mName, nc); + mNetworkCapabilities.put(config.mIface, nc); if (null != config.mIpConfig) { IpConfiguration ipConfig = parseStaticIpConfiguration(config.mIpConfig); - mIpConfigurations.put(config.mName, ipConfig); + mIpConfigurations.put(config.mIface, ipConfig); } } @@ -493,10 +507,6 @@ public class EthernetTracker { return builder.build(); } - private static NetworkCapabilities createNetworkCapabilities(boolean clearDefaultCapabilities) { - return createNetworkCapabilities(clearDefaultCapabilities, null, null).build(); - } - /** * Parses a static list of network capabilities * @@ -623,10 +633,15 @@ public class EthernetTracker { } } } + return createIpConfiguration(staticIpConfigBuilder.build()); + } + + static IpConfiguration createIpConfiguration( + @NonNull final StaticIpConfiguration staticIpConfig) { final IpConfiguration ret = new IpConfiguration(); ret.setIpAssignment(IpAssignment.STATIC); ret.setProxySettings(ProxySettings.NONE); - ret.setStaticIpConfiguration(staticIpConfigBuilder.build()); + ret.setStaticIpConfiguration(staticIpConfig); return ret; } @@ -681,14 +696,14 @@ public class EthernetTracker { @VisibleForTesting static class EthernetTrackerConfig { - final String mName; + final String mIface; final String mCapabilities; final String mIpConfig; final String mTransport; EthernetTrackerConfig(@NonNull final String[] tokens) { Objects.requireNonNull(tokens, "EthernetTrackerConfig requires non-null tokens"); - mName = tokens[0]; + mIface = tokens[0]; mCapabilities = tokens.length > 1 ? tokens[1] : null; mIpConfig = tokens.length > 2 && !TextUtils.isEmpty(tokens[2]) ? tokens[2] : null; mTransport = tokens.length > 3 ? tokens[3] : null; diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp index 1bc9352f9b..93a8f6ca45 100644 --- a/tests/ethernet/Android.bp +++ b/tests/ethernet/Android.bp @@ -36,6 +36,8 @@ android_test { "ethernet-service", "frameworks-base-testutils", "mockito-target-minus-junit4", + "net-tests-utils", + "services.core", "services.net", ], } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 990ee5fee7..44ed26c9b4 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -16,9 +16,11 @@ package com.android.server.ethernet; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; @@ -36,17 +38,24 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; +import android.net.IInternalNetworkManagementListener; +import android.net.InternalNetworkManagementException; import android.net.IpConfiguration; +import android.net.LinkAddress; import android.net.LinkProperties; +import android.net.Network; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkProvider; import android.net.NetworkRequest; +import android.net.StaticIpConfiguration; import android.net.ip.IpClientCallbacks; import android.net.ip.IpClientManager; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.test.TestLooper; +import android.util.Pair; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -61,10 +70,20 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + @RunWith(AndroidJUnit4.class) @SmallTest public class EthernetNetworkFactoryTest { + private static final int TIMEOUT_MS = 2_000; private static final String TEST_IFACE = "test123"; + private static final String IP_ADDR = "192.0.2.2/25"; + private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); + private static final String HW_ADDR = "01:02:03:04:05:06"; private final TestLooper mLooper = new TestLooper(); private Handler mHandler; private EthernetNetworkFactory mNetFactory = null; @@ -75,13 +94,13 @@ public class EthernetNetworkFactoryTest { @Mock private IpClientManager mIpClient; @Mock private EthernetNetworkAgent mNetworkAgent; @Mock private InterfaceParams mInterfaceParams; + @Mock private Network mMockNetwork; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mHandler = new Handler(mLooper.getLooper()); - mNetFactory = new EthernetNetworkFactory(mHandler, mContext, createDefaultFilterCaps(), - mDeps); + mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mDeps); setupNetworkAgentMock(); setupIpClientMock(); @@ -100,6 +119,8 @@ public class EthernetNetworkFactoryTest { NetworkProvider provider, EthernetNetworkAgent.Callbacks cb) { when(mNetworkAgent.getCallbacks()).thenReturn(cb); + when(mNetworkAgent.getNetwork()) + .thenReturn(mMockNetwork); return mNetworkAgent; } } @@ -185,6 +206,19 @@ public class EthernetNetworkFactoryTest { return ipConfig; } + /** + * Create an {@link IpConfiguration} with an associated {@link StaticIpConfiguration}. + * + * @return {@link IpConfiguration} with its {@link StaticIpConfiguration} set. + */ + private IpConfiguration createStaticIpConfig() { + final IpConfiguration ipConfig = new IpConfiguration(); + ipConfig.setIpAssignment(IpConfiguration.IpAssignment.STATIC); + ipConfig.setStaticIpConfiguration( + new StaticIpConfiguration.Builder().setIpAddress(LINK_ADDR).build()); + return ipConfig; + } + // creates an interface with provisioning in progress (since updating the interface link state // automatically starts the provisioning process) private void createInterfaceUndergoingProvisioning(String iface) { @@ -194,10 +228,11 @@ public class EthernetNetworkFactoryTest { private void createInterfaceUndergoingProvisioning( @NonNull final String iface, final int transportType) { - mNetFactory.addInterface(iface, iface, createInterfaceCapsBuilder(transportType).build(), - createDefaultIpConfig()); + final IpConfiguration ipConfig = createDefaultIpConfig(); + mNetFactory.addInterface(iface, HW_ADDR, ipConfig, + createInterfaceCapsBuilder(transportType).build()); assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); - verifyStart(); + verifyStart(ipConfig); clearInvocations(mDeps); clearInvocations(mIpClient); } @@ -431,13 +466,19 @@ public class EthernetNetworkFactoryTest { triggerOnReachabilityLost(); // Reachability loss should trigger a stop and start, since the interface is still there - verifyStop(); - verifyStart(); + verifyRestart(createDefaultIpConfig()); } - private void verifyStart() { + private void verifyRestart(@NonNull final IpConfiguration ipConfig) { + verifyStop(); + verifyStart(ipConfig); + } + + private void verifyStart(@NonNull final IpConfiguration ipConfig) { verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); - verify(mIpClient).startProvisioning(any()); + verify(mIpClient).startProvisioning( + argThat(x -> Objects.equals(x.mStaticIpConfig, ipConfig.getStaticIpConfiguration())) + ); } private void verifyStop() { @@ -449,4 +490,56 @@ public class EthernetNetworkFactoryTest { verify(mNetworkAgent).register(); verify(mNetworkAgent).markConnected(); } + + private static final class TestNetworkManagementListener + implements IInternalNetworkManagementListener { + private final CompletableFuture> mDone + = new CompletableFuture<>(); + + @Override + public void onComplete(final Network network, + final InternalNetworkManagementException exception) { + mDone.complete(new Pair<>(network, exception)); + } + + Pair expectOnComplete() throws Exception { + return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + @Override + public IBinder asBinder() { + return null; + } + } + + @Test + public void testUpdateInterfaceCallsListenerCorrectlyOnSuccess() throws Exception { + createAndVerifyProvisionedInterface(TEST_IFACE); + final NetworkCapabilities capabilities = createDefaultFilterCaps(); + final IpConfiguration ipConfiguration = createStaticIpConfig(); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + + mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); + triggerOnProvisioningSuccess(); + + final Pair ret = listener.expectOnComplete(); + assertEquals(mMockNetwork, ret.first); + assertNull(ret.second); + } + + @Test + public void testUpdateInterfaceRestartsAgentCorrectly() throws Exception { + createAndVerifyProvisionedInterface(TEST_IFACE); + final NetworkCapabilities capabilities = createDefaultFilterCaps(); + final IpConfiguration ipConfiguration = createStaticIpConfig(); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + + mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); + triggerOnProvisioningSuccess(); + + listener.expectOnComplete(); + verify(mDeps).makeEthernetNetworkAgent(any(), any(), + eq(capabilities), any(), any(), any(), any()); + verifyRestart(ipConfiguration); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 516e574522..1c0888398a 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -18,13 +18,17 @@ package com.android.server.ethernet; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; +import android.net.IInternalNetworkManagementListener; import android.net.InternalNetworkUpdateRequest; import android.net.IpConfiguration; +import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; import android.os.Handler; @@ -41,6 +45,10 @@ import org.mockito.MockitoAnnotations; @SmallTest public class EthernetServiceImplTest { private static final String TEST_IFACE = "test123"; + private static final InternalNetworkUpdateRequest UPDATE_REQUEST = + new InternalNetworkUpdateRequest( + new StaticIpConfiguration(), new NetworkCapabilities.Builder().build()); + private static final IInternalNetworkManagementListener NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @Mock private Handler mHandler; @@ -69,10 +77,8 @@ public class EthernetServiceImplTest { public void testUpdateConfigurationRejectsWhenEthNotStarted() { mEthernetServiceImpl.mStarted.set(false); assertThrows(IllegalStateException.class, () -> { - final InternalNetworkUpdateRequest r = - new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); - - mEthernetServiceImpl.updateConfiguration("" /* iface */, r, null /* listener */); + mEthernetServiceImpl.updateConfiguration( + "" /* iface */, UPDATE_REQUEST, null /* listener */); }); } @@ -95,24 +101,21 @@ public class EthernetServiceImplTest { @Test public void testUpdateConfigurationRejectsNullIface() { assertThrows(NullPointerException.class, () -> { - final InternalNetworkUpdateRequest r = - new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); - - mEthernetServiceImpl.updateConfiguration(null /* iface */, r, null /* listener */); + mEthernetServiceImpl.updateConfiguration(null, UPDATE_REQUEST, NULL_LISTENER); }); } @Test public void testConnectNetworkRejectsNullIface() { assertThrows(NullPointerException.class, () -> { - mEthernetServiceImpl.connectNetwork(null /* iface */, null /* listener */); + mEthernetServiceImpl.connectNetwork(null /* iface */, NULL_LISTENER); }); } @Test public void testDisconnectNetworkRejectsNullIface() { assertThrows(NullPointerException.class, () -> { - mEthernetServiceImpl.disconnectNetwork(null /* iface */, null /* listener */); + mEthernetServiceImpl.disconnectNetwork(null /* iface */, NULL_LISTENER); }); } @@ -120,10 +123,7 @@ public class EthernetServiceImplTest { public void testUpdateConfigurationRejectsWithoutAutomotiveFeature() { toggleAutomotiveFeature(false); assertThrows(UnsupportedOperationException.class, () -> { - final InternalNetworkUpdateRequest r = - new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); - - mEthernetServiceImpl.updateConfiguration("" /* iface */, r, null /* listener */); + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); }); } @@ -131,7 +131,7 @@ public class EthernetServiceImplTest { public void testConnectNetworkRejectsWithoutAutomotiveFeature() { toggleAutomotiveFeature(false); assertThrows(UnsupportedOperationException.class, () -> { - mEthernetServiceImpl.connectNetwork("" /* iface */, null /* listener */); + mEthernetServiceImpl.connectNetwork("" /* iface */, NULL_LISTENER); }); } @@ -139,7 +139,7 @@ public class EthernetServiceImplTest { public void testDisconnectNetworkRejectsWithoutAutomotiveFeature() { toggleAutomotiveFeature(false); assertThrows(UnsupportedOperationException.class, () -> { - mEthernetServiceImpl.disconnectNetwork("" /* iface */, null /* listener */); + mEthernetServiceImpl.disconnectNetwork("" /* iface */, NULL_LISTENER); }); } @@ -152,10 +152,7 @@ public class EthernetServiceImplTest { public void testUpdateConfigurationRejectsWithUntrackedIface() { shouldTrackIface(TEST_IFACE, false); assertThrows(UnsupportedOperationException.class, () -> { - final InternalNetworkUpdateRequest r = - new InternalNetworkUpdateRequest(new StaticIpConfiguration(), null); - - mEthernetServiceImpl.updateConfiguration(TEST_IFACE, r, null /* listener */); + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); }); } @@ -163,7 +160,7 @@ public class EthernetServiceImplTest { public void testConnectNetworkRejectsWithUntrackedIface() { shouldTrackIface(TEST_IFACE, false); assertThrows(UnsupportedOperationException.class, () -> { - mEthernetServiceImpl.connectNetwork(TEST_IFACE, null /* listener */); + mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER); }); } @@ -171,11 +168,20 @@ public class EthernetServiceImplTest { public void testDisconnectNetworkRejectsWithUntrackedIface() { shouldTrackIface(TEST_IFACE, false); assertThrows(UnsupportedOperationException.class, () -> { - mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, null /* listener */); + mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); }); } private void shouldTrackIface(@NonNull final String iface, final boolean shouldTrack) { doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface); } + + @Test + public void testUpdateConfiguration() { + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); + verify(mEthernetTracker).updateConfiguration( + eq(TEST_IFACE), + eq(UPDATE_REQUEST.getIpConfig()), + eq(UPDATE_REQUEST.getNetworkCapabilities()), eq(NULL_LISTENER)); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 6ea2154337..5aca2e40a0 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -19,20 +19,35 @@ package com.android.server.ethernet; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import android.content.Context; +import android.content.res.Resources; import android.net.InetAddresses; +import android.net.IInternalNetworkManagementListener; +import android.net.INetd; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; +import android.os.HandlerThread; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.R; +import com.android.testutils.HandlerUtils; + +import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.net.InetAddress; import java.util.ArrayList; @@ -40,6 +55,39 @@ import java.util.ArrayList; @SmallTest @RunWith(AndroidJUnit4.class) public class EthernetTrackerTest { + private static final int TIMEOUT_MS = 1_000; + private static final String THREAD_NAME = "EthernetServiceThread"; + private EthernetTracker tracker; + private HandlerThread mHandlerThread; + @Mock private Context mContext; + @Mock private EthernetNetworkFactory mFactory; + @Mock private INetd mNetd; + @Mock Resources mResources; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + initMockResources(); + mHandlerThread = new HandlerThread(THREAD_NAME); + mHandlerThread.start(); + tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd); + } + + @After + public void cleanUp() { + mHandlerThread.quitSafely(); + } + + private void initMockResources() { + doReturn("").when(mResources).getString(R.string.config_ethernet_iface_regex); + doReturn(new String[0]).when(mResources).getStringArray(R.array.config_ethernet_interfaces); + doReturn(mResources).when(mContext).getResources(); + } + + private void waitForIdle() { + HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS); + } + /** * Test: Creation of various valid static IP configurations */ @@ -246,16 +294,16 @@ public class EthernetTrackerTest { @Test public void testCreateEthernetTrackerConfigReturnsCorrectValue() { - final String name = "1"; + final String iface = "1"; final String capabilities = "2"; final String ipConfig = "3"; final String transport = "4"; - final String configString = String.join(";", name, capabilities, ipConfig, transport); + final String configString = String.join(";", iface, capabilities, ipConfig, transport); final EthernetTracker.EthernetTrackerConfig config = EthernetTracker.createEthernetTrackerConfig(configString); - assertEquals(name, config.mName); + assertEquals(iface, config.mIface); assertEquals(capabilities, config.mCapabilities); assertEquals(ipConfig, config.mIpConfig); assertEquals(transport, config.mTransport); @@ -266,4 +314,19 @@ public class EthernetTrackerTest { assertThrows(NullPointerException.class, () -> EthernetTracker.createEthernetTrackerConfig(null)); } + + @Test + public void testUpdateConfiguration() { + final String iface = "testiface"; + final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build(); + final StaticIpConfiguration staticIpConfig = new StaticIpConfiguration(); + final IInternalNetworkManagementListener listener = null; + + tracker.updateConfiguration(iface, staticIpConfig, capabilities, listener); + waitForIdle(); + + verify(mFactory).updateInterface( + eq(iface), eq(EthernetTracker.createIpConfiguration(staticIpConfig)), + eq(capabilities), eq(listener)); + } } From c9dedfbe95cd0b34462c67995eff57283b563c7c Mon Sep 17 00:00:00 2001 From: lifr Date: Thu, 23 Dec 2021 15:13:29 +0800 Subject: [PATCH 755/881] [DU03]Remove INetworkStatsService from BatteryStatsImpl BatteryStatsImpl is using INetworkStatsService APIs, which cannot be accessed after moving into the mainline module. So, replace and remove those hidden API usages. Bug: 210066922 Test: atest BatteryStatsImplTest WifiPowerCalculatorTest MobileRadioPowerCalculatorTest CTS-Coverage-Bug: 213437796 (cherry-picked from ag/16548638) Change-Id: I584897ff8ba303c717a9df3756c9f6778c1cfb10 Merged-In: I584897ff8ba303c717a9df3756c9f6778c1cfb10 --- .../app/usage/NetworkStatsManager.java | 26 +++++++++++++++++++ .../server/net/NetworkStatsService.java | 1 + 2 files changed, 27 insertions(+) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index a316b8a617..583f7ba8cd 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -54,6 +54,7 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; +import java.util.Set; /** * Provides access to network usage history and statistics. Usage data is collected in @@ -535,6 +536,31 @@ public class NetworkStatsManager { return result; } + /** + * Query realtime network usage statistics details with interfaces constrains. + * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING}, + * video calling data usage and count of network operations that set by + * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any + * statistics that is reported by {@link NetworkStatsProvider}. + * + * @param requiredIfaces A list of interfaces the stats should be restricted to, or + * {@link NetworkStats#INTERFACES_ALL}. + * + * @hide + */ + //@SystemApi + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + @NonNull public android.net.NetworkStats getDetailedUidStats( + @NonNull Set requiredIfaces) { + Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null"); + try { + return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0])); + } catch (RemoteException e) { + if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats"); + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ public void registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 97281ed424..4db90c1b1a 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -922,6 +922,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDetailedUidStats(String[] requiredIfaces) { + enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); try { final String[] ifacesToQuery = mStatsFactory.augmentWithStackedInterfaces(requiredIfaces); From 77422187544271b04ce33d80718bcb4c3e73e565 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 12 Jan 2022 23:00:20 +0800 Subject: [PATCH 756/881] Check iface by TextUtils.equals In current equals method, if iface is null then it will cause null object reference when checking iface. Thus, use TextUtils.equals to check iface so that it can compare null iface. Bug: 210073043 Test: FrameworksNetTests, NetworkStaticLibTests Change-Id: I2bd8127cb030ea54438382ee89961590fffbc31a --- framework-t/src/android/net/NetworkStats.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java index b00fea4de2..352849c1e8 100644 --- a/framework-t/src/android/net/NetworkStats.java +++ b/framework-t/src/android/net/NetworkStats.java @@ -28,6 +28,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.SystemClock; +import android.text.TextUtils; import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; @@ -410,7 +411,7 @@ public final class NetworkStats implements Parcelable { && roaming == e.roaming && defaultNetwork == e.defaultNetwork && rxBytes == e.rxBytes && rxPackets == e.rxPackets && txBytes == e.txBytes && txPackets == e.txPackets - && operations == e.operations && iface.equals(e.iface); + && operations == e.operations && TextUtils.equals(iface, e.iface); } return false; } From 7577deee2135bcafe317e1fc8f319e0eaef5be0a Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 7 Jan 2022 11:28:54 +0000 Subject: [PATCH 757/881] [MS44.1] Add API to query tagged UID summary Query tagged UID summary is currently needed by StatsPullAtomService to collect tagged traffic statistics. Add an Api via NetworkStatsManager to support this functionality. Test: atest NetworkStatsManagerTest Bug: 204830222 Change-Id: Iaa54482a8109b56e66e829c5bec5a8a8f466641a --- .../src/android/app/usage/NetworkStats.java | 9 +++++ .../app/usage/NetworkStatsManager.java | 35 ++++++++++++++++++- .../src/android/net/INetworkStatsSession.aidl | 4 +++ .../server/net/NetworkStatsService.java | 14 ++++++-- 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java index f684a4d9d8..d33666d744 100644 --- a/framework-t/src/android/app/usage/NetworkStats.java +++ b/framework-t/src/android/app/usage/NetworkStats.java @@ -544,6 +544,15 @@ public final class NetworkStats implements AutoCloseable { mEnumerationIndex = 0; } + /** + * Collects tagged summary results and sets summary enumeration mode. + * @throws RemoteException + */ + void startTaggedSummaryEnumeration() throws RemoteException { + mSummary = mSession.getTaggedSummaryForAllUid(mTemplate, mStartTimeStamp, mEndTimeStamp); + mEnumerationIndex = 0; + } + /** * Collects history results for uid and resets history enumeration index. */ diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index a316b8a617..8043a374bd 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -368,7 +368,7 @@ public class NetworkStatsManager { * @return Statistics which is described above. * @hide */ - @Nullable + @NonNull // @SystemApi(client = MODULE_LIBRARIES) @WorkerThread public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime, @@ -384,6 +384,39 @@ public class NetworkStatsManager { return null; // To make the compiler happy. } + /** + * Query tagged network usage statistics summaries. + * + * The results will only include tagged traffic made by UIDs belonging to the calling user + * profile. The results are aggregated over time, so that all buckets will have the same + * start and end timestamps as the passed arguments. Not aggregated over state, uid, + * default network, metered, or roaming. + * This may take a long time, and apps should avoid calling this on their main thread. + * + * @param template Template used to match networks. See {@link NetworkTemplate}. + * @param startTime Start of period, in milliseconds since the Unix epoch, see + * {@link System#currentTimeMillis}. + * @param endTime End of period, in milliseconds since the Unix epoch, see + * {@link System#currentTimeMillis}. + * @return Statistics which is described above. + * @hide + */ + @NonNull + // @SystemApi(client = MODULE_LIBRARIES) + @WorkerThread + public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime, + long endTime) throws SecurityException { + try { + NetworkStats result = + new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); + result.startTaggedSummaryEnumeration(); + return result; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + return null; // To make the compiler happy. + } + /** * Query network usage statistics details for a given uid. * This may take a long time, and apps should avoid calling this on their main thread. diff --git a/framework-t/src/android/net/INetworkStatsSession.aidl b/framework-t/src/android/net/INetworkStatsSession.aidl index dfedf6633d..babe0bfb97 100644 --- a/framework-t/src/android/net/INetworkStatsSession.aidl +++ b/framework-t/src/android/net/INetworkStatsSession.aidl @@ -46,6 +46,10 @@ interface INetworkStatsSession { */ @UnsupportedAppUsage NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags); + + /** Return network layer usage summary per UID for tagged traffic that matches template. */ + NetworkStats getTaggedSummaryForAllUid(in NetworkTemplate template, long start, long end); + /** Return historical network layer stats for specific UID traffic that matches template. */ @UnsupportedAppUsage NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields); diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 97281ed424..2b73eb6100 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -766,8 +766,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } return stats; } catch (NullPointerException e) { - // TODO: Track down and fix the cause of this crash and remove this catch block. - Log.wtf(TAG, "NullPointerException in getSummaryForAllUid", e); + throw e; + } + } + + @Override + public NetworkStats getTaggedSummaryForAllUid( + NetworkTemplate template, long start, long end) { + try { + final NetworkStats tagStats = getUidTagComplete() + .getSummary(template, start, end, mAccessLevel, mCallingUid); + return tagStats; + } catch (NullPointerException e) { throw e; } } From 595dc3b96e6de2b467fd7565bb35e066c3bfaefb Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 16 Dec 2021 00:11:15 +0800 Subject: [PATCH 758/881] Add PolicyDirection InfDef annotation to IpSecManager IpSec is going to be moved into Connectivity module and it needs to use PolicyDirection annotation. Add PolicyDirection IntDef annotation so that it can be used in the module. Bug: 204153604 Test: FrameworksNetTests Change-Id: Ib411d8c436d67574bfaf7f3aba43e5f31e7487e2 --- framework-t/src/android/net/IpSecManager.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java index 0d15dffae9..49aa99b097 100644 --- a/framework-t/src/android/net/IpSecManager.java +++ b/framework-t/src/android/net/IpSecManager.java @@ -17,6 +17,7 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; @@ -25,7 +26,6 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; import android.content.pm.PackageManager; -import android.net.annotations.PolicyDirection; import android.os.Binder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -41,6 +41,8 @@ import dalvik.system.CloseGuard; import java.io.FileDescriptor; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.Socket; @@ -88,6 +90,11 @@ public final class IpSecManager { @SystemApi(client = MODULE_LIBRARIES) public static final int DIRECTION_FWD = 2; + /** @hide */ + @IntDef(value = {DIRECTION_IN, DIRECTION_OUT}) + @Retention(RetentionPolicy.SOURCE) + public @interface PolicyDirection {} + /** * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index. * From af0aab7b68bab4738f8d58b52e435251225260ce Mon Sep 17 00:00:00 2001 From: Pavan Kumar M Date: Thu, 6 Jan 2022 14:19:48 +0530 Subject: [PATCH 759/881] Synchronize the IpClient events If the ipClient is stopped before handling the events in Handler thread, ethernet network factory might end up creating a network agent for a network which is already cleared. This change fixes the issue by handling the events only if ipClient is initialized. Tests: Builds, Boots, EthernetNetworkFactoryTest. Ethernet related test scenarios Bug: 207057937 Change-Id: If7ff7abf5f0dcdb0e94de0502bfdf981f9f20298 --- .../ethernet/EthernetNetworkFactory.java | 16 ++++++ .../ethernet/EthernetNetworkFactoryTest.java | 53 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index b556f6c949..7b727a3ce3 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -481,6 +481,10 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStarted(LinkProperties linkProperties) { + if(mIpClient == null) { + if (DBG) Log.d(TAG, "IpClient is not initialized."); + return; + } if (mNetworkAgent != null) { Log.e(TAG, "Already have a NetworkAgent - aborting new request"); stop(); @@ -528,6 +532,10 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStopped(LinkProperties linkProperties) { + if(mIpClient == null) { + if (DBG) Log.d(TAG, "IpClient is not initialized."); + return; + } // This cannot happen due to provisioning timeout, because our timeout is 0. It can only // happen if we're provisioned and we lose provisioning. stop(); @@ -539,6 +547,10 @@ public class EthernetNetworkFactory extends NetworkFactory { } void updateLinkProperties(LinkProperties linkProperties) { + if(mIpClient == null) { + if (DBG) Log.d(TAG, "IpClient is not initialized."); + return; + } mLinkProperties = linkProperties; if (mNetworkAgent != null) { mNetworkAgent.sendLinkPropertiesImpl(linkProperties); @@ -546,6 +558,10 @@ public class EthernetNetworkFactory extends NetworkFactory { } void updateNeighborLostEvent(String logMsg) { + if(mIpClient == null) { + if (DBG) Log.d(TAG, "IpClient is not initialized."); + return; + } Log.i(TAG, "updateNeighborLostEvent " + logMsg); // Reachability lost will be seen only if the gateway is not reachable. // Since ethernet FW doesn't have the mechanism to scan for new networks diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 44ed26c9b4..52ddf3c8ad 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -469,6 +469,59 @@ public class EthernetNetworkFactoryTest { verifyRestart(createDefaultIpConfig()); } + @Test + public void testIgnoreOnIpLayerStartedCallbackAfterIpClientHasStopped() throws Exception { + createAndVerifyProvisionedInterface(TEST_IFACE); + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); + mLooper.dispatchAll(); + verifyStop(); + + // ipClient has been shut down first, we should not retry + verify(mIpClient, never()).startProvisioning(any()); + verify(mNetworkAgent, never()).register(); + } + + @Test + public void testIgnoreOnIpLayerStoppedCallbackAfterIpClientHasStopped() throws Exception { + createAndVerifyProvisionedInterface(TEST_IFACE); + when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + verifyStop(); + + // ipClient has been shut down first, we should not retry + verify(mIpClient).startProvisioning(any()); + } + + @Test + public void testIgnoreLinkPropertiesCallbackAfterIpClientHasStopped() throws Exception { + createAndVerifyProvisionedInterface(TEST_IFACE); + LinkProperties lp = new LinkProperties(); + + mIpClientCallbacks.onProvisioningFailure(lp); + mIpClientCallbacks.onLinkPropertiesChange(lp); + mLooper.dispatchAll(); + verifyStop(); + + // ipClient has been shut down first, we should not update + verify(mNetworkAgent, never()).sendLinkPropertiesImpl(same(lp)); + } + + @Test + public void testIgnoreNeighborLossCallbackAfterIpClientHasStopped() throws Exception { + createAndVerifyProvisionedInterface(TEST_IFACE); + mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mIpClientCallbacks.onReachabilityLost("Neighbor Lost"); + mLooper.dispatchAll(); + verifyStop(); + + // ipClient has been shut down first, we should not update + verify(mIpClient, never()).startProvisioning(any()); + verify(mNetworkAgent, never()).register(); + } + private void verifyRestart(@NonNull final IpConfiguration ipConfig) { verifyStop(); verifyStart(ipConfig); From 5f631cf00b1770695de16b42f38c265296c51ed6 Mon Sep 17 00:00:00 2001 From: lifr Date: Mon, 27 Dec 2021 13:24:35 +0800 Subject: [PATCH 760/881] [DU04]Remove NetworkPolicyManagerInternal from NetworkStatsService NetworkStatsService is using NetworkPolicyManagerInternal APIs, which cannot be accessed after moving into the mainline module. So, replace and remove those hidden API usages. Bug: 211843446 Test: atest NetworkStatsServiceTest NetworkPolicyManagerTest NetworkPolicyManagerServiceTest Change-Id: I0f3f02d1dc014967fab27ffcf37dd1918dbef5e0 --- .../android/server/net/NetworkStatsService.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 74f3156305..37f7118efe 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -96,6 +96,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkIdentitySet; +import android.net.NetworkPolicyManager; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStateSnapshot; @@ -850,7 +851,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (LOGD) Log.d(TAG, "Resolving plan for " + template); final long token = Binder.clearCallingIdentity(); try { - plan = LocalServices.getService(NetworkPolicyManagerInternal.class) + plan = mContext.getSystemService(NetworkPolicyManager.class) .getSubscriptionPlan(template); } finally { Binder.restoreCallingIdentity(token); @@ -2021,10 +2022,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); Objects.requireNonNull(provider, "provider is null"); Objects.requireNonNull(tag, "tag is null"); + final NetworkPolicyManager netPolicyManager = mContext + .getSystemService(NetworkPolicyManager.class); try { NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl( tag, provider, mStatsProviderSem, mAlertObserver, - mStatsProviderCbList); + mStatsProviderCbList, netPolicyManager); mStatsProviderCbList.add(callback); Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid=" + getCallingUid() + "/" + getCallingPid()); @@ -2066,6 +2069,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final Semaphore mSemaphore; @NonNull final AlertObserver mAlertObserver; @NonNull final CopyOnWriteArrayList mStatsProviderCbList; + @NonNull final NetworkPolicyManager mNetworkPolicyManager; @NonNull private final Object mProviderStatsLock = new Object(); @@ -2079,7 +2083,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull String tag, @NonNull INetworkStatsProvider provider, @NonNull Semaphore semaphore, @NonNull AlertObserver alertObserver, - @NonNull CopyOnWriteArrayList cbList) + @NonNull CopyOnWriteArrayList cbList, + @NonNull NetworkPolicyManager networkPolicyManager) throws RemoteException { mTag = tag; mProvider = provider; @@ -2087,6 +2092,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSemaphore = semaphore; mAlertObserver = alertObserver; mStatsProviderCbList = cbList; + mNetworkPolicyManager = networkPolicyManager; } @NonNull @@ -2133,8 +2139,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void notifyWarningOrLimitReached() { Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); BinderUtils.withCleanCallingIdentity(() -> - LocalServices.getService(NetworkPolicyManagerInternal.class) - .onStatsProviderWarningOrLimitReached(mTag)); + mNetworkPolicyManager.onStatsProviderWarningOrLimitReached()); } @Override From 86adedf565d5eea95ca1f94db238a974cdc8a380 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 7 Jan 2022 06:55:30 +0000 Subject: [PATCH 761/881] [MS43] Remove EventLogTags depdendency Inline functions and copy constants to the service. Test: TH Bug: 204830222 Change-Id: Idf5c8ff7c7fec39530269b3c6b24475407198fbc --- .../com/android/server/net/NetworkStatsService.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 3273e88213..b99675e239 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -155,7 +155,6 @@ import com.android.net.module.util.BinderUtils; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkStatsUtils; import com.android.net.module.util.PermissionUtils; -import com.android.server.EventLogTags; import com.android.server.LocalServices; import java.io.File; @@ -209,6 +208,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String TAG_NETSTATS_ERROR = "netstats_error"; + /** + * EventLog tags used when logging into the event log. Note the values must be sync with + * frameworks/base/services/core/java/com/android/server/EventLogTags.logtags to get correct + * name translation. + */ + private static final int LOG_TAG_NETSTATS_MOBILE_SAMPLE = 51100; + private static final int LOG_TAG_NETSTATS_WIFI_SAMPLE = 51101; + private final Context mContext; private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; @@ -1624,7 +1631,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { xtTotal = mXtRecorder.getTotalSinceBootLocked(template); uidTotal = mUidRecorder.getTotalSinceBootLocked(template); - EventLogTags.writeNetstatsMobileSample( + EventLog.writeEvent(LOG_TAG_NETSTATS_MOBILE_SAMPLE, devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, @@ -1636,7 +1643,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { xtTotal = mXtRecorder.getTotalSinceBootLocked(template); uidTotal = mUidRecorder.getTotalSinceBootLocked(template); - EventLogTags.writeNetstatsWifiSample( + EventLog.writeEvent(LOG_TAG_NETSTATS_WIFI_SAMPLE, devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, From 4c0b80f6f190228ddb783bde94cc9564f8de7ba1 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 13 Jan 2022 16:17:01 +0000 Subject: [PATCH 762/881] Revert "Pivot network statistics to use DataInput/Output." This reverts commit 1b4f0a409db397bcf877f36edcf15ed16e801d96. Reason for revert: FastDataInput/Output is hidden and cannot be used in mainline module. Test: TH Bug: 204830222 Change-Id: I8cfa435bb6233818adb9cc99dadeeb06a03443d5 --- .../src/android/net/NetworkStatsCollection.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 7935d28f30..9f9d73f888 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -46,8 +46,6 @@ import android.util.Range; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.FastDataInput; -import com.android.internal.util.FastDataOutput; import com.android.internal.util.FileRotator; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkStatsUtils; @@ -58,6 +56,7 @@ import java.io.BufferedInputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutput; +import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -83,9 +82,6 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** File header magic number: "ANET" */ private static final int FILE_MAGIC = 0x414E4554; - /** Default buffer size from BufferedInputStream */ - private static final int BUFFER_SIZE = 8192; - private static final int VERSION_NETWORK_INIT = 1; private static final int VERSION_UID_INIT = 1; @@ -439,8 +435,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W @Override public void read(InputStream in) throws IOException { - final FastDataInput dataIn = new FastDataInput(in, BUFFER_SIZE); - read(dataIn); + read((DataInput) new DataInputStream(in)); } private void read(DataInput in) throws IOException { @@ -479,9 +474,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W @Override public void write(OutputStream out) throws IOException { - final FastDataOutput dataOut = new FastDataOutput(out, BUFFER_SIZE); - write(dataOut); - dataOut.flush(); + write((DataOutput) new DataOutputStream(out)); + out.flush(); } private void write(DataOutput out) throws IOException { From 638f6667e943d90c181aceb44d5b73dd138681c0 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 24 Dec 2021 02:00:54 +0000 Subject: [PATCH 763/881] [MS35] Remove getNetwork[Total|Uid]Bytes dependencies from NPMS 1. getNetworkTotalBytes was used for querying overall statistics that regards of the NetworkPolicy to calculate the remaining data warning/limit quota that needs to be send to the lower layer. 2. getNetworkUidBytes was used for querying overall statistics of apps to find out the rapid traffic that caused by an abnormal app behavior. This change replaces getNetwork[Total|Uid]Bytes with APIs that are about to expose, and introduces a dependencies object for better unit test injection. Test: atest NetworkPolicyManagerServiceTest Bug: 204830222 Change-Id: I802d2316fb22886e951456df0941c09176c981f8 --- .../src/android/app/usage/NetworkStatsManager.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index cc7b2a5a30..f0af42d308 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -142,7 +142,15 @@ public class NetworkStatsManager { setAugmentWithSubscriptionPlan(true); } - /** @hide */ + /** + * Set poll on open flag to indicate the poll is needed before service gets statistics + * result. This is default enabled. However, for any non-privileged caller, the poll might + * be omitted in case of rate limiting. + * + * @param pollOnOpen true if poll is needed. + * @hide + */ + // @SystemApi(client = MODULE_LIBRARIES) public void setPollOnOpen(boolean pollOnOpen) { if (pollOnOpen) { mFlags |= FLAG_POLL_ON_OPEN; From 3715b37705e80920cd5e9e6135a4c2f69c0325bb Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 4 Jan 2022 03:55:28 +0000 Subject: [PATCH 764/881] [MS36] Remove unused getNetwork[Total|Uid]Bytes Since the usages are all removed, clean up the unused code accordingly. Test: TH Bug: 204830222 Change-Id: Ia6863a7098632580b411bd79550754e511ea2543 --- .../server/net/NetworkStatsService.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index b99675e239..dadc51883c 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1690,26 +1690,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal { - @Override - public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { - Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes"); - try { - return NetworkStatsService.this.getNetworkTotalBytes(template, start, end); - } finally { - Trace.traceEnd(TRACE_TAG_NETWORK); - } - } - - @Override - public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { - Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes"); - try { - return NetworkStatsService.this.getNetworkUidBytes(template, start, end); - } finally { - Trace.traceEnd(TRACE_TAG_NETWORK); - } - } - @Override public void setUidForeground(int uid, boolean uidForeground) { NetworkStatsService.this.setUidForeground(uid, uidForeground); From 4161a040337f7b46eadd5be332c727ea9d343b20 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 4 Jan 2022 07:24:40 +0000 Subject: [PATCH 765/881] [MS37] Replace NetworkStatsManagerInternal usages in NPMS This is done by: 1. Add NetworkStatsManagerInternal APIs directly from NetworkStatsManager, these APIs are needed by NPMS. 2. Replace all usages with these APIs. 3. Delete NetworkStatsManagerInternal implementation. Test: atest FrameworksNetTests NetworkPolicyManagerServiceTest Bug: 204830222 CTS-Coverage-Bug: 213124616 Change-Id: If51b6676915e3a0a8a9f95221d735306911442fc --- .../app/usage/NetworkStatsManager.java | 70 +++++++++++++++++++ .../src/android/net/INetworkStatsService.aidl | 12 ++++ .../server/net/NetworkStatsService.java | 52 +++++--------- 3 files changed, 100 insertions(+), 34 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index f0af42d308..f74edb1a01 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -871,4 +871,74 @@ public class NetworkStatsManager { return msg.getData().getParcelable(key); } } + + /** + * Mark given UID as being in foreground for stats purposes. + * + * @hide + */ + // @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void setUidForeground(int uid, boolean uidForeground) { + try { + mService.setUidForeground(uid, uidForeground); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Advise persistence threshold; may be overridden internally. + * + * @hide + */ + // @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void advisePersistThreshold(long thresholdBytes) { + try { + mService.advisePersistThreshold(thresholdBytes); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Force update of statistics. + * + * @hide + */ + // @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void forceUpdate() { + try { + mService.forceUpdate(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set the warning and limit to all registered custom network stats providers. + * Note that invocation of any interface will be sent to all providers. + * + * @hide + */ + // @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) + public void setStatsProviderWarningAndLimitAsync(@NonNull String iface, long warning, + long limit) { + try { + mService.setStatsProviderWarningAndLimitAsync(iface, warning, limit); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/framework-t/src/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl index 12937b5cb2..a4babb543d 100644 --- a/framework-t/src/android/net/INetworkStatsService.aidl +++ b/framework-t/src/android/net/INetworkStatsService.aidl @@ -94,4 +94,16 @@ interface INetworkStatsService { /** Registers a network stats provider */ INetworkStatsProviderCallback registerNetworkStatsProvider(String tag, in INetworkStatsProvider provider); + + /** Mark given UID as being in foreground for stats purposes. */ + void setUidForeground(int uid, boolean uidForeground); + + /** Advise persistence threshold; may be overridden internally. */ + void advisePersistThreshold(long thresholdBytes); + + /** + * Set the warning and limit to all registered custom network stats providers. + * Note that invocation of any interface will be sent to all providers. + */ + void setStatsProviderWarningAndLimitAsync(String iface, long warning, long limit); } diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index dadc51883c..4cc18af466 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -430,7 +430,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); - service.registerLocalService(); return service; } @@ -511,11 +510,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - private void registerLocalService() { - LocalServices.addService(NetworkStatsManagerInternal.class, - new NetworkStatsManagerInternalImpl()); - } - /** * Observer that watches for {@link INetdUnsolicitedEventListener} alerts. */ @@ -1006,7 +1000,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @VisibleForTesting - void setUidForeground(int uid, boolean uidForeground) { + public void setUidForeground(int uid, boolean uidForeground) { + PermissionUtils.enforceNetworkStackPermission(mContext); synchronized (mStatsLock) { final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT; final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT); @@ -1042,7 +1037,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void forceUpdate() { - mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); + PermissionUtils.enforceNetworkStackPermission(mContext); final long token = Binder.clearCallingIdentity(); try { @@ -1052,7 +1047,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - private void advisePersistThreshold(long thresholdBytes) { + /** Advise persistence threshold; may be overridden internally. */ + public void advisePersistThreshold(long thresholdBytes) { + PermissionUtils.enforceNetworkStackPermission(mContext); // clamp threshold into safe range mPersistThreshold = NetworkStatsUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES); @@ -1689,32 +1686,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub { removeUidsLocked(CollectionUtils.toIntArray(uids)); } - private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal { - @Override - public void setUidForeground(int uid, boolean uidForeground) { - NetworkStatsService.this.setUidForeground(uid, uidForeground); - } - - @Override - public void advisePersistThreshold(long thresholdBytes) { - NetworkStatsService.this.advisePersistThreshold(thresholdBytes); - } - - @Override - public void forceUpdate() { - NetworkStatsService.this.forceUpdate(); - } - - @Override - public void setStatsProviderWarningAndLimitAsync( - @NonNull String iface, long warning, long limit) { - if (LOGV) { - Log.v(TAG, "setStatsProviderWarningAndLimitAsync(" - + iface + "," + warning + "," + limit + ")"); - } - invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, - warning, limit)); + /** + * Set the warning and limit to all registered custom network stats providers. + * Note that invocation of any interface will be sent to all providers. + */ + public void setStatsProviderWarningAndLimitAsync( + @NonNull String iface, long warning, long limit) { + PermissionUtils.enforceNetworkStackPermission(mContext); + if (LOGV) { + Log.v(TAG, "setStatsProviderWarningAndLimitAsync(" + + iface + "," + warning + "," + limit + ")"); } + invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, + warning, limit)); } @Override From 3b5180d80e056bc17b69ab2342835a97aefd6604 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 7 Jan 2022 23:43:09 +0800 Subject: [PATCH 766/881] Add getter for the fields of NetworkStats.Entry NetworkStats is going to be moved into mainline module and there're some external callers have dependencies on it. To replace those hidden APIs with formal APIs, NetworkStats needs to expose some getter methods to eliminate the dependencies on hidden API. Bug: 210073043 Bug: 204830222 CTS-Coverage-Bug: 214881138 Test: FrameworksNetTests Change-Id: I85bb6b27bd17bad16c9693d95b569d0ec5fbb785 --- framework-t/src/android/net/NetworkStats.java | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java index b00fea4de2..9d532e7929 100644 --- a/framework-t/src/android/net/NetworkStats.java +++ b/framework-t/src/android/net/NetworkStats.java @@ -383,6 +383,95 @@ public final class NetworkStats implements Parcelable { this.operations += another.operations; } + /** + * @return interface name of this entry. + * @hide + */ + @Nullable public String getIface() { + return iface; + } + + /** + * @return the uid of this entry. + */ + public int getUid() { + return uid; + } + + /** + * @return the set state of this entry. Should be one of the following + * values: {@link #SET_DEFAULT}, {@link #SET_FOREGROUND}. + */ + @State public int getSet() { + return set; + } + + /** + * @return the tag value of this entry. + */ + public int getTag() { + return tag; + } + + /** + * @return the metered state. Should be one of the following + * values: {link #METERED_YES}, {link #METERED_NO}. + */ + @Meteredness public int getMetered() { + return metered; + } + + /** + * @return the roaming state. Should be one of the following + * values: {link #ROAMING_YES}, {link #ROAMING_NO}. + */ + @Roaming public int getRoaming() { + return roaming; + } + + /** + * @return the default network state. Should be one of the following + * values: {link #DEFAULT_NETWORK_YES}, {link #DEFAULT_NETWORK_NO}. + */ + @DefaultNetwork public int getDefaultNetwork() { + return defaultNetwork; + } + + /** + * @return the number of received bytes. + */ + public long getRxBytes() { + return rxBytes; + } + + /** + * @return the number of received packets. + */ + public long getRxPackets() { + return rxPackets; + } + + /** + * @return the number of transmitted bytes. + */ + public long getTxBytes() { + return txBytes; + } + + /** + * @return the number of transmitted packets. + */ + public long getTxPackets() { + return txPackets; + } + + /** + * @return the count of network operations performed for this entry. + */ + public long getOperations() { + return operations; + } + @Override public String toString() { final StringBuilder builder = new StringBuilder(); @@ -593,7 +682,7 @@ public final class NetworkStats implements Parcelable { * @hide */ @UnsupportedAppUsage - public Entry getValues(int i, Entry recycle) { + public Entry getValues(int i, @Nullable Entry recycle) { final Entry entry = recycle != null ? recycle : new Entry(); entry.iface = iface[i]; entry.uid = uid[i]; From d3cb2bae4f11930a85294bcf0b320099de26557a Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 28 Dec 2021 16:18:43 +0000 Subject: [PATCH 767/881] [MS30] Remove ServiceManager#getService dependency Since TrafficStats is moving into the mainline module, ServiceManager#getService can no longer be accessed. This change use reflection to access getService, since there is no offical way to get the service binder, and TrafficStats is a static utility that doesn't have the context to invoke Context#getSystemService. This change also fixes minor lint errors. Test: atest CtsNetTestCases:TrafficStatsTest Bug: 204830222 Change-Id: I5caec42a71431b39f747fc791b8511d92e5cf7cc --- framework-t/src/android/net/TrafficStats.java | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java index d8feb88f0f..032bc3f402 100644 --- a/framework-t/src/android/net/TrafficStats.java +++ b/framework-t/src/android/net/TrafficStats.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -27,8 +28,8 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.media.MediaPlayer; import android.os.Build; +import android.os.IBinder; import android.os.RemoteException; -import android.os.ServiceManager; import com.android.server.NetworkManagementSocketTagger; @@ -36,6 +37,8 @@ import dalvik.system.SocketTagger; import java.io.FileDescriptor; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.DatagramSocket; import java.net.Socket; import java.net.SocketException; @@ -53,6 +56,7 @@ import java.net.SocketException; * use {@link NetworkStatsManager} instead. */ public class TrafficStats { + private static final String TAG = TrafficStats.class.getSimpleName(); /** * The return value to indicate that the device does not support the statistic. */ @@ -173,12 +177,25 @@ public class TrafficStats { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private synchronized static INetworkStatsService getStatsService() { if (sStatsService == null) { - sStatsService = INetworkStatsService.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); + sStatsService = getStatsBinder(); } return sStatsService; } + @Nullable + private static INetworkStatsService getStatsBinder() { + try { + final Method getServiceMethod = Class.forName("android.os.ServiceManager") + .getDeclaredMethod("getService", new Class[]{String.class}); + final IBinder binder = (IBinder) getServiceMethod.invoke( + null, Context.NETWORK_STATS_SERVICE); + return INetworkStatsService.Stub.asInterface(binder); + } catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException + | InvocationTargetException e) { + throw new NullPointerException("Cannot get INetworkStatsService: " + e); + } + } + /** * Snapshot of {@link NetworkStats} when the currently active profiling * session started, or {@code null} if no session active. From 69e220ccd89f6cfecd0fa2f7c406d332e6043313 Mon Sep 17 00:00:00 2001 From: lifr Date: Tue, 11 Jan 2022 11:17:36 +0800 Subject: [PATCH 768/881] [DU04-1]Remove NetworkPolicyManagerInternal from NetworkStatsService Expose system APIs for use by NetworkStatsService. Bug: 211843446 Test: atest NetworkStatsServiceTest NetworkPolicyManagerTest NetworkPolicyManagerServiceTest Change-Id: I56a066b7f4b4c2c8fefdd185c2e50de63b1e2629 --- service-t/src/com/android/server/net/NetworkStatsService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index e15acf3ef6..878056bbeb 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -156,7 +156,6 @@ import com.android.net.module.util.BinderUtils; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkStatsUtils; import com.android.net.module.util.PermissionUtils; -import com.android.server.LocalServices; import java.io.File; import java.io.FileDescriptor; @@ -2120,7 +2119,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void notifyWarningOrLimitReached() { Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); BinderUtils.withCleanCallingIdentity(() -> - mNetworkPolicyManager.onStatsProviderWarningOrLimitReached()); + mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached()); } @Override From 2d34f3e72930ea562ea9826f0e584b9b949c5c37 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 18 Jan 2022 02:46:23 +0000 Subject: [PATCH 769/881] [MS63.1] Remove TrafficStats.TAG_SYSTEM_DOWNLOAD dependency Replace with system Api. Test: TH Bug: 204830222 CTS-Coverage-Bug: 215043101 Change-Id: Ic14b26d2862f6fe8bee18fe0c9eaf183052452ee --- framework-t/src/android/net/TrafficStats.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java index 032bc3f402..1af32bf552 100644 --- a/framework-t/src/android/net/TrafficStats.java +++ b/framework-t/src/android/net/TrafficStats.java @@ -281,6 +281,18 @@ public class TrafficStats { setThreadStatsTag(TAG_SYSTEM_APP); } + /** + * Set active tag to use when accounting {@link Socket} traffic originating + * from the current thread. The tag used internally is well-defined to + * distinguish all download provider traffic. + * + * @hide + */ + @SystemApi + public static void setThreadStatsTagDownload() { + setThreadStatsTag(TAG_SYSTEM_DOWNLOAD); + } + /** * Get the active tag used when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. From 55b39355dd0bc40a84f9e19441e9bef9fa45f4f3 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Tue, 18 Jan 2022 04:49:55 +0000 Subject: [PATCH 770/881] Fix the Preconditions dependency in EthernetNetworkSpecifier. Ethernet service related files are going to be moved into Connectivity module. Replace the Preconditions class in the EthernetNetworkSpecifier, either add modules-utils-preconditions static lib dependency to fix it, however, notice that will result in the duplicate class import when moving ethernet stuff to p/m/Connectivity. Bug: 210586283 Test: atest FrameworksNetTests EthernetServiceTests Change-Id: I6163699be4126ef1b95dfb87ec9a6aba2c01195a --- framework-t/src/android/net/EthernetNetworkSpecifier.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework-t/src/android/net/EthernetNetworkSpecifier.java b/framework-t/src/android/net/EthernetNetworkSpecifier.java index 62c5761442..925d12b574 100644 --- a/framework-t/src/android/net/EthernetNetworkSpecifier.java +++ b/framework-t/src/android/net/EthernetNetworkSpecifier.java @@ -23,8 +23,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; -import com.android.internal.util.Preconditions; - import java.util.Objects; /** @@ -47,7 +45,9 @@ public final class EthernetNetworkSpecifier extends NetworkSpecifier implements * @param interfaceName Name of the ethernet interface the specifier refers to. */ public EthernetNetworkSpecifier(@NonNull String interfaceName) { - Preconditions.checkStringNotEmpty(interfaceName); + if (TextUtils.isEmpty(interfaceName)) { + throw new IllegalArgumentException(); + } mInterfaceName = interfaceName; } From ba8efd5c84dc025755ceb68d519f5a6429b137da Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 13 Jan 2022 15:54:41 +0000 Subject: [PATCH 771/881] [MS37.1] Expose APIs which is used by NPMS Test: TH Bug: 204830222 CTS-Coverage-Bug: 213124616 Change-Id: I16418791246b12fc3da7348ed36b58274e20db54 --- .../app/usage/NetworkStatsManager.java | 34 ++++++++++++++----- .../server/net/NetworkStatsService.java | 33 ++++++++++++------ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index f74edb1a01..d00de3679e 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -18,6 +18,7 @@ package android.app.usage; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -150,7 +151,13 @@ public class NetworkStatsManager { * @param pollOnOpen true if poll is needed. * @hide */ - // @SystemApi(client = MODULE_LIBRARIES) + // The system will ignore any non-default values for non-privileged + // processes, so processes that don't hold the appropriate permissions + // can make no use of this API. + @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean pollOnOpen) { if (pollOnOpen) { mFlags |= FLAG_POLL_ON_OPEN; @@ -877,7 +884,7 @@ public class NetworkStatsManager { * * @hide */ - // @SystemApi + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) @@ -890,17 +897,18 @@ public class NetworkStatsManager { } /** - * Advise persistence threshold; may be overridden internally. + * Set default value of global alert bytes, the value will be clamped to [128kB, 2MB]. * * @hide */ - // @SystemApi + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, - android.Manifest.permission.NETWORK_STACK}) - public void advisePersistThreshold(long thresholdBytes) { + Manifest.permission.NETWORK_STACK}) + public void setDefaultGlobalAlert(long alertBytes) { try { - mService.advisePersistThreshold(thresholdBytes); + // TODO: Sync internal naming with the API surface. + mService.advisePersistThreshold(alertBytes); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -911,7 +919,7 @@ public class NetworkStatsManager { * * @hide */ - // @SystemApi + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) @@ -927,9 +935,17 @@ public class NetworkStatsManager { * Set the warning and limit to all registered custom network stats providers. * Note that invocation of any interface will be sent to all providers. * + * Asynchronicity notes : because traffic may be happening on the device at the same time, it + * doesn't make sense to wait for the warning and limit to be set – a caller still wouldn't + * know when exactly it was effective. All that can matter is that it's done quickly. Also, + * this method can't fail, so there is no status to return. All providers will see the new + * values soon. + * As such, this method returns immediately and sends the warning and limit to all providers + * as soon as possible through a one-way binder call. + * * @hide */ - // @SystemApi + @SystemApi(client = MODULE_LIBRARIES) @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 4cc18af466..595f88d71e 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -707,12 +707,25 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return now - lastCallTime < POLL_RATE_LIMIT_MS; } - private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { + private int restrictFlagsForCaller(int flags) { + // All non-privileged callers are not allowed to turn off POLL_ON_OPEN. + final boolean isPrivileged = PermissionUtils.checkAnyPermissionOf(mContext, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK); + if (!isPrivileged) { + flags |= NetworkStatsManager.FLAG_POLL_ON_OPEN; + } + // Non-system uids are rate limited for POLL_ON_OPEN. final int callingUid = Binder.getCallingUid(); - final int usedFlags = isRateLimitedForPoll(callingUid) + flags = isRateLimitedForPoll(callingUid) ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN) : flags; - if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN + return flags; + } + + private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { + final int restrictedFlags = restrictFlagsForCaller(flags); + if ((restrictedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) { final long ident = Binder.clearCallingIdentity(); try { @@ -726,7 +739,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // for its lifetime; when caller closes only weak references remain. return new INetworkStatsSession.Stub() { - private final int mCallingUid = callingUid; + private final int mCallingUid = Binder.getCallingUid(); private final String mCallingPackage = callingPackage; private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel( callingPackage); @@ -760,21 +773,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDeviceSummaryForNetwork( NetworkTemplate template, long start, long end) { - return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel, - mCallingUid); + return internalGetSummaryForNetwork(template, restrictedFlags, start, end, + mAccessLevel, mCallingUid); } @Override public NetworkStats getSummaryForNetwork( NetworkTemplate template, long start, long end) { - return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel, - mCallingUid); + return internalGetSummaryForNetwork(template, restrictedFlags, start, end, + mAccessLevel, mCallingUid); } @Override public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { - return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel, - mCallingUid); + return internalGetHistoryForNetwork(template, restrictedFlags, fields, + mAccessLevel, mCallingUid); } @Override From 1cad2ea6518cda5bd7031c80b529c466674b98bc Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 14 Jan 2022 23:34:54 +0800 Subject: [PATCH 772/881] Have NetworkStats implements iterable Make NetworkStats be iterable and expose iterator as system API which is better than expose size() and getValues(). This API could be used by the caller who needs to get entry from NetworkStats. Bug: 210073043 CTS-Coverage-Bug: 215061403 Test: build, TH Change-Id: I6cb4c8f63d7067133f2722b2be7e16b4098a697d --- framework-t/src/android/net/NetworkStats.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java index 9d532e7929..9175809d9c 100644 --- a/framework-t/src/android/net/NetworkStats.java +++ b/framework-t/src/android/net/NetworkStats.java @@ -41,6 +41,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -57,7 +58,7 @@ import java.util.function.Predicate; */ // @NotThreadSafe @SystemApi -public final class NetworkStats implements Parcelable { +public final class NetworkStats implements Parcelable, Iterable { private static final String TAG = "NetworkStats"; /** @@ -677,6 +678,35 @@ public final class NetworkStats implements Parcelable { operations[i] = entry.operations; } + /** + * Iterate over Entry objects. + * + * Return an iterator of this object that will iterate through all contained Entry objects. + * + * This iterator does not support concurrent modification and makes no guarantee of fail-fast + * behavior. If any method that can mutate the contents of this object is called while + * iteration is in progress, either inside the loop or in another thread, then behavior is + * undefined. + * The remove() method is not implemented and will throw UnsupportedOperationException. + * @hide + */ + @SystemApi + @NonNull public Iterator iterator() { + return new Iterator() { + int mIndex = 0; + + @Override + public boolean hasNext() { + return mIndex < size; + } + + @Override + public Entry next() { + return getValues(mIndex++, null); + } + }; + } + /** * Return specific stats entry. * @hide From 172aa68e5dbf484c5a316b77bf47c20b3b03a21a Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 14 Dec 2021 23:09:55 +0800 Subject: [PATCH 773/881] Split out the nsd API surface and use framework-connectivity-tiramisu - Split out nsd APIs and hidden APIs to Connectivity module. - Keep the all files in f/b/packages/Connectivity-T and add framework-connectivity-tiramisu library on p/m/Connectivity. Then make framework to use this module library. - Remove NsdService from SystemServer which will register from ConnectivityServiceInitializer Bug: 206893064 Test: m online-sdk-dev-docs Test: atest FrameworksNetTests CtsNetTestCases CTS-Coverage-Bug: 207804007 Merged-In: I72c7de124b9cc53f2263bd452ecd5f39e88e485b Change-Id: I72c7de124b9cc53f2263bd452ecd5f39e88e485b --- framework-t/Sources.bp | 14 ++++++++++++-- service-t/Sources.bp | 12 +++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 90bb76a87d..d3d8bba16c 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -156,8 +156,18 @@ filegroup { ":framework-connectivity-ethernet-sources", ":framework-connectivity-ipsec-sources", ":framework-connectivity-netstats-sources", - ":framework-connectivity-nsd-sources", - ":framework-connectivity-tiramisu-internal-sources", ], visibility: ["//frameworks/base"], } + +filegroup { + name: "framework-connectivity-tiramisu-updatable-sources", + srcs: [ + ":framework-connectivity-nsd-sources", + ":framework-connectivity-tiramisu-internal-sources", + ], + visibility: [ + "//frameworks/base", + "//packages/modules/Connectivity:__subpackages__", + ], +} diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 97dfb64b33..b261e165a1 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -82,8 +82,18 @@ filegroup { ":services.connectivity-ethernet-sources", ":services.connectivity-ipsec-sources", ":services.connectivity-netstats-sources", - ":services.connectivity-nsd-sources", ], path: "src", visibility: ["//frameworks/base/services/core"], } + +filegroup { + name: "services.connectivity-tiramisu-updatable-sources", + srcs: [ + ":services.connectivity-nsd-sources", + ], + path: "src", + visibility: [ + "//packages/modules/Connectivity:__subpackages__", + ], +} From 504e9b3587010d4eb54687add3976f2920b6685b Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 19 Jan 2022 15:07:06 +0000 Subject: [PATCH 774/881] [MS64] Remove subscriberId and NetworkId in proto netstats.proto is about to move into mainline module. And it can no longer see privacy.proto definition. Thus, this change remove PII data that is not very useful when debugging and any reference to privacy.proto. Test: adb bugreport and check output at transponder Bug: 204830222 Change-Id: I755530f356d2c16b336d62785c4c17c557f792db --- framework-t/src/android/net/NetworkIdentity.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 8f1115e065..04d1d68851 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -160,11 +160,6 @@ public class NetworkIdentity implements Comparable { // Not dumping mSubType, subtypes are no longer supported. - if (mSubscriberId != null) { - proto.write(NetworkIdentityProto.SUBSCRIBER_ID, - NetworkIdentityUtils.scrubSubscriberId(mSubscriberId)); - } - proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId); proto.write(NetworkIdentityProto.ROAMING, mRoaming); proto.write(NetworkIdentityProto.METERED, mMetered); proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork); From e1a82896b6ed951e7277e970e17a7c8aeb2cb6a1 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Jan 2022 16:22:33 +0900 Subject: [PATCH 775/881] Replace runWithScissors with a custom implementation. This is not any better than the previous code though... But it should behave the same. Test: FrameworksNetTests Change-Id: Ia3d379681cb0f17dd5f86062b7cfe84f1547fadb --- .../src/com/android/server/ethernet/EthernetTracker.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 0b6547d145..53af955d69 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -34,6 +34,7 @@ import android.net.IpConfiguration.ProxySettings; import android.net.LinkAddress; import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; +import android.os.ConditionVariable; import android.os.Handler; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -662,7 +663,13 @@ public class EthernetTracker { } private void postAndWaitForRunnable(Runnable r) { - mHandler.runWithScissors(r, 2000L /* timeout */); + final ConditionVariable cv = new ConditionVariable(); + if (mHandler.post(() -> { + r.run(); + cv.open(); + })) { + cv.block(2000L); + } } void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { From 878641336d5e41fee220c11feb66a8ecae256d7c Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 20 Jan 2022 16:05:04 +0800 Subject: [PATCH 776/881] [DU05]Remove the android.provider.Settings.Global in NetworkStatsService Replace android.provider.Settings.Global methods that return the default value and hardcoding them inside the methods. Bug: 213329727 Test: atest NetworkStatsServiceTest Change-Id: I51d686222f983c8deb71d4b32f9e443e87a5e53e --- .../server/net/NetworkStatsService.java | 73 +++++-------------- 1 file changed, 20 insertions(+), 53 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index e15acf3ef6..a0ee1b6a40 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -47,23 +47,6 @@ import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.TrafficStats.UID_TETHERING; import static android.net.TrafficStats.UNSUPPORTED; import static android.os.Trace.TRACE_TAG_NETWORK; -import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; -import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED; -import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; -import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; -import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; -import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE; -import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES; -import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL; -import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED; -import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION; -import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE; -import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES; -import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE; -import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; -import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; -import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; -import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; @@ -156,7 +139,6 @@ import com.android.net.module.util.BinderUtils; import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkStatsUtils; import com.android.net.module.util.PermissionUtils; -import com.android.server.LocalServices; import java.io.File; import java.io.FileDescriptor; @@ -217,6 +199,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int LOG_TAG_NETSTATS_MOBILE_SAMPLE = 51100; private static final int LOG_TAG_NETSTATS_WIFI_SAMPLE = 51101; + // TODO: Replace the hardcoded string and move it into ConnectivitySettingsManager. + private static final String NETSTATS_COMBINE_SUBTYPE_ENABLED = + "netstats_combine_subtype_enabled"; + private final Context mContext; private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; @@ -428,7 +414,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsService service = new NetworkStatsService(context, INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)), alarmManager, wakeLock, getDefaultClock(), - new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd), + new DefaultNetworkStatsSettings(), new NetworkStatsFactory(netd), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -591,13 +577,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mSettings.getPollInterval(), pollIntent); mContentResolver.registerContentObserver(Settings.Global - .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED), + .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED), false /* notifyForDescendants */, mContentObserver); // Post a runnable on handler thread to call onChange(). It's for getting current value of // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes. mHandler.post(() -> mContentObserver.onChange(false, Settings.Global - .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED))); + .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED))); registerGlobalAlert(); } @@ -2179,24 +2165,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * {@link android.provider.Settings.Global}. */ private static class DefaultNetworkStatsSettings implements NetworkStatsSettings { - private final ContentResolver mResolver; - - public DefaultNetworkStatsSettings(Context context) { - mResolver = Objects.requireNonNull(context.getContentResolver()); - // TODO: adjust these timings for production builds - } - - private long getGlobalLong(String name, long def) { - return Settings.Global.getLong(mResolver, name, def); - } - private boolean getGlobalBoolean(String name, boolean def) { - final int defInt = def ? 1 : 0; - return Settings.Global.getInt(mResolver, name, defInt) != 0; - } + DefaultNetworkStatsSettings() {} @Override public long getPollInterval() { - return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); + return 30 * MINUTE_IN_MILLIS; } @Override public long getPollDelay() { @@ -2204,25 +2177,23 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override public long getGlobalAlertBytes(long def) { - return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def); + return def; } @Override public boolean getSampleEnabled() { - return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true); + return true; } @Override public boolean getAugmentEnabled() { - return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true); + return true; } @Override public boolean getCombineSubtypeEnabled() { - return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false); + return false; } @Override public Config getDevConfig() { - return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), - getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), - getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS)); + return new Config(HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS); } @Override public Config getXtConfig() { @@ -2230,31 +2201,27 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override public Config getUidConfig() { - return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), - getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS), - getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS)); + return new Config(2 * HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS); } @Override public Config getUidTagConfig() { - return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), - getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS), - getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS)); + return new Config(2 * HOUR_IN_MILLIS, 5 * DAY_IN_MILLIS, 15 * DAY_IN_MILLIS); } @Override public long getDevPersistBytes(long def) { - return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def); + return def; } @Override public long getXtPersistBytes(long def) { - return getDevPersistBytes(def); + return def; } @Override public long getUidPersistBytes(long def) { - return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def); + return def; } @Override public long getUidTagPersistBytes(long def) { - return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def); + return def; } } From bb459aeababb9bdbc50d4325e178919dba9ec210 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 5 Jan 2022 13:45:29 +0000 Subject: [PATCH 777/881] [MS41.1] Prepare for APIs for querying usage with template This CL includes: 1. Prepare for queryDetailsForDevice which allows callers to query history of networks that matches the given template. 2. Prepare for queryDetailsForUidTagState, which allows callers to query history uid stats with the given template, uid and other conditions. 3. Enforce fine location permission if the caller is querying data usage with a template which contains wifi network keys. Test: atest NetworkStatsServiceTest NetworkStatsManagerTest Bug: 204830222 Bug: 200768422 Change-Id: I6783d6bfd6e075e0b3ec8a3c91836377f1d71c7a --- .../src/android/app/usage/NetworkStats.java | 16 +++- .../app/usage/NetworkStatsManager.java | 85 +++++++++++++++++-- .../src/android/net/INetworkStatsSession.aidl | 5 ++ .../server/net/NetworkStatsService.java | 62 ++++++++++++-- 4 files changed, 153 insertions(+), 15 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStats.java b/framework-t/src/android/app/usage/NetworkStats.java index d33666d744..2b6570a6ec 100644 --- a/framework-t/src/android/app/usage/NetworkStats.java +++ b/framework-t/src/android/app/usage/NetworkStats.java @@ -556,7 +556,7 @@ public final class NetworkStats implements AutoCloseable { /** * Collects history results for uid and resets history enumeration index. */ - void startHistoryEnumeration(int uid, int tag, int state) { + void startHistoryUidEnumeration(int uid, int tag, int state) { mHistory = null; try { mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid, @@ -570,6 +570,20 @@ public final class NetworkStats implements AutoCloseable { mEnumerationIndex = 0; } + /** + * Collects history results for network and resets history enumeration index. + */ + void startHistoryDeviceEnumeration() { + try { + mHistory = mSession.getHistoryIntervalForNetwork( + mTemplate, NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp); + } catch (RemoteException e) { + Log.w(TAG, e); + mHistory = null; + } + mEnumerationIndex = 0; + } + /** * Starts uid enumeration for current user. * @throws RemoteException diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index d00de3679e..4b906c9089 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -433,6 +433,42 @@ public class NetworkStatsManager { return null; // To make the compiler happy. } + /** + * Query usage statistics details for networks matching a given {@link NetworkTemplate}. + * + * Result is not aggregated over time. This means buckets' start and + * end timestamps will be between 'startTime' and 'endTime' parameters. + *

Only includes buckets whose entire time period is included between + * startTime and endTime. Doesn't interpolate or return partial buckets. + * Since bucket length is in the order of hours, this + * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. + * + * @param template Template used to match networks. See {@link NetworkTemplate}. + * @param startTime Start of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @return Statistics which is described above. + * @hide + */ + @NonNull + // @SystemApi(client = MODULE_LIBRARIES) + @WorkerThread + public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template, + long startTime, long endTime) { + try { + final NetworkStats result = + new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); + result.startHistoryDeviceEnumeration(); + return result; + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + + return null; // To make the compiler happy. + } + /** * Query network usage statistics details for a given uid. * This may take a long time, and apps should avoid calling this on their main thread. @@ -499,7 +535,8 @@ public class NetworkStatsManager { * @param endTime End of period. Defined in terms of "Unix time", see * {@link java.lang.System#currentTimeMillis}. * @param uid UID of app - * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags. + * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data + * across all the tags. * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate * traffic from all states. * @return Statistics object or null if an error happened during statistics collection. @@ -514,21 +551,51 @@ public class NetworkStatsManager { return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state); } - /** @hide */ - public NetworkStats queryDetailsForUidTagState(NetworkTemplate template, + /** + * Query network usage statistics details for a given template, uid, tag, and state. + * + * Only usable for uids belonging to calling user. Result is not aggregated over time. + * This means buckets' start and end timestamps are going to be between 'startTime' and + * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag + * the same as the 'tag' parameter, and the state the same as the 'state' parameter. + * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL}, + * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and + * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. + *

Only includes buckets that atomically occur in the inclusive time range. Doesn't + * interpolate across partial buckets. Since bucket length is in the order of hours, this + * method cannot be used to measure data usage on a fine grained time scale. + * This may take a long time, and apps should avoid calling this on their main thread. + * + * @param template Template used to match networks. See {@link NetworkTemplate}. + * @param startTime Start of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @param endTime End of period, in milliseconds since the Unix epoch, see + * {@link java.lang.System#currentTimeMillis}. + * @param uid UID of app + * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data + * across all the tags. + * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate + * traffic from all states. + * @return Statistics which is described above. + * @hide + */ + @NonNull + // @SystemApi(client = MODULE_LIBRARIES) + @WorkerThread + public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template, long startTime, long endTime, int uid, int tag, int state) throws SecurityException { - - NetworkStats result; try { - result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); - result.startHistoryEnumeration(uid, tag, state); + final NetworkStats result = new NetworkStats( + mContext, template, mFlags, startTime, endTime, mService); + result.startHistoryUidEnumeration(uid, tag, state); + return result; } catch (RemoteException e) { Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag + " state=" + state, e); - return null; + e.rethrowFromSystemServer(); } - return result; + return null; // To make the compiler happy. } /** diff --git a/framework-t/src/android/net/INetworkStatsSession.aidl b/framework-t/src/android/net/INetworkStatsSession.aidl index babe0bfb97..ab70be826f 100644 --- a/framework-t/src/android/net/INetworkStatsSession.aidl +++ b/framework-t/src/android/net/INetworkStatsSession.aidl @@ -32,6 +32,11 @@ interface INetworkStatsSession { /** Return historical network layer stats for traffic that matches template. */ @UnsupportedAppUsage NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields); + /** + * Return historical network layer stats for traffic that matches template, start and end + * timestamp. + */ + NetworkStatsHistory getHistoryIntervalForNetwork(in NetworkTemplate template, int fields, long start, long end); /** * Return network layer usage summary per UID for traffic that matches template. diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 0abc52309a..a0710f77b4 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -154,6 +154,7 @@ import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.BestClock; import com.android.net.module.util.BinderUtils; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.LocationPermissionChecker; import com.android.net.module.util.NetworkStatsUtils; import com.android.net.module.util.PermissionUtils; @@ -365,6 +366,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; + @NonNull + private final LocationPermissionChecker mLocationPermissionChecker; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -461,6 +465,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContentResolver = mContext.getContentResolver(); mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, mNetworkStatsSubscriptionsMonitor); + mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext); } /** @@ -508,6 +513,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; } + + /** + * @see LocationPermissionChecker + */ + public LocationPermissionChecker makeLocationPermissionChecker(final Context context) { + return new LocationPermissionChecker(context); + } } /** @@ -773,6 +785,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getDeviceSummaryForNetwork( NetworkTemplate template, long start, long end) { + enforceTemplatePermissions(template, callingPackage); return internalGetSummaryForNetwork(template, restrictedFlags, start, end, mAccessLevel, mCallingUid); } @@ -780,19 +793,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getSummaryForNetwork( NetworkTemplate template, long start, long end) { + enforceTemplatePermissions(template, callingPackage); return internalGetSummaryForNetwork(template, restrictedFlags, start, end, mAccessLevel, mCallingUid); } + // TODO: Remove this after all callers are removed. @Override public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { + enforceTemplatePermissions(template, callingPackage); return internalGetHistoryForNetwork(template, restrictedFlags, fields, - mAccessLevel, mCallingUid); + mAccessLevel, mCallingUid, Long.MIN_VALUE, Long.MAX_VALUE); + } + + @Override + public NetworkStatsHistory getHistoryIntervalForNetwork(NetworkTemplate template, + int fields, long start, long end) { + enforceTemplatePermissions(template, callingPackage); + // TODO(b/200768422): Redact returned history if the template is location + // sensitive but the caller is not privileged. + return internalGetHistoryForNetwork(template, restrictedFlags, fields, + mAccessLevel, mCallingUid, start, end); } @Override public NetworkStats getSummaryForAllUid( NetworkTemplate template, long start, long end, boolean includeTags) { + enforceTemplatePermissions(template, callingPackage); try { final NetworkStats stats = getUidComplete() .getSummary(template, start, end, mAccessLevel, mCallingUid); @@ -810,6 +837,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getTaggedSummaryForAllUid( NetworkTemplate template, long start, long end) { + enforceTemplatePermissions(template, callingPackage); try { final NetworkStats tagStats = getUidTagComplete() .getSummary(template, start, end, mAccessLevel, mCallingUid); @@ -822,6 +850,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStatsHistory getHistoryForUid( NetworkTemplate template, int uid, int set, int tag, int fields) { + enforceTemplatePermissions(template, callingPackage); // NOTE: We don't augment UID-level statistics if (tag == TAG_NONE) { return getUidComplete().getHistory(template, null, uid, set, tag, fields, @@ -836,6 +865,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public NetworkStatsHistory getHistoryIntervalForUid( NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end) { + enforceTemplatePermissions(template, callingPackage); + // TODO(b/200768422): Redact returned history if the template is location + // sensitive but the caller is not privileged. // NOTE: We don't augment UID-level statistics if (tag == TAG_NONE) { return getUidComplete().getHistory(template, null, uid, set, tag, fields, @@ -857,6 +889,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { }; } + private void enforceTemplatePermissions(@NonNull NetworkTemplate template, + @NonNull String callingPackage) { + // For a template with wifi network keys, it is possible for a malicious + // client to track the user locations via querying data usage. Thus, enforce + // fine location permission check. + if (!template.getWifiNetworkKeys().isEmpty()) { + final boolean canAccessFineLocation = mLocationPermissionChecker + .checkCallersLocationPermission(callingPackage, + null /* featureId */, + Binder.getCallingUid(), + false /* coarseForTargetSdkLessThanQ */, + null /* message */); + if (!canAccessFineLocation) { + throw new SecurityException("Access fine location is required when querying" + + " with wifi network keys, make sure the app has the necessary" + + "permissions and the location toggle is on."); + } + } + } + private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) { return NetworkStatsAccess.checkAccessLevel( mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage); @@ -893,7 +945,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL, - accessLevel, callingUid); + accessLevel, callingUid, start, end); final long now = System.currentTimeMillis(); final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); @@ -910,14 +962,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * appropriate. */ private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, - int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) { + int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid, + long start, long end) { // We've been using pure XT stats long enough that we no longer need to // splice DEV and XT together. final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags); synchronized (mStatsLock) { return mXtStatsCached.getHistory(template, augmentPlan, - UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE, - accessLevel, callingUid); + UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid); } } From 84316eb4b62ab173213cccbaf030ccc62b821098 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 7 Jan 2022 14:46:26 +0000 Subject: [PATCH 778/881] [MS45] Expose SystemApis to query summary and history with template This includes: 1. queryDetailsForDevice: get history of network stats that matches the given template. 2. querySummaryForDevice: similar to the above one, but the result is aggregated over time. 3. queryDetailsForUidTagState: get history of uid stats that matches the given template, uid, tag and other conditions. 4. querySummary: similar to the above one, but the result is aggregated over time. 5. queryTaggedSummary: similar to the above one, but only return tagged data. Test: TH Bug: 204830222 Change-Id: Ic18010822a33e340b954e9c53dc515f3b6224d6d --- .../android/app/usage/NetworkStatsManager.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 4b906c9089..903983da07 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -211,9 +211,10 @@ public class NetworkStatsManager { */ @NonNull @WorkerThread - // @SystemApi(client = MODULE_LIBRARIES) + @SystemApi(client = MODULE_LIBRARIES) public Bucket querySummaryForDevice(@NonNull NetworkTemplate template, long startTime, long endTime) { + Objects.requireNonNull(template); try { NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); @@ -385,10 +386,11 @@ public class NetworkStatsManager { * @hide */ @NonNull - // @SystemApi(client = MODULE_LIBRARIES) + @SystemApi(client = MODULE_LIBRARIES) @WorkerThread public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime, long endTime) throws SecurityException { + Objects.requireNonNull(template); try { NetworkStats result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); @@ -418,10 +420,11 @@ public class NetworkStatsManager { * @hide */ @NonNull - // @SystemApi(client = MODULE_LIBRARIES) + @SystemApi(client = MODULE_LIBRARIES) @WorkerThread public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime, long endTime) throws SecurityException { + Objects.requireNonNull(template); try { NetworkStats result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); @@ -453,10 +456,11 @@ public class NetworkStatsManager { * @hide */ @NonNull - // @SystemApi(client = MODULE_LIBRARIES) + @SystemApi(client = MODULE_LIBRARIES) @WorkerThread public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template, long startTime, long endTime) { + Objects.requireNonNull(template); try { final NetworkStats result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService); @@ -580,10 +584,11 @@ public class NetworkStatsManager { * @hide */ @NonNull - // @SystemApi(client = MODULE_LIBRARIES) + @SystemApi(client = MODULE_LIBRARIES) @WorkerThread public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template, long startTime, long endTime, int uid, int tag, int state) throws SecurityException { + Objects.requireNonNull(template); try { final NetworkStats result = new NetworkStats( mContext, template, mFlags, startTime, endTime, mService); From a8dc50de05a445adf6d79c66f1108a7804b073a4 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Sun, 16 Jan 2022 11:04:16 +0000 Subject: [PATCH 779/881] [MS57.1] Prepare APIs for data migration utility This includes: 1. Move PREFIX_* constants to NetworkStatsManager to expose in later changes. 2. Rename networkId to wifiNetworkKey. 3. Rename subType to ratType. 4. Replace SUBTYPE_COMBINED with NETWORK_TYPE_ALL 5. Fix lint errors when exposing system api. Test: TH Bug: 204830222 Change-Id: I2b7c34958bc59c3225c96f12abba008b83101585 --- .../app/usage/NetworkStatsManager.java | 13 +++ .../src/android/net/NetworkIdentity.java | 96 ++++++++++++------- .../src/android/net/NetworkIdentitySet.java | 38 ++++++-- .../android/net/NetworkStatsCollection.java | 71 ++++++++++++-- .../src/android/net/NetworkStatsHistory.java | 54 ++++++++++- .../src/android/net/NetworkTemplate.java | 30 +++--- .../server/net/NetworkStatsService.java | 28 +++--- 7 files changed, 245 insertions(+), 85 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 903983da07..8d93354ea9 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -125,6 +125,19 @@ public class NetworkStatsManager { private final Context mContext; private final INetworkStatsService mService; + /** + * Type constants for reading different types of Data Usage. + * @hide + */ + // @SystemApi(client = MODULE_LIBRARIES) + public static final String PREFIX_DEV = "dev"; + /** @hide */ + public static final String PREFIX_XT = "xt"; + /** @hide */ + public static final String PREFIX_UID = "uid"; + /** @hide */ + public static final String PREFIX_UID_TAG = "uid_tag"; + /** @hide */ public static final int FLAG_POLL_ON_OPEN = 1 << 0; /** @hide */ diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 04d1d68851..097b9bea90 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -17,12 +17,15 @@ package android.net; import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; import android.service.NetworkIdentityProto; -import android.telephony.Annotation.NetworkType; +import android.telephony.Annotation; +import android.telephony.TelephonyManager; import android.util.proto.ProtoOutputStream; import com.android.net.module.util.NetworkCapabilitiesUtils; @@ -37,9 +40,13 @@ import java.util.Objects; * * @hide */ +// @SystemApi(client = MODULE_LIBRARIES) public class NetworkIdentity implements Comparable { private static final String TAG = "NetworkIdentity"; + /** @hide */ + // TODO: Remove this after migrating all callers to use + // {@link NetworkTemplate#NETWORK_TYPE_ALL} instead. public static final int SUBTYPE_COMBINED = -1; /** @@ -59,21 +66,22 @@ public class NetworkIdentity implements Comparable { public static final int OEM_PRIVATE = 0x2; final int mType; - final int mSubType; + final int mRatType; final String mSubscriberId; - final String mNetworkId; + final String mWifiNetworkKey; final boolean mRoaming; final boolean mMetered; final boolean mDefaultNetwork; final int mOemManaged; + /** @hide */ public NetworkIdentity( - int type, int subType, String subscriberId, String networkId, boolean roaming, - boolean metered, boolean defaultNetwork, int oemManaged) { + int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey, + boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged) { mType = type; - mSubType = subType; + mRatType = ratType; mSubscriberId = subscriberId; - mNetworkId = networkId; + mWifiNetworkKey = wifiNetworkKey; mRoaming = roaming; mMetered = metered; mDefaultNetwork = defaultNetwork; @@ -82,7 +90,7 @@ public class NetworkIdentity implements Comparable { @Override public int hashCode() { - return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered, + return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered, mDefaultNetwork, mOemManaged); } @@ -90,9 +98,9 @@ public class NetworkIdentity implements Comparable { public boolean equals(@Nullable Object obj) { if (obj instanceof NetworkIdentity) { final NetworkIdentity ident = (NetworkIdentity) obj; - return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming + return mType == ident.mType && mRatType == ident.mRatType && mRoaming == ident.mRoaming && Objects.equals(mSubscriberId, ident.mSubscriberId) - && Objects.equals(mNetworkId, ident.mNetworkId) + && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey) && mMetered == ident.mMetered && mDefaultNetwork == ident.mDefaultNetwork && mOemManaged == ident.mOemManaged; @@ -104,18 +112,18 @@ public class NetworkIdentity implements Comparable { public String toString() { final StringBuilder builder = new StringBuilder("{"); builder.append("type=").append(mType); - builder.append(", subType="); - if (mSubType == SUBTYPE_COMBINED) { + builder.append(", ratType="); + if (mRatType == NETWORK_TYPE_ALL) { builder.append("COMBINED"); } else { - builder.append(mSubType); + builder.append(mRatType); } if (mSubscriberId != null) { builder.append(", subscriberId=") .append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId)); } - if (mNetworkId != null) { - builder.append(", networkId=").append(mNetworkId); + if (mWifiNetworkKey != null) { + builder.append(", wifiNetworkKey=").append(mWifiNetworkKey); } if (mRoaming) { builder.append(", ROAMING"); @@ -153,12 +161,13 @@ public class NetworkIdentity implements Comparable { } } + /** @hide */ public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); proto.write(NetworkIdentityProto.TYPE, mType); - // Not dumping mSubType, subtypes are no longer supported. + // TODO: dump mRatType as well. proto.write(NetworkIdentityProto.ROAMING, mRoaming); proto.write(NetworkIdentityProto.METERED, mMetered); @@ -168,50 +177,68 @@ public class NetworkIdentity implements Comparable { proto.end(start); } + /** @hide */ public int getType() { return mType; } - public int getSubType() { - return mSubType; + /** @hide */ + public int getRatType() { + return mRatType; } + /** @hide */ public String getSubscriberId() { return mSubscriberId; } - public String getNetworkId() { - return mNetworkId; + /** @hide */ + public String getWifiNetworkKey() { + return mWifiNetworkKey; } + /** @hide */ public boolean getRoaming() { return mRoaming; } + /** @hide */ public boolean getMetered() { return mMetered; } + /** @hide */ public boolean getDefaultNetwork() { return mDefaultNetwork; } + /** @hide */ public int getOemManaged() { return mOemManaged; } /** - * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and - * {@code subType}, assuming that any mobile networks are using the current IMSI. - * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_* - * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not. + * Assemble a {@link NetworkIdentity} from the passed arguments. + * + * This methods builds an identity based on the capabilities of the network in the + * snapshot and other passed arguments. The identity is used as a key to record data usage. + * + * @param snapshot the snapshot of network state. See {@link NetworkStateSnapshot}. + * @param defaultNetwork whether the network is a default network. + * @param ratType the Radio Access Technology(RAT) type of the network. Or + * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable. + * See {@code TelephonyManager.NETWORK_TYPE_*}. + * @hide */ + // TODO: Remove this after all callers are migrated to use new Api. + @NonNull public static NetworkIdentity buildNetworkIdentity(Context context, - NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) { + @NonNull NetworkStateSnapshot snapshot, + boolean defaultNetwork, @Annotation.NetworkType int ratType) { final int legacyType = snapshot.getLegacyType(); final String subscriberId = snapshot.getSubscriberId(); - String networkId = null; + String wifiNetworkKey = null; boolean roaming = !snapshot.getNetworkCapabilities().hasCapability( NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); boolean metered = !(snapshot.getNetworkCapabilities().hasCapability( @@ -226,19 +253,19 @@ public class NetworkIdentity implements Comparable { .getTransportInfo(); if (transportInfo instanceof WifiInfo) { final WifiInfo info = (WifiInfo) transportInfo; - networkId = info != null ? info.getCurrentNetworkKey() : null; + wifiNetworkKey = info != null ? info.getCurrentNetworkKey() : null; } } - return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered, - defaultNetwork, oemManaged); + return new NetworkIdentity(legacyType, ratType, subscriberId, wifiNetworkKey, roaming, + metered, defaultNetwork, oemManaged); } /** * Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}. * @hide */ - public static int getOemBitfield(NetworkCapabilities nc) { + public static int getOemBitfield(@NonNull NetworkCapabilities nc) { int oemManaged = OEM_NONE; if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) { @@ -252,16 +279,17 @@ public class NetworkIdentity implements Comparable { } @Override - public int compareTo(NetworkIdentity another) { + public int compareTo(@NonNull NetworkIdentity another) { + Objects.requireNonNull(another); int res = Integer.compare(mType, another.mType); if (res == 0) { - res = Integer.compare(mSubType, another.mSubType); + res = Integer.compare(mRatType, another.mRatType); } if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) { res = mSubscriberId.compareTo(another.mSubscriberId); } - if (res == 0 && mNetworkId != null && another.mNetworkId != null) { - res = mNetworkId.compareTo(another.mNetworkId); + if (res == 0 && mWifiNetworkKey != null && another.mWifiNetworkKey != null) { + res = mWifiNetworkKey.compareTo(another.mWifiNetworkKey); } if (res == 0) { res = Boolean.compare(mRoaming, another.mRoaming); diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java index abbebef85c..c2d8ea1f96 100644 --- a/framework-t/src/android/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -18,6 +18,7 @@ package android.net; import static android.net.ConnectivityManager.TYPE_MOBILE; +import android.annotation.NonNull; import android.service.NetworkIdentitySetProto; import android.util.proto.ProtoOutputStream; @@ -25,6 +26,7 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.HashSet; +import java.util.Objects; /** * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} @@ -32,6 +34,7 @@ import java.util.HashSet; * * @hide */ +// @SystemApi(client = MODULE_LIBRARIES) public class NetworkIdentitySet extends HashSet implements Comparable { private static final int VERSION_INIT = 1; @@ -41,9 +44,14 @@ public class NetworkIdentitySet extends HashSet implements private static final int VERSION_ADD_DEFAULT_NETWORK = 5; private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6; + /** + * Construct a {@link NetworkIdentitySet} object. + */ public NetworkIdentitySet() { + super(); } + /** @hide */ public NetworkIdentitySet(DataInput in) throws IOException { final int version = in.readInt(); final int size = in.readInt(); @@ -52,7 +60,7 @@ public class NetworkIdentitySet extends HashSet implements final int ignored = in.readInt(); } final int type = in.readInt(); - final int subType = in.readInt(); + final int ratType = in.readInt(); final String subscriberId = readOptionalString(in); final String networkId; if (version >= VERSION_ADD_NETWORK_ID) { @@ -91,22 +99,23 @@ public class NetworkIdentitySet extends HashSet implements oemNetCapabilities = NetworkIdentity.OEM_NONE; } - add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, + add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered, defaultNetwork, oemNetCapabilities)); } } /** * Method to serialize this object into a {@code DataOutput}. + * @hide */ public void writeToStream(DataOutput out) throws IOException { out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK); out.writeInt(size()); for (NetworkIdentity ident : this) { out.writeInt(ident.getType()); - out.writeInt(ident.getSubType()); + out.writeInt(ident.getRatType()); writeOptionalString(out, ident.getSubscriberId()); - writeOptionalString(out, ident.getNetworkId()); + writeOptionalString(out, ident.getWifiNetworkKey()); out.writeBoolean(ident.getRoaming()); out.writeBoolean(ident.getMetered()); out.writeBoolean(ident.getDefaultNetwork()); @@ -114,7 +123,10 @@ public class NetworkIdentitySet extends HashSet implements } } - /** @return whether any {@link NetworkIdentity} in this set is considered metered. */ + /** + * @return whether any {@link NetworkIdentity} in this set is considered metered. + * @hide + */ public boolean isAnyMemberMetered() { if (isEmpty()) { return false; @@ -127,7 +139,10 @@ public class NetworkIdentitySet extends HashSet implements return false; } - /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */ + /** + * @return whether any {@link NetworkIdentity} in this set is considered roaming. + * @hide + */ public boolean isAnyMemberRoaming() { if (isEmpty()) { return false; @@ -140,8 +155,11 @@ public class NetworkIdentitySet extends HashSet implements return false; } - /** @return whether any {@link NetworkIdentity} in this set is considered on the default - network. */ + /** + * @return whether any {@link NetworkIdentity} in this set is considered on the default + * network. + * @hide + */ public boolean areAllMembersOnDefaultNetwork() { if (isEmpty()) { return true; @@ -172,7 +190,8 @@ public class NetworkIdentitySet extends HashSet implements } @Override - public int compareTo(NetworkIdentitySet another) { + public int compareTo(@NonNull NetworkIdentitySet another) { + Objects.requireNonNull(another); if (isEmpty()) return -1; if (another.isEmpty()) return 1; @@ -183,6 +202,7 @@ public class NetworkIdentitySet extends HashSet implements /** * Method to dump this object into proto debug file. + * @hide */ public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 9f9d73f888..f169fed6b9 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -32,6 +32,8 @@ import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; @@ -77,6 +79,7 @@ import java.util.Objects; * * @hide */ +// @SystemApi(client = MODULE_LIBRARIES) public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer { private static final String TAG = NetworkStatsCollection.class.getSimpleName(); /** File header magic number: "ANET" */ @@ -100,15 +103,23 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private long mTotalBytes; private boolean mDirty; + /** + * Construct a {@link NetworkStatsCollection} object. + * + * @param bucketDuration duration of the buckets in this object, in milliseconds. + * @hide + */ public NetworkStatsCollection(long bucketDuration) { mBucketDuration = bucketDuration; reset(); } + /** @hide */ public void clear() { reset(); } + /** @hide */ public void reset() { mStats.clear(); mStartMillis = Long.MAX_VALUE; @@ -117,6 +128,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W mDirty = false; } + /** @hide */ public long getStartMillis() { return mStartMillis; } @@ -124,6 +136,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** * Return first atomic bucket in this collection, which is more conservative * than {@link #mStartMillis}. + * @hide */ public long getFirstAtomicBucketMillis() { if (mStartMillis == Long.MAX_VALUE) { @@ -133,26 +146,32 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** @hide */ public long getEndMillis() { return mEndMillis; } + /** @hide */ public long getTotalBytes() { return mTotalBytes; } + /** @hide */ public boolean isDirty() { return mDirty; } + /** @hide */ public void clearDirty() { mDirty = false; } + /** @hide */ public boolean isEmpty() { return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE; } + /** @hide */ @VisibleForTesting public long roundUp(long time) { if (time == Long.MIN_VALUE || time == Long.MAX_VALUE @@ -168,6 +187,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** @hide */ @VisibleForTesting public long roundDown(long time) { if (time == Long.MIN_VALUE || time == Long.MAX_VALUE @@ -182,10 +202,12 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** @hide */ public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) { return getRelevantUids(accessLevel, Binder.getCallingUid()); } + /** @hide */ public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel, final int callerUid) { final ArrayList uids = new ArrayList<>(); @@ -206,6 +228,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** * Combine all {@link NetworkStatsHistory} in this collection which match * the requested parameters. + * @hide */ public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan, int uid, int set, int tag, int fields, long start, long end, @@ -331,6 +354,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * @param end - end of the range, timestamp in milliseconds since the epoch. * @param accessLevel - caller access level. * @param callerUid - caller UID. + * @hide */ public NetworkStats getSummary(NetworkTemplate template, long start, long end, @NetworkStatsAccess.Level int accessLevel, int callerUid) { @@ -377,6 +401,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** * Record given {@link android.net.NetworkStats.Entry} into this collection. + * @hide */ public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start, long end, NetworkStats.Entry entry) { @@ -387,8 +412,12 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** * Record given {@link NetworkStatsHistory} into this collection. + * + * @hide */ - private void recordHistory(Key key, NetworkStatsHistory history) { + public void recordHistory(@NonNull Key key, @NonNull NetworkStatsHistory history) { + Objects.requireNonNull(key); + Objects.requireNonNull(history); if (history.size() == 0) return; noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes()); @@ -403,8 +432,11 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W /** * Record all {@link NetworkStatsHistory} contained in the given collection * into this collection. + * + * @hide */ - public void recordCollection(NetworkStatsCollection another) { + public void recordCollection(@NonNull NetworkStatsCollection another) { + Objects.requireNonNull(another); for (int i = 0; i < another.mStats.size(); i++) { final Key key = another.mStats.keyAt(i); final NetworkStatsHistory value = another.mStats.valueAt(i); @@ -433,6 +465,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** @hide */ @Override public void read(InputStream in) throws IOException { read((DataInput) new DataInputStream(in)); @@ -472,6 +505,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** @hide */ @Override public void write(OutputStream out) throws IOException { write((DataOutput) new DataOutputStream(out)); @@ -514,6 +548,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}. * * @deprecated + * @hide */ @Deprecated public void readLegacyNetwork(File file) throws IOException { @@ -559,6 +594,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}. * * @deprecated + * @hide */ @Deprecated public void readLegacyUid(File file, boolean onlyTags) throws IOException { @@ -629,6 +665,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * Remove any {@link NetworkStatsHistory} attributed to the requested UID, * moving any {@link NetworkStats#TAG_NONE} series to * {@link TrafficStats#UID_REMOVED}. + * @hide */ public void removeUids(int[] uids) { final ArrayList knownKeys = new ArrayList<>(); @@ -669,6 +706,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W return keys; } + /** @hide */ public void dump(IndentingPrintWriter pw) { for (Key key : getSortedKeys()) { pw.print("ident="); pw.print(key.ident.toString()); @@ -683,6 +721,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } } + /** @hide */ public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); @@ -706,6 +745,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W proto.end(start); } + /** @hide */ public void dumpCheckin(PrintWriter pw, long start, long end) { dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell"); dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi"); @@ -768,16 +808,32 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W return false; } - private static class Key implements Comparable { + /** + * the identifier that associate with the {@link NetworkStatsHistory} object to identify + * a certain record in the {@link NetworkStatsCollection} object. + */ + public static class Key implements Comparable { + /** @hide */ public final NetworkIdentitySet ident; + /** @hide */ public final int uid; + /** @hide */ public final int set; + /** @hide */ public final int tag; private final int mHashCode; - Key(NetworkIdentitySet ident, int uid, int set, int tag) { - this.ident = ident; + /** + * Construct a {@link Key} object. + * + * @param ident a Set of {@link NetworkIdentity} that associated with the record. + * @param uid Uid of the record. + * @param set Set of the record, see {@code NetworkStats#SET_*}. + * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}. + */ + public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) { + this.ident = Objects.requireNonNull(ident); this.uid = uid; this.set = set; this.tag = tag; @@ -790,7 +846,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (obj instanceof Key) { final Key key = (Key) obj; return uid == key.uid && set == key.set && tag == key.tag @@ -800,7 +856,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W } @Override - public int compareTo(Key another) { + public int compareTo(@NonNull Key another) { + Objects.requireNonNull(another); int res = 0; if (ident != null && another.ident != null) { res = ident.compareTo(another.ident); diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java index 428bc6df26..90054c683d 100644 --- a/framework-t/src/android/net/NetworkStatsHistory.java +++ b/framework-t/src/android/net/NetworkStatsHistory.java @@ -30,6 +30,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; +import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -64,18 +65,25 @@ import java.util.Random; * * @hide */ -public class NetworkStatsHistory implements Parcelable { +// @SystemApi(client = MODULE_LIBRARIES) +public final class NetworkStatsHistory implements Parcelable { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_PACKETS = 2; private static final int VERSION_ADD_ACTIVE = 3; + /** @hide */ public static final int FIELD_ACTIVE_TIME = 0x01; + /** @hide */ public static final int FIELD_RX_BYTES = 0x02; + /** @hide */ public static final int FIELD_RX_PACKETS = 0x04; + /** @hide */ public static final int FIELD_TX_BYTES = 0x08; + /** @hide */ public static final int FIELD_TX_PACKETS = 0x10; + /** @hide */ public static final int FIELD_OPERATIONS = 0x20; - + /** @hide */ public static final int FIELD_ALL = 0xFFFFFFFF; private long bucketDuration; @@ -108,15 +116,18 @@ public class NetworkStatsHistory implements Parcelable { public long operations; } + /** @hide */ @UnsupportedAppUsage public NetworkStatsHistory(long bucketDuration) { this(bucketDuration, 10, FIELD_ALL); } + /** @hide */ public NetworkStatsHistory(long bucketDuration, int initialSize) { this(bucketDuration, initialSize, FIELD_ALL); } + /** @hide */ public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) { this.bucketDuration = bucketDuration; bucketStart = new long[initialSize]; @@ -130,11 +141,13 @@ public class NetworkStatsHistory implements Parcelable { totalBytes = 0; } + /** @hide */ public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) { this(bucketDuration, existing.estimateResizeBuckets(bucketDuration)); recordEntireHistory(existing); } + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public NetworkStatsHistory(Parcel in) { bucketDuration = in.readLong(); @@ -150,7 +163,7 @@ public class NetworkStatsHistory implements Parcelable { } @Override - public void writeToParcel(Parcel out, int flags) { + public void writeToParcel(@NonNull Parcel out, int flags) { out.writeLong(bucketDuration); writeLongArray(out, bucketStart, bucketCount); writeLongArray(out, activeTime, bucketCount); @@ -162,6 +175,7 @@ public class NetworkStatsHistory implements Parcelable { out.writeLong(totalBytes); } + /** @hide */ public NetworkStatsHistory(DataInput in) throws IOException { final int version = in.readInt(); switch (version) { @@ -204,6 +218,7 @@ public class NetworkStatsHistory implements Parcelable { } } + /** @hide */ public void writeToStream(DataOutput out) throws IOException { out.writeInt(VERSION_ADD_ACTIVE); out.writeLong(bucketDuration); @@ -221,15 +236,18 @@ public class NetworkStatsHistory implements Parcelable { return 0; } + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int size() { return bucketCount; } + /** @hide */ public long getBucketDuration() { return bucketDuration; } + /** @hide */ @UnsupportedAppUsage public long getStart() { if (bucketCount > 0) { @@ -239,6 +257,7 @@ public class NetworkStatsHistory implements Parcelable { } } + /** @hide */ @UnsupportedAppUsage public long getEnd() { if (bucketCount > 0) { @@ -250,6 +269,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return total bytes represented by this history. + * @hide */ public long getTotalBytes() { return totalBytes; @@ -258,6 +278,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return index of bucket that contains or is immediately before the * requested time. + * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public int getIndexBefore(long time) { @@ -273,6 +294,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return index of bucket that contains or is immediately after the * requested time. + * @hide */ public int getIndexAfter(long time) { int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time); @@ -286,6 +308,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Return specific stats entry. + * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Entry getValues(int i, Entry recycle) { @@ -301,6 +324,7 @@ public class NetworkStatsHistory implements Parcelable { return entry; } + /** @hide */ public void setValues(int i, Entry entry) { // Unwind old values if (rxBytes != null) totalBytes -= rxBytes[i]; @@ -322,6 +346,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Record that data traffic occurred in the given time range. Will * distribute across internal buckets, creating new buckets as needed. + * @hide */ @Deprecated public void recordData(long start, long end, long rxBytes, long txBytes) { @@ -332,6 +357,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Record that data traffic occurred in the given time range. Will * distribute across internal buckets, creating new buckets as needed. + * @hide */ public void recordData(long start, long end, NetworkStats.Entry entry) { long rxBytes = entry.rxBytes; @@ -392,6 +418,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Record an entire {@link NetworkStatsHistory} into this history. Usually * for combining together stats for external reporting. + * @hide */ @UnsupportedAppUsage public void recordEntireHistory(NetworkStatsHistory input) { @@ -402,6 +429,7 @@ public class NetworkStatsHistory implements Parcelable { * Record given {@link NetworkStatsHistory} into this history, copying only * buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. + * @hide */ public void recordHistory(NetworkStatsHistory input, long start, long end) { final NetworkStats.Entry entry = new NetworkStats.Entry( @@ -483,6 +511,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Clear all data stored in this object. + * @hide */ public void clear() { bucketStart = EmptyArray.LONG; @@ -498,9 +527,10 @@ public class NetworkStatsHistory implements Parcelable { /** * Remove buckets older than requested cutoff. + * @hide */ - @Deprecated public void removeBucketsBefore(long cutoff) { + // TODO: Consider use getIndexBefore. int i; for (i = 0; i < bucketCount; i++) { final long curStart = bucketStart[i]; @@ -522,7 +552,9 @@ public class NetworkStatsHistory implements Parcelable { if (operations != null) operations = Arrays.copyOfRange(operations, i, length); bucketCount -= i; - // TODO: subtract removed values from totalBytes + totalBytes = 0; + if (rxBytes != null) totalBytes += CollectionUtils.total(rxBytes); + if (txBytes != null) totalBytes += CollectionUtils.total(txBytes); } } @@ -536,6 +568,7 @@ public class NetworkStatsHistory implements Parcelable { * @param start - start of the range, timestamp in milliseconds since the epoch. * @param end - end of the range, timestamp in milliseconds since the epoch. * @param recycle - entry instance for performance, could be null. + * @hide */ @UnsupportedAppUsage public Entry getValues(long start, long end, Entry recycle) { @@ -550,6 +583,7 @@ public class NetworkStatsHistory implements Parcelable { * @param end - end of the range, timestamp in milliseconds since the epoch. * @param now - current timestamp in milliseconds since the epoch (wall clock). * @param recycle - entry instance for performance, could be null. + * @hide */ @UnsupportedAppUsage public Entry getValues(long start, long end, long now, Entry recycle) { @@ -613,6 +647,7 @@ public class NetworkStatsHistory implements Parcelable { /** * @deprecated only for temporary testing + * @hide */ @Deprecated public void generateRandom(long start, long end, long bytes) { @@ -631,6 +666,7 @@ public class NetworkStatsHistory implements Parcelable { /** * @deprecated only for temporary testing + * @hide */ @Deprecated public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes, @@ -660,12 +696,14 @@ public class NetworkStatsHistory implements Parcelable { } } + /** @hide */ public static long randomLong(Random r, long start, long end) { return (long) (start + (r.nextFloat() * (end - start))); } /** * Quickly determine if this history intersects with given window. + * @hide */ public boolean intersects(long start, long end) { final long dataStart = getStart(); @@ -677,6 +715,7 @@ public class NetworkStatsHistory implements Parcelable { return false; } + /** @hide */ public void dump(IndentingPrintWriter pw, boolean fullHistory) { pw.print("NetworkStatsHistory: bucketDuration="); pw.println(bucketDuration / SECOND_IN_MILLIS); @@ -700,6 +739,7 @@ public class NetworkStatsHistory implements Parcelable { pw.decreaseIndent(); } + /** @hide */ public void dumpCheckin(PrintWriter pw) { pw.print("d,"); pw.print(bucketDuration / SECOND_IN_MILLIS); @@ -717,6 +757,7 @@ public class NetworkStatsHistory implements Parcelable { } } + /** @hide */ public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); @@ -776,6 +817,7 @@ public class NetworkStatsHistory implements Parcelable { if (array != null) array[i] += value; } + /** @hide */ public int estimateResizeBuckets(long newBucketDuration) { return (int) (size() * getBucketDuration() / newBucketDuration); } @@ -783,6 +825,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Utility methods for interacting with {@link DataInputStream} and * {@link DataOutputStream}, mostly dealing with writing partial arrays. + * @hide */ public static class DataStreamUtils { @Deprecated @@ -857,6 +900,7 @@ public class NetworkStatsHistory implements Parcelable { /** * Utility methods for interacting with {@link Parcel} structures, mostly * dealing with writing partial arrays. + * @hide */ public static class ParcelUtils { public static long[] readLongArray(Parcel in) { diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index e9084b0196..a7e48d4363 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -364,7 +364,7 @@ public final class NetworkTemplate implements Parcelable { private final int mMetered; private final int mRoaming; private final int mDefaultNetwork; - private final int mSubType; + private final int mRatType; /** * The subscriber Id match rule defines how the template should match networks with * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail. @@ -413,18 +413,18 @@ public final class NetworkTemplate implements Parcelable { /** @hide */ // TODO: Remove it after updating all of the caller. public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, - String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int subType, + String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int ratType, int oemManaged) { this(matchRule, subscriberId, matchSubscriberIds, wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0], - metered, roaming, defaultNetwork, subType, oemManaged, + metered, roaming, defaultNetwork, ratType, oemManaged, NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT); } /** @hide */ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds, String[] matchWifiNetworkKeys, int metered, int roaming, - int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) { + int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) { Objects.requireNonNull(matchWifiNetworkKeys); mMatchRule = matchRule; mSubscriberId = subscriberId; @@ -435,7 +435,7 @@ public final class NetworkTemplate implements Parcelable { mMetered = metered; mRoaming = roaming; mDefaultNetwork = defaultNetwork; - mSubType = subType; + mRatType = ratType; mOemManaged = oemManaged; mSubscriberIdMatchRule = subscriberIdMatchRule; checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule); @@ -453,7 +453,7 @@ public final class NetworkTemplate implements Parcelable { mMetered = in.readInt(); mRoaming = in.readInt(); mDefaultNetwork = in.readInt(); - mSubType = in.readInt(); + mRatType = in.readInt(); mOemManaged = in.readInt(); mSubscriberIdMatchRule = in.readInt(); } @@ -467,7 +467,7 @@ public final class NetworkTemplate implements Parcelable { dest.writeInt(mMetered); dest.writeInt(mRoaming); dest.writeInt(mDefaultNetwork); - dest.writeInt(mSubType); + dest.writeInt(mRatType); dest.writeInt(mOemManaged); dest.writeInt(mSubscriberIdMatchRule); } @@ -500,8 +500,8 @@ public final class NetworkTemplate implements Parcelable { builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString( mDefaultNetwork)); } - if (mSubType != NETWORK_TYPE_ALL) { - builder.append(", subType=").append(mSubType); + if (mRatType != NETWORK_TYPE_ALL) { + builder.append(", ratType=").append(mRatType); } if (mOemManaged != OEM_MANAGED_ALL) { builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged)); @@ -514,7 +514,7 @@ public final class NetworkTemplate implements Parcelable { @Override public int hashCode() { return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys), - mMetered, mRoaming, mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule); + mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, mSubscriberIdMatchRule); } @Override @@ -526,7 +526,7 @@ public final class NetworkTemplate implements Parcelable { && mMetered == other.mMetered && mRoaming == other.mRoaming && mDefaultNetwork == other.mDefaultNetwork - && mSubType == other.mSubType + && mRatType == other.mRatType && mOemManaged == other.mOemManaged && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule && Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys); @@ -635,7 +635,7 @@ public final class NetworkTemplate implements Parcelable { * Get the Radio Access Technology(RAT) type filter of the template. */ public int getRatType() { - return mSubType; + return mRatType; } /** @@ -708,8 +708,8 @@ public final class NetworkTemplate implements Parcelable { } private boolean matchesCollapsedRatType(NetworkIdentity ident) { - return mSubType == NETWORK_TYPE_ALL - || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType); + return mRatType == NETWORK_TYPE_ALL + || getCollapsedRatType(mRatType) == getCollapsedRatType(ident.mRatType); } /** @@ -837,7 +837,7 @@ public final class NetworkTemplate implements Parcelable { switch (ident.mType) { case TYPE_WIFI: return matchesSubscriberId(ident.mSubscriberId) - && matchesWifiNetworkKey(ident.mNetworkId); + && matchesWifiNetworkKey(ident.mWifiNetworkKey); default: return false; } diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index a0710f77b4..4bb61bd090 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -19,12 +19,15 @@ package com.android.server.net; import static android.Manifest.permission.NETWORK_STATS_PROVIDER; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.UPDATE_DEVICE_STATS; +import static android.app.usage.NetworkStatsManager.PREFIX_DEV; +import static android.app.usage.NetworkStatsManager.PREFIX_UID; +import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG; +import static android.app.usage.NetworkStatsManager.PREFIX_XT; import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.NetworkIdentity.SUBTYPE_COMBINED; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.IFACE_VT; @@ -243,11 +246,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private PendingIntent mPollIntent; - private static final String PREFIX_DEV = "dev"; - private static final String PREFIX_XT = "xt"; - private static final String PREFIX_UID = "uid"; - private static final String PREFIX_UID_TAG = "uid_tag"; - /** * Settings that can be changed externally. */ @@ -257,9 +255,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { boolean getSampleEnabled(); boolean getAugmentEnabled(); /** - * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}. - * When disabled, mobile data is broken down by a granular subtype representative of the - * actual subtype. {@see NetworkTemplate#getCollapsedRatType}. + * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}. + * When disabled, mobile data is broken down by a granular ratType representative of the + * actual ratType. {@see NetworkTemplate#getCollapsedRatType}. * Enabling this decreases the level of detail but saves performance, disk space and * amount of data logged. */ @@ -1389,10 +1387,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); final boolean isDefault = CollectionUtils.contains( mDefaultNetworks, snapshot.getNetwork()); - final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED - : getSubTypeForStateSnapshot(snapshot); + final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL + : getRatTypeForStateSnapshot(snapshot); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot, - isDefault, subType); + isDefault, ratType); // Traffic occurring on the base interface is always counted for // both total usage and UID details. @@ -1411,7 +1409,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Copy the identify from IMS one but mark it as metered. NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), - ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), + ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(), ident.getRoaming(), true /* metered */, true /* onDefaultNetwork */, ident.getOemManaged()); final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot); @@ -1492,11 +1490,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** - * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through + * For networks with {@code TRANSPORT_CELLULAR}, get ratType that was obtained through * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different * transport types do not actually fill this value. */ - private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) { + private int getRatTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) { if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { return 0; } From 86377eba46902ea42f065f7df020cfd6751eab86 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 19 Jan 2022 18:25:03 +0000 Subject: [PATCH 780/881] [MS65.1] Add NetworkIdentity#Builder Test: atest NetworkIdentityTest#testBuilder Bug: 204830222 Change-Id: Ifdb6482a54fb1e6999c82647d2710cb833c78d02 --- .../src/android/net/NetworkIdentity.java | 259 ++++++++++++++++-- .../src/android/net/NetworkIdentitySet.java | 12 +- .../server/net/NetworkStatsService.java | 4 +- 3 files changed, 238 insertions(+), 37 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 097b9bea90..9b9d38a360 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -19,8 +19,10 @@ package android.net; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.content.Context; import android.net.wifi.WifiInfo; import android.service.NetworkIdentityProto; @@ -31,6 +33,8 @@ import android.util.proto.ProtoOutputStream; import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.NetworkIdentityUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; @@ -49,6 +53,15 @@ public class NetworkIdentity implements Comparable { // {@link NetworkTemplate#NETWORK_TYPE_ALL} instead. public static final int SUBTYPE_COMBINED = -1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "OEM_MANAGED_" }, value = { + NetworkTemplate.OEM_MANAGED_NO, + NetworkTemplate.OEM_MANAGED_PAID, + NetworkTemplate.OEM_MANAGED_PRIVATE + }) + public @interface OemManaged{} + /** * Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}. * @hide @@ -177,42 +190,62 @@ public class NetworkIdentity implements Comparable { proto.end(start); } - /** @hide */ + /** Get the network type of this instance. */ public int getType() { return mType; } - /** @hide */ + /** Get the Radio Access Technology(RAT) type of this instance. */ public int getRatType() { return mRatType; } - /** @hide */ + /** Get the Subscriber Id of this instance. */ + @Nullable public String getSubscriberId() { return mSubscriberId; } - /** @hide */ + /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getCurrentNetworkKey()}. */ + @Nullable public String getWifiNetworkKey() { return mWifiNetworkKey; } /** @hide */ + // TODO: Remove this function after all callers are removed. public boolean getRoaming() { return mRoaming; } + /** Return the roaming status of this instance. */ + public boolean isRoaming() { + return mRoaming; + } + /** @hide */ + // TODO: Remove this function after all callers are removed. public boolean getMetered() { return mMetered; } + /** Return the meteredness of this instance. */ + public boolean isMetered() { + return mMetered; + } + /** @hide */ + // TODO: Remove this function after all callers are removed. public boolean getDefaultNetwork() { return mDefaultNetwork; } - /** @hide */ + /** Return the default network status of this instance. */ + public boolean isDefaultNetwork() { + return mDefaultNetwork; + } + + /** Get the OEM managed type of this instance. */ public int getOemManaged() { return mOemManaged; } @@ -229,36 +262,16 @@ public class NetworkIdentity implements Comparable { * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable. * See {@code TelephonyManager.NETWORK_TYPE_*}. * @hide + * @deprecated See {@link NetworkIdentity#Builder}. */ // TODO: Remove this after all callers are migrated to use new Api. + @Deprecated @NonNull public static NetworkIdentity buildNetworkIdentity(Context context, @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, @Annotation.NetworkType int ratType) { - final int legacyType = snapshot.getLegacyType(); - - final String subscriberId = snapshot.getSubscriberId(); - String wifiNetworkKey = null; - boolean roaming = !snapshot.getNetworkCapabilities().hasCapability( - NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING); - boolean metered = !(snapshot.getNetworkCapabilities().hasCapability( - NetworkCapabilities.NET_CAPABILITY_NOT_METERED) - || snapshot.getNetworkCapabilities().hasCapability( - NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)); - - final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities()); - - if (legacyType == TYPE_WIFI) { - final TransportInfo transportInfo = snapshot.getNetworkCapabilities() - .getTransportInfo(); - if (transportInfo instanceof WifiInfo) { - final WifiInfo info = (WifiInfo) transportInfo; - wifiNetworkKey = info != null ? info.getCurrentNetworkKey() : null; - } - } - - return new NetworkIdentity(legacyType, ratType, subscriberId, wifiNetworkKey, roaming, - metered, defaultNetwork, oemManaged); + return new NetworkIdentity.Builder().setNetworkStateSnapshot(snapshot) + .setDefaultNetwork(defaultNetwork).setRatType(ratType).build(); } /** @@ -305,4 +318,192 @@ public class NetworkIdentity implements Comparable { } return res; } + + /** + * Builder class for {@link NetworkIdentity}. + */ + public static final class Builder { + private int mType; + private int mRatType; + private String mSubscriberId; + private String mWifiNetworkKey; + private boolean mRoaming; + private boolean mMetered; + private boolean mDefaultNetwork; + private int mOemManaged; + + /** + * Creates a new Builder. + */ + public Builder() { + // Initialize with default values. Will be overwritten by setters. + mType = ConnectivityManager.TYPE_NONE; + mRatType = NetworkTemplate.NETWORK_TYPE_ALL; + mSubscriberId = null; + mWifiNetworkKey = null; + mRoaming = false; + mMetered = false; + mDefaultNetwork = false; + mOemManaged = NetworkTemplate.OEM_MANAGED_NO; + } + + /** + * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance. + * This is to read roaming, metered, wifikey... from the snapshot for convenience. + * + * @param snapshot The target {@link NetworkStateSnapshot} object. + * @return The builder object. + */ + @SuppressLint("MissingGetterMatchingBuilder") + @NonNull + public Builder setNetworkStateSnapshot(@NonNull NetworkStateSnapshot snapshot) { + setType(snapshot.getLegacyType()); + + setSubscriberId(snapshot.getSubscriberId()); + setRoaming(!snapshot.getNetworkCapabilities().hasCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)); + setMetered(!(snapshot.getNetworkCapabilities().hasCapability( + NetworkCapabilities.NET_CAPABILITY_NOT_METERED) + || snapshot.getNetworkCapabilities().hasCapability( + NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED))); + + setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities())); + + if (mType == TYPE_WIFI) { + final TransportInfo transportInfo = snapshot.getNetworkCapabilities() + .getTransportInfo(); + if (transportInfo instanceof WifiInfo) { + final WifiInfo info = (WifiInfo) transportInfo; + if (info != null) { + setWifiNetworkKey(info.getCurrentNetworkKey()); + } + } + } + return this; + } + + /** + * Set the network type of the network. + * + * @param type the network type. See {@link ConnectivityManager#TYPE_*}. + * + * @return this builder. + */ + @NonNull + public Builder setType(int type) { + mType = type; + return this; + } + + /** + * Set the Radio Access Technology(RAT) type of the network. + * + * @param ratType the Radio Access Technology(RAT) type if applicable. See + * {@code TelephonyManager.NETWORK_TYPE_*}. + * + * @return this builder. + */ + @NonNull + public Builder setRatType(@Annotation.NetworkType int ratType) { + mRatType = ratType; + return this; + } + + /** + * Clear the Radio Access Technology(RAT) type of the network. + * + * @return this builder. + */ + @NonNull + public Builder clearRatType() { + mRatType = NetworkTemplate.NETWORK_TYPE_ALL; + return this; + } + + /** + * Set the Subscriber Id. + * + * @param subscriberId the Subscriber Id of the network. Or null if not applicable. + * @return this builder. + */ + @NonNull + public Builder setSubscriberId(@Nullable String subscriberId) { + mSubscriberId = subscriberId; + return this; + } + + /** + * Set the Wifi Network Key. + * + * @param wifiNetworkKey Wifi Network Key of the network, + * see {@link WifiInfo#getCurrentNetworkKey()}. + * Or null if not applicable. + * @return this builder. + */ + @NonNull + public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) { + mWifiNetworkKey = wifiNetworkKey; + return this; + } + + /** + * Set the roaming. + * + * @param roaming the roaming status of the network. + * @return this builder. + */ + @NonNull + public Builder setRoaming(boolean roaming) { + mRoaming = roaming; + return this; + } + + /** + * Set the meteredness. + * + * @param metered the meteredness of the network. + * @return this builder. + */ + @NonNull + public Builder setMetered(boolean metered) { + mMetered = metered; + return this; + } + + /** + * Set the default network status. + * + * @param defaultNetwork the default network status of the network. + * @return this builder. + */ + @NonNull + public Builder setDefaultNetwork(boolean defaultNetwork) { + mDefaultNetwork = defaultNetwork; + return this; + } + + /** + * Set the OEM managed type. + * + * @param oemManaged Type of OEM managed network or unmanaged networks. + * See {@code NetworkTemplate#OEM_MANAGED_*}. + * @return this builder. + */ + @NonNull + public Builder setOemManaged(@OemManaged int oemManaged) { + mOemManaged = oemManaged; + return this; + } + + /** + * Builds the instance of the {@link NetworkIdentity}. + * + * @return the built instance of {@link NetworkIdentity}. + */ + @NonNull + public NetworkIdentity build() { + return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey, + mRoaming, mMetered, mDefaultNetwork, mOemManaged); + } + } } diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java index c2d8ea1f96..041f070512 100644 --- a/framework-t/src/android/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -116,9 +116,9 @@ public class NetworkIdentitySet extends HashSet implements out.writeInt(ident.getRatType()); writeOptionalString(out, ident.getSubscriberId()); writeOptionalString(out, ident.getWifiNetworkKey()); - out.writeBoolean(ident.getRoaming()); - out.writeBoolean(ident.getMetered()); - out.writeBoolean(ident.getDefaultNetwork()); + out.writeBoolean(ident.isRoaming()); + out.writeBoolean(ident.isMetered()); + out.writeBoolean(ident.isDefaultNetwork()); out.writeInt(ident.getOemManaged()); } } @@ -132,7 +132,7 @@ public class NetworkIdentitySet extends HashSet implements return false; } for (NetworkIdentity ident : this) { - if (ident.getMetered()) { + if (ident.isMetered()) { return true; } } @@ -148,7 +148,7 @@ public class NetworkIdentitySet extends HashSet implements return false; } for (NetworkIdentity ident : this) { - if (ident.getRoaming()) { + if (ident.isRoaming()) { return true; } } @@ -165,7 +165,7 @@ public class NetworkIdentitySet extends HashSet implements return true; } for (NetworkIdentity ident : this) { - if (!ident.getDefaultNetwork()) { + if (!ident.isDefaultNetwork()) { return false; } } diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 4bb61bd090..577de215d8 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1405,12 +1405,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // VT is considered always metered in framework's layer. If VT is not metered // per carrier's policy, modem will report 0 usage for VT calls. if (snapshot.getNetworkCapabilities().hasCapability( - NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) { + NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) { // Copy the identify from IMS one but mark it as metered. NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(), - ident.getRoaming(), true /* metered */, + ident.isRoaming(), true /* metered */, true /* onDefaultNetwork */, ident.getOemManaged()); final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot); findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent); From 02eb422cb48283b7011424281f9c00c4759e89df Mon Sep 17 00:00:00 2001 From: lifr Date: Wed, 12 Jan 2022 00:54:40 +0800 Subject: [PATCH 781/881] [DU03-1]Remove INetworkStatsService from BatteryStatsImpl Expose systemapi NetworkStats.getDetailedUidStats for use by BatteryStats. BatteryStatsImpl is using INetworkStatsService APIs, which cannot be accessed after moving into the mainline module. So, replace and remove those hidden API usages. Bug: 210066922 Test: atest BatteryStatsImplTest WifiPowerCalculatorTest MobileRadioPowerCalculatorTest NetworkStatsServiceTest CTS-Coverage-Bug: 213437796 Change-Id: I40d713923278f4654d67bb4d12155cea85c10447 --- .../app/usage/NetworkStatsManager.java | 52 ++++++++++++++----- .../src/android/net/INetworkStatsService.aidl | 10 +--- .../server/net/NetworkStatsService.java | 25 ++++++++- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 8d93354ea9..683678ad46 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -17,6 +17,8 @@ package android.app.usage; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import android.Manifest; import android.annotation.NonNull; @@ -55,7 +57,6 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; -import java.util.Set; /** * Provides access to network usage history and statistics. Usage data is collected in @@ -670,26 +671,49 @@ public class NetworkStatsManager { } /** - * Query realtime network usage statistics details with interfaces constrains. - * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING}, - * video calling data usage and count of network operations that set by - * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any - * statistics that is reported by {@link NetworkStatsProvider}. + * Query realtime mobile network usage statistics. * - * @param requiredIfaces A list of interfaces the stats should be restricted to, or - * {@link NetworkStats#INTERFACES_ALL}. + * Return a snapshot of current UID network statistics, as it applies + * to the mobile radios of the device. The snapshot will include any + * tethering traffic, video calling data usage and count of + * network operations set by {@link TrafficStats#incrementOperationCount} + * made over a mobile radio. + * The snapshot will not include any statistics that cannot be seen by + * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s. * * @hide */ - //@SystemApi + @SystemApi @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) - @NonNull public android.net.NetworkStats getDetailedUidStats( - @NonNull Set requiredIfaces) { - Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null"); + @NonNull public android.net.NetworkStats getMobileUidStats() { try { - return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0])); + return mService.getUidStatsForTransport(TRANSPORT_CELLULAR); } catch (RemoteException e) { - if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats"); + if (DBG) Log.d(TAG, "Remote exception when get Mobile uid stats"); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Query realtime Wi-Fi network usage statistics. + * + * Return a snapshot of current UID network statistics, as it applies + * to the Wi-Fi radios of the device. The snapshot will include any + * tethering traffic, video calling data usage and count of + * network operations set by {@link TrafficStats#incrementOperationCount} + * made over a Wi-Fi radio. + * The snapshot will not include any statistics that cannot be seen by + * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s. + * + * @hide + */ + @SystemApi + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + @NonNull public android.net.NetworkStats getWifiUidStats() { + try { + return mService.getUidStatsForTransport(TRANSPORT_WIFI); + } catch (RemoteException e) { + if (DBG) Log.d(TAG, "Remote exception when get WiFi uid stats"); throw e.rethrowFromSystemServer(); } } diff --git a/framework-t/src/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl index a4babb543d..da0aa99b93 100644 --- a/framework-t/src/android/net/INetworkStatsService.aidl +++ b/framework-t/src/android/net/INetworkStatsService.aidl @@ -49,14 +49,8 @@ interface INetworkStatsService { @UnsupportedAppUsage NetworkStats getDataLayerSnapshotForUid(int uid); - /** Get a detailed snapshot of stats since boot for all UIDs. - * - *

Results will not always be limited to stats on requiredIfaces when specified: stats for - * interfaces stacked on the specified interfaces, or for interfaces on which the specified - * interfaces are stacked on, will also be included. - * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}. - */ - NetworkStats getDetailedUidStats(in String[] requiredIfaces); + /** Get the transport NetworkStats for all UIDs since boot. */ + NetworkStats getUidStatsForTransport(int transport); /** Return set of any ifaces associated with mobile networks since boot. */ @UnsupportedAppUsage diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 8e15f799c3..192c5c1297 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -28,6 +28,7 @@ import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.IFACE_VT; @@ -291,6 +292,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Set of any ifaces associated with mobile networks since boot. */ private volatile String[] mMobileIfaces = new String[0]; + /** Set of any ifaces associated with wifi networks since boot. */ + private volatile String[] mWifiIfaces = new String[0]; + /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */ @GuardedBy("mStatsLock") private Network[] mDefaultNetworks = new Network[0]; @@ -1005,11 +1009,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public NetworkStats getDetailedUidStats(String[] requiredIfaces) { + public NetworkStats getUidStatsForTransport(int transport) { enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); try { + final String[] relevantIfaces = + transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces; + // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked + // interfaces, so this is not useful, remove it. final String[] ifacesToQuery = - mStatsFactory.augmentWithStackedInterfaces(requiredIfaces); + mStatsFactory.augmentWithStackedInterfaces(relevantIfaces); return getNetworkStatsUidDetail(ifacesToQuery); } catch (RemoteException e) { Log.wtf(TAG, "Error compiling UID stats", e); @@ -1368,10 +1376,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); final ArraySet mobileIfaces = new ArraySet<>(); + final ArraySet wifiIfaces = new ArraySet<>(); for (NetworkStateSnapshot snapshot : snapshots) { final int displayTransport = getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes()); final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); + final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport); final boolean isDefault = CollectionUtils.contains( mDefaultNetworks, snapshot.getNetwork()); final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL @@ -1407,6 +1417,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (isMobile) { mobileIfaces.add(baseIface); } + if (isWifi) { + wifiIfaces.add(baseIface); + } } // Traffic occurring on stacked interfaces is usually clatd. @@ -1448,6 +1461,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { if (isMobile) { mobileIfaces.add(iface); } + if (isWifi) { + wifiIfaces.add(iface); + } mStatsFactory.noteStackedIface(iface, baseIface); } @@ -1455,11 +1471,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } mMobileIfaces = mobileIfaces.toArray(new String[0]); + mWifiIfaces = wifiIfaces.toArray(new String[0]); // TODO (b/192758557): Remove debug log. if (CollectionUtils.contains(mMobileIfaces, null)) { throw new NullPointerException( "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); } + if (CollectionUtils.contains(mWifiIfaces, null)) { + throw new NullPointerException( + "null element in mWifiIfaces: " + Arrays.toString(mWifiIfaces)); + } } private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { From 9703eb291cd736ae5a119b1898436ba92fad5d6b Mon Sep 17 00:00:00 2001 From: markchien Date: Fri, 14 Jan 2022 22:20:03 +0800 Subject: [PATCH 782/881] Replace INetd#trafficSwapActiveStatsMap with ConnectivityManager API INetd#trafficSwapActiveStatsMap is deprecated and the implementaion is moved into tethering (connectivity) mainline module. A new ConnectivityManager API swapActiveStatsMap is temprary exposed for NetworkStatsFactory. Once NetworkStatsFactory move into tethering module, swapActiveStatsMap API would be removed and NetworkStatsFactory should could call the implemeneted inside the module directly. This should happen before T sdk finalization. Bug: 209935649 Test: atest NetworkStatsFactoryTest Change-Id: I6685fe513511e7af9fa6521601891c66d1297da0 --- .../server/net/NetworkStatsFactory.java | 23 ++++++++++--------- .../server/net/NetworkStatsService.java | 15 +++++++++--- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java index bb123a38eb..17f3455d20 100644 --- a/service-t/src/com/android/server/net/NetworkStatsFactory.java +++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java @@ -26,10 +26,10 @@ import static com.android.server.NetworkManagementSocketTagger.kernelToTag; import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.INetd; +import android.content.Context; +import android.net.ConnectivityManager; import android.net.NetworkStats; import android.net.UnderlyingNetworkInfo; -import android.os.RemoteException; import android.os.StrictMode; import android.os.SystemClock; @@ -70,7 +70,7 @@ public class NetworkStatsFactory { private final boolean mUseBpfStats; - private final INetd mNetd; + private final Context mContext; /** * Guards persistent data access in this class @@ -158,12 +158,12 @@ public class NetworkStatsFactory { NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces); } - public NetworkStatsFactory(@NonNull INetd netd) { - this(new File("/proc/"), true, netd); + public NetworkStatsFactory(@NonNull Context ctx) { + this(ctx, new File("/proc/"), true); } @VisibleForTesting - public NetworkStatsFactory(File procRoot, boolean useBpfStats, @NonNull INetd netd) { + public NetworkStatsFactory(@NonNull Context ctx, File procRoot, boolean useBpfStats) { mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); @@ -172,7 +172,7 @@ public class NetworkStatsFactory { mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); } - mNetd = netd; + mContext = ctx; } public NetworkStats readBpfNetworkStatsDev() throws IOException { @@ -295,11 +295,12 @@ public class NetworkStatsFactory { } @GuardedBy("mPersistentDataLock") - private void requestSwapActiveStatsMapLocked() throws RemoteException { - // Ask netd to do a active map stats swap. When the binder call successfully returns, + private void requestSwapActiveStatsMapLocked() { + // Do a active map stats swap. When the binder call successfully returns, // the system server should be able to safely read and clean the inactive map // without race problem. - mNetd.trafficSwapActiveStatsMap(); + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.swapActiveStatsMap(); } /** @@ -327,7 +328,7 @@ public class NetworkStatsFactory { if (mUseBpfStats) { try { requestSwapActiveStatsMapLocked(); - } catch (RemoteException e) { + } catch (RuntimeException e) { throw new IOException(e); } // Stats are always read from the inactive map, so they must be read after the diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index d0db938837..815fc592f9 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -418,7 +418,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsService service = new NetworkStatsService(context, INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)), alarmManager, wakeLock, getDefaultClock(), - new DefaultNetworkStatsSettings(), new NetworkStatsFactory(netd), + new DefaultNetworkStatsSettings(), new NetworkStatsFactory(context), new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), new Dependencies()); @@ -987,8 +987,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } // TODO: switch to data layer stats once kernel exports - // for now, read network layer stats and flatten across all ifaces - final NetworkStats networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL); + // for now, read network layer stats and flatten across all ifaces. + // This function is used to query NeworkStats for calle's uid. The only caller method + // TrafficStats#getDataLayerSnapshotForUid alrady claim no special permission to query + // its own NetworkStats. + final long ident = Binder.clearCallingIdentity(); + final NetworkStats networkLayer; + try { + networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL); + } finally { + Binder.restoreCallingIdentity(ident); + } // splice in operation counts networkLayer.spliceOperationsFrom(mUidOperations); From debfc4015b2105b03b2cbb65be1aef7bcbb4aea8 Mon Sep 17 00:00:00 2001 From: markchien Date: Tue, 18 Jan 2022 18:26:28 +0800 Subject: [PATCH 783/881] Monitor interface added and update bpf interface map Have BpfInterfaceMapUpdater to update bpf interface map: adding the interface and index mapping to bpf interface map when interface added. Bug: 215095957 Test: atest FrameworkNetTests Change-Id: I2189a50c4869cfc0c33fc6f0228f40ee9f3ac1d4 --- service-t/Sources.bp | 27 ++++ service-t/jni/onload.cpp | 38 +++++ .../server/net/BpfInterfaceMapUpdater.java | 139 ++++++++++++++++++ .../android/server/net/InterfaceMapValue.java | 35 +++++ .../server/net/NetworkStatsService.java | 12 ++ 5 files changed, 251 insertions(+) create mode 100644 service-t/jni/onload.cpp create mode 100644 service-t/src/com/android/server/net/BpfInterfaceMapUpdater.java create mode 100644 service-t/src/com/android/server/net/InterfaceMapValue.java diff --git a/service-t/Sources.bp b/service-t/Sources.bp index b261e165a1..3fd3d8caab 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -26,6 +26,8 @@ filegroup { srcs: [ "src/com/android/server/net/NetworkIdentity*.java", "src/com/android/server/net/NetworkStats*.java", + "src/com/android/server/net/BpfInterfaceMapUpdater.java", + "src/com/android/server/net/InterfaceMapValue.java", ], path: "src", visibility: [ @@ -97,3 +99,28 @@ filegroup { "//packages/modules/Connectivity:__subpackages__", ], } + +cc_library_shared { + name: "libcom_android_net_module_util_jni", + min_sdk_version: "30", + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + "-Wthread-safety", + ], + srcs: [ + "jni/onload.cpp", + ], + stl: "libc++_static", + static_libs: [ + "libnet_utils_device_common_bpfjni", + ], + shared_libs: [ + "liblog", + "libnativehelper", + ], + apex_available: [ + "//apex_available:platform", + ], +} diff --git a/service-t/jni/onload.cpp b/service-t/jni/onload.cpp new file mode 100644 index 0000000000..bca4697560 --- /dev/null +++ b/service-t/jni/onload.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace android { + +int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + ALOGE("GetEnv failed"); + return JNI_ERR; + } + + if (register_com_android_net_module_util_BpfMap(env, + "com/android/net/module/util/BpfMap") < 0) return JNI_ERR; + + return JNI_VERSION_1_6; +} + +}; + diff --git a/service-t/src/com/android/server/net/BpfInterfaceMapUpdater.java b/service-t/src/com/android/server/net/BpfInterfaceMapUpdater.java new file mode 100644 index 0000000000..25c88eb6bd --- /dev/null +++ b/service-t/src/com/android/server/net/BpfInterfaceMapUpdater.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.net; + +import android.content.Context; +import android.net.INetd; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceSpecificException; +import android.system.ErrnoException; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.net.module.util.BaseNetdUnsolicitedEventListener; +import com.android.net.module.util.BpfMap; +import com.android.net.module.util.IBpfMap; +import com.android.net.module.util.InterfaceParams; +import com.android.net.module.util.Struct.U32; + +/** + * Monitor interface added (without removed) and right interface name and its index to bpf map. + */ +public class BpfInterfaceMapUpdater { + private static final String TAG = BpfInterfaceMapUpdater.class.getSimpleName(); + // This is current path but may be changed soon. + private static final String IFACE_INDEX_NAME_MAP_PATH = + "/sys/fs/bpf/map_netd_iface_index_name_map"; + private final IBpfMap mBpfMap; + private final INetd mNetd; + private final Handler mHandler; + private final Dependencies mDeps; + + public BpfInterfaceMapUpdater(Context ctx, Handler handler) { + this(ctx, handler, new Dependencies()); + } + + @VisibleForTesting + public BpfInterfaceMapUpdater(Context ctx, Handler handler, Dependencies deps) { + mDeps = deps; + mBpfMap = deps.getInterfaceMap(); + mNetd = deps.getINetd(ctx); + mHandler = handler; + } + + /** + * Dependencies of BpfInerfaceMapUpdater, for injection in tests. + */ + @VisibleForTesting + public static class Dependencies { + /** Create BpfMap for updating interface and index mapping. */ + public IBpfMap getInterfaceMap() { + try { + return new BpfMap<>(IFACE_INDEX_NAME_MAP_PATH, BpfMap.BPF_F_RDWR, + U32.class, InterfaceMapValue.class); + } catch (ErrnoException e) { + Log.e(TAG, "Cannot create interface map: " + e); + return null; + } + } + + /** Get InterfaceParams for giving interface name. */ + public InterfaceParams getInterfaceParams(String ifaceName) { + return InterfaceParams.getByName(ifaceName); + } + + /** Get INetd binder object. */ + public INetd getINetd(Context ctx) { + return INetd.Stub.asInterface((IBinder) ctx.getSystemService(Context.NETD_SERVICE)); + } + } + + /** + * Start listening interface update event. + * Query current interface names before listening. + */ + public void start() { + mHandler.post(() -> { + if (mBpfMap == null) { + Log.wtf(TAG, "Fail to start: Null bpf map"); + return; + } + + try { + // TODO: use a NetlinkMonitor and listen for RTM_NEWLINK messages instead. + mNetd.registerUnsolicitedEventListener(new InterfaceChangeObserver()); + } catch (RemoteException e) { + Log.wtf(TAG, "Unable to register netd UnsolicitedEventListener, " + e); + } + + final String[] ifaces; + try { + // TODO: use a netlink dump to get the current interface list. + ifaces = mNetd.interfaceGetList(); + } catch (RemoteException | ServiceSpecificException e) { + Log.wtf(TAG, "Unable to query interface names by netd, " + e); + return; + } + + for (String ifaceName : ifaces) { + addInterface(ifaceName); + } + }); + } + + private void addInterface(String ifaceName) { + final InterfaceParams iface = mDeps.getInterfaceParams(ifaceName); + if (iface == null) { + Log.e(TAG, "Unable to get InterfaceParams for " + ifaceName); + return; + } + + try { + mBpfMap.updateEntry(new U32(iface.index), new InterfaceMapValue(ifaceName)); + } catch (ErrnoException e) { + Log.e(TAG, "Unable to update entry for " + ifaceName + ", " + e); + } + } + + private class InterfaceChangeObserver extends BaseNetdUnsolicitedEventListener { + @Override + public void onInterfaceAdded(String ifName) { + mHandler.post(() -> addInterface(ifName)); + } + } +} diff --git a/service-t/src/com/android/server/net/InterfaceMapValue.java b/service-t/src/com/android/server/net/InterfaceMapValue.java new file mode 100644 index 0000000000..061f323447 --- /dev/null +++ b/service-t/src/com/android/server/net/InterfaceMapValue.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * The value of bpf interface index map which is used for NetworkStatsService. + */ +public class InterfaceMapValue extends Struct { + @Field(order = 0, type = Type.ByteArray, arraysize = 16) + public final byte[] interfaceName; + + public InterfaceMapValue(String iface) { + final byte[] ifaceArray = iface.getBytes(); + interfaceName = new byte[16]; + // All array bytes after the interface name, if any, must be 0. + System.arraycopy(ifaceArray, 0, interfaceName, 0, ifaceArray.length); + } +} diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index d0db938837..ad15c3c0c2 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -356,6 +356,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull private final LocationPermissionChecker mLocationPermissionChecker; + @NonNull + private final BpfInterfaceMapUpdater mInterfaceMapUpdater; + private static @NonNull File getDefaultSystemDir() { return new File(Environment.getDataDirectory(), "system"); } @@ -453,6 +456,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, mNetworkStatsSubscriptionsMonitor); mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext); + mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler); + mInterfaceMapUpdater.start(); } /** @@ -507,6 +512,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public LocationPermissionChecker makeLocationPermissionChecker(final Context context) { return new LocationPermissionChecker(context); } + + /** Create BpfInterfaceMapUpdater to update bpf interface map. */ + @NonNull + public BpfInterfaceMapUpdater makeBpfInterfaceMapUpdater( + @NonNull Context ctx, @NonNull Handler handler) { + return new BpfInterfaceMapUpdater(ctx, handler); + } } /** From 6f39e805a1c82ae6c32bde6d750544e620a55b21 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 19 Jan 2022 08:33:21 +0000 Subject: [PATCH 784/881] [MS66] Initialize TrafficStats with context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TrafficStats has static methods created in API level 8 that need access to NetworkStatsManager but doesn't take a context. Previously this was achieved by using ServiceManager, but with TrafficStats moving to the connectivity module, this is no longer possible. Instead, make sure TrafficStats has an appropriate context by the time any client code can call the relevant methods. • In app code, this achieved by passing the application context from ActivityThread#handleBindApplication, before any app code can run. • In the system server, this is achieved by passing the context right after creating service. Test: atest TrafficStatsTest CtsWebkitTestCases Bug: 204830222 Change-Id: I251bb8a4431ad12ff61929879ef1363cf06b9244 --- .../app/usage/NetworkStatsManager.java | 5 +++ framework-t/src/android/net/TrafficStats.java | 42 ++++++++++--------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 683678ad46..8813f98451 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -157,6 +157,11 @@ public class NetworkStatsManager { setAugmentWithSubscriptionPlan(true); } + /** @hide */ + public INetworkStatsService getBinder() { + return mService; + } + /** * Set poll on open flag to indicate the poll is needed before service gets statistics * result. This is default enabled. However, for any non-privileged caller, the poll might diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java index 1af32bf552..c803a723ba 100644 --- a/framework-t/src/android/net/TrafficStats.java +++ b/framework-t/src/android/net/TrafficStats.java @@ -17,7 +17,6 @@ package android.net; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -27,8 +26,8 @@ import android.app.usage.NetworkStatsManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.media.MediaPlayer; +import android.os.Binder; import android.os.Build; -import android.os.IBinder; import android.os.RemoteException; import com.android.server.NetworkManagementSocketTagger; @@ -37,8 +36,6 @@ import dalvik.system.SocketTagger; import java.io.FileDescriptor; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.net.DatagramSocket; import java.net.Socket; import java.net.SocketException; @@ -177,25 +174,12 @@ public class TrafficStats { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562) private synchronized static INetworkStatsService getStatsService() { if (sStatsService == null) { - sStatsService = getStatsBinder(); + throw new IllegalStateException("TrafficStats not initialized, uid=" + + Binder.getCallingUid()); } return sStatsService; } - @Nullable - private static INetworkStatsService getStatsBinder() { - try { - final Method getServiceMethod = Class.forName("android.os.ServiceManager") - .getDeclaredMethod("getService", new Class[]{String.class}); - final IBinder binder = (IBinder) getServiceMethod.invoke( - null, Context.NETWORK_STATS_SERVICE); - return INetworkStatsService.Stub.asInterface(binder); - } catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException - | InvocationTargetException e) { - throw new NullPointerException("Cannot get INetworkStatsService: " + e); - } - } - /** * Snapshot of {@link NetworkStats} when the currently active profiling * session started, or {@code null} if no session active. @@ -209,6 +193,26 @@ public class TrafficStats { private static final String LOOPBACK_IFACE = "lo"; + /** + * Initialization {@link TrafficStats} with the context, to + * allow {@link TrafficStats} to fetch the needed binder. + * + * @param context a long-lived context, such as the application context or system + * server context. + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @SuppressLint("VisiblySynchronized") + public static synchronized void init(@NonNull final Context context) { + if (sStatsService != null) { + throw new IllegalStateException("TrafficStats is already initialized, uid=" + + Binder.getCallingUid()); + } + final NetworkStatsManager statsManager = + context.getSystemService(NetworkStatsManager.class); + sStatsService = statsManager.getBinder(); + } + /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. From 8efe3482f33d9df358c087a2f8fb9a1d5f0b09e4 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 17 Jan 2022 17:05:30 +0000 Subject: [PATCH 785/881] [MS61] Remove NetworkManagementSocketTagger#install dependency Expose TrafficStats#attachSocketTagger and use it instead. Test: atest TrafficStatsTest Bug: 204830222 CTS-Coverage-Bug: 214979748 Change-Id: I1748d349b499053ad08bd62202325fa759ad8da5 --- framework-t/src/android/net/TrafficStats.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java index c803a723ba..77b7f16671 100644 --- a/framework-t/src/android/net/TrafficStats.java +++ b/framework-t/src/android/net/TrafficStats.java @@ -16,6 +16,8 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -213,6 +215,18 @@ public class TrafficStats { sStatsService = statsManager.getBinder(); } + /** + * Attach the socket tagger implementation to the current process, to + * get notified when a socket's {@link FileDescriptor} is assigned to + * a thread. See {@link SocketTagger#set(SocketTagger)}. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static void attachSocketTagger() { + NetworkManagementSocketTagger.install(); + } + /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. From 103f53789d6054087b2644cb6bf7f740d3c01aa3 Mon Sep 17 00:00:00 2001 From: Les Lee Date: Thu, 20 Jan 2022 11:06:46 +0800 Subject: [PATCH 786/881] wifi data usage: Update calling API name Bug: 213387087 Test: atest -c FrameworksWifiApiTests Test: atest -c NetworkPolicyManagerServiceTest Merged-In: I02d7f57de1acfd7b03be0a3e1c957ec1e1c5b4d4 Change-Id: I02d7f57de1acfd7b03be0a3e1c957ec1e1c5b4d4 --- framework-t/src/android/net/NetworkIdentity.java | 6 +++--- framework-t/src/android/net/NetworkTemplate.java | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 9b9d38a360..a62aa519a9 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -206,7 +206,7 @@ public class NetworkIdentity implements Comparable { return mSubscriberId; } - /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getCurrentNetworkKey()}. */ + /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getNetworkKey()}. */ @Nullable public String getWifiNetworkKey() { return mWifiNetworkKey; @@ -375,7 +375,7 @@ public class NetworkIdentity implements Comparable { if (transportInfo instanceof WifiInfo) { final WifiInfo info = (WifiInfo) transportInfo; if (info != null) { - setWifiNetworkKey(info.getCurrentNetworkKey()); + setWifiNetworkKey(info.getNetworkKey()); } } } @@ -436,7 +436,7 @@ public class NetworkIdentity implements Comparable { * Set the Wifi Network Key. * * @param wifiNetworkKey Wifi Network Key of the network, - * see {@link WifiInfo#getCurrentNetworkKey()}. + * see {@link WifiInfo#getNetworkKey()}. * Or null if not applicable. * @return this builder. */ diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index a7e48d4363..cad80752b8 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -263,7 +263,7 @@ public final class NetworkTemplate implements Parcelable { * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the * given key of the wifi network. * - * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()} + * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()} * to know details about the key. * @hide */ @@ -283,7 +283,7 @@ public final class NetworkTemplate implements Parcelable { * Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless * of key of the wifi network. * - * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()} + * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()} * to know details about the key. * @param subscriberId the IMSI associated to this wifi network. * @@ -593,7 +593,7 @@ public final class NetworkTemplate implements Parcelable { /** * Get the set of Wifi Network Keys of the template. - * See {@link WifiInfo#getCurrentNetworkKey()}. + * See {@link WifiInfo#getNetworkKey()}. */ @NonNull public Set getWifiNetworkKeys() { @@ -729,7 +729,7 @@ public final class NetworkTemplate implements Parcelable { * Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is * empty. * - * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()} + * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()} * to know details about the key. */ private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) { @@ -1059,9 +1059,9 @@ public final class NetworkTemplate implements Parcelable { * the intention of matching any Wifi Network Key. * * @param wifiNetworkKeys the list of Wifi Network Key, - * see {@link WifiInfo#getCurrentNetworkKey()}. + * see {@link WifiInfo#getNetworkKey()}. * Or an empty list to match all networks. - * Note that {@code getCurrentNetworkKey()} might get null key + * Note that {@code getNetworkKey()} might get null key * when wifi disconnects. However, the caller should never invoke * this function with a null Wifi Network Key since such statistics * never exists. From 4489b71b9a158630cba9478301cc366bdb7c9f22 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Fri, 21 Jan 2022 12:41:45 +0000 Subject: [PATCH 787/881] [MS65.3] Address comments at aosp/1954383 This change also remove dependencies from NetworkPolicyManagerService. Test: atest NetworkIdentityTest#testBuilder \ NetworkPolicyManagerServiceTest Bug: 204830222 Change-Id: Ib1ec1968746d88165cbf5421d4ba30a00f4b678f --- .../src/android/net/NetworkIdentity.java | 69 +++++++++++++++---- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index a62aa519a9..ae0e8aa02e 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -16,6 +16,7 @@ package android.net; +import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; @@ -30,6 +31,7 @@ import android.telephony.Annotation; import android.telephony.TelephonyManager; import android.util.proto.ProtoOutputStream; +import com.android.net.module.util.CollectionUtils; import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.NetworkIdentityUtils; @@ -55,7 +57,7 @@ public class NetworkIdentity implements Comparable { /** @hide */ @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = { "OEM_MANAGED_" }, value = { + @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = { NetworkTemplate.OEM_MANAGED_NO, NetworkTemplate.OEM_MANAGED_PAID, NetworkTemplate.OEM_MANAGED_PRIVATE @@ -71,12 +73,14 @@ public class NetworkIdentity implements Comparable { * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}. * @hide */ - public static final int OEM_PAID = 0x1; + public static final int OEM_PAID = 1 << 0; /** * Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}. * @hide */ - public static final int OEM_PRIVATE = 0x2; + public static final int OEM_PRIVATE = 1 << 1; + + private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE; final int mType; final int mRatType; @@ -218,7 +222,7 @@ public class NetworkIdentity implements Comparable { return mRoaming; } - /** Return the roaming status of this instance. */ + /** Return whether this network is roaming. */ public boolean isRoaming() { return mRoaming; } @@ -229,7 +233,7 @@ public class NetworkIdentity implements Comparable { return mMetered; } - /** Return the meteredness of this instance. */ + /** Return whether this network is metered. */ public boolean isMetered() { return mMetered; } @@ -240,7 +244,7 @@ public class NetworkIdentity implements Comparable { return mDefaultNetwork; } - /** Return the default network status of this instance. */ + /** Return whether this network is the default network. */ public boolean isDefaultNetwork() { return mDefaultNetwork; } @@ -262,7 +266,7 @@ public class NetworkIdentity implements Comparable { * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable. * See {@code TelephonyManager.NETWORK_TYPE_*}. * @hide - * @deprecated See {@link NetworkIdentity#Builder}. + * @deprecated See {@link NetworkIdentity.Builder}. */ // TODO: Remove this after all callers are migrated to use new Api. @Deprecated @@ -270,8 +274,12 @@ public class NetworkIdentity implements Comparable { public static NetworkIdentity buildNetworkIdentity(Context context, @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, @Annotation.NetworkType int ratType) { - return new NetworkIdentity.Builder().setNetworkStateSnapshot(snapshot) - .setDefaultNetwork(defaultNetwork).setRatType(ratType).build(); + final NetworkIdentity.Builder builder = new NetworkIdentity.Builder() + .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork); + if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) { + builder.setRatType(ratType); + } + return builder.build(); } /** @@ -323,6 +331,11 @@ public class NetworkIdentity implements Comparable { * Builder class for {@link NetworkIdentity}. */ public static final class Builder { + // Need to be synchronized with ConnectivityManager. + // TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module. + private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST + private static final int MIN_NETWORK_TYPE = TYPE_MOBILE; + private int mType; private int mRatType; private String mSubscriberId; @@ -374,9 +387,7 @@ public class NetworkIdentity implements Comparable { .getTransportInfo(); if (transportInfo instanceof WifiInfo) { final WifiInfo info = (WifiInfo) transportInfo; - if (info != null) { - setWifiNetworkKey(info.getNetworkKey()); - } + setWifiNetworkKey(info.getNetworkKey()); } } return this; @@ -391,6 +402,12 @@ public class NetworkIdentity implements Comparable { */ @NonNull public Builder setType(int type) { + // Include TYPE_NONE for compatibility, type field might not be filled by some + // networks such as test networks. + if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type) + && type != ConnectivityManager.TYPE_NONE) { + throw new IllegalArgumentException("Invalid network type: " + type); + } mType = type; return this; } @@ -405,6 +422,10 @@ public class NetworkIdentity implements Comparable { */ @NonNull public Builder setRatType(@Annotation.NetworkType int ratType) { + if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType) + && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN) { + throw new IllegalArgumentException("Invalid ratType " + ratType); + } mRatType = ratType; return this; } @@ -447,7 +468,7 @@ public class NetworkIdentity implements Comparable { } /** - * Set the roaming. + * Set whether this network is roaming. * * @param roaming the roaming status of the network. * @return this builder. @@ -459,7 +480,7 @@ public class NetworkIdentity implements Comparable { } /** - * Set the meteredness. + * Set whether this network is metered. * * @param metered the meteredness of the network. * @return this builder. @@ -471,7 +492,7 @@ public class NetworkIdentity implements Comparable { } /** - * Set the default network status. + * Set whether this network is the default network. * * @param defaultNetwork the default network status of the network. * @return this builder. @@ -491,10 +512,27 @@ public class NetworkIdentity implements Comparable { */ @NonNull public Builder setOemManaged(@OemManaged int oemManaged) { + // Assert input does not contain illegal oemManage bits. + if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) { + throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged); + } mOemManaged = oemManaged; return this; } + private void ensureValidParameters() { + // Assert non-mobile network cannot have a ratType. + if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) { + throw new IllegalArgumentException( + "Invalid ratType " + mRatType + " for type " + mType); + } + + // Assert non-wifi network cannot have a wifi network key. + if (mType != TYPE_WIFI && mWifiNetworkKey != null) { + throw new IllegalArgumentException("Invalid wifi network key for type " + mType); + } + } + /** * Builds the instance of the {@link NetworkIdentity}. * @@ -502,6 +540,7 @@ public class NetworkIdentity implements Comparable { */ @NonNull public NetworkIdentity build() { + ensureValidParameters(); return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered, mDefaultNetwork, mOemManaged); } From c0d66230eaccf03561ecf85fd2816c1b8b8305e7 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Sun, 16 Jan 2022 16:43:39 +0000 Subject: [PATCH 788/881] [MS56.1] Add NetworkStatsHistory#Builder NetworkStatsHistory will need to be exposed and constructed from the data migration tool in the follow-up changes. Add a Builder class to prevent from exposing internal array structures. Test: atest NetworkStatsHistoryTest#testBuilder Bug: 204830222 Change-Id: I5f8ea1c825d601de0aac8623034ef896999fc1a0 --- .../src/android/net/NetworkStatsHistory.java | 230 +++++++++++++++++- 1 file changed, 229 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java index 90054c683d..a09b3bb7db 100644 --- a/framework-t/src/android/net/NetworkStatsHistory.java +++ b/framework-t/src/android/net/NetworkStatsHistory.java @@ -51,7 +51,9 @@ import java.io.DataOutput; import java.io.IOException; import java.io.PrintWriter; import java.net.ProtocolException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Random; /** @@ -97,23 +99,157 @@ public final class NetworkStatsHistory implements Parcelable { private long[] operations; private long totalBytes; - public static class Entry { + /** @hide */ + public NetworkStatsHistory(long bucketDuration, long[] bucketStart, long[] activeTime, + long[] rxBytes, long[] rxPackets, long[] txBytes, long[] txPackets, + long[] operations, int bucketCount, long totalBytes) { + this.bucketDuration = bucketDuration; + this.bucketStart = bucketStart; + this.activeTime = activeTime; + this.rxBytes = rxBytes; + this.rxPackets = rxPackets; + this.txBytes = txBytes; + this.txPackets = txPackets; + this.operations = operations; + this.bucketCount = bucketCount; + this.totalBytes = totalBytes; + } + + /** + * An instance to represent a single record in a {@link NetworkStatsHistory} object. + */ + public static final class Entry { + /** @hide */ public static final long UNKNOWN = -1; + /** @hide */ + // TODO: Migrate all callers to get duration from the history object and remove this field. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketDuration; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long bucketStart; + /** @hide */ public long activeTime; + /** @hide */ @UnsupportedAppUsage public long rxBytes; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long rxPackets; + /** @hide */ @UnsupportedAppUsage public long txBytes; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public long txPackets; + /** @hide */ public long operations; + /** @hide */ + Entry() {} + + /** + * Construct a {@link Entry} instance to represent a single record in a + * {@link NetworkStatsHistory} object. + * + * @param bucketStart Start of period for this {@link Entry}, in milliseconds since the + * Unix epoch, see {@link java.lang.System#currentTimeMillis}. + * @param activeTime Active time for this {@link Entry}, in milliseconds. + * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param rxPackets Number of packets received for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should + * represent the contents of IP packets, including IP headers. + * @param operations count of network operations performed for this {@link Entry}. This can + * be used to derive bytes-per-operation. + */ + public Entry(long bucketStart, long activeTime, long rxBytes, + long rxPackets, long txBytes, long txPackets, long operations) { + this.bucketStart = bucketStart; + this.activeTime = activeTime; + this.rxBytes = rxBytes; + this.rxPackets = rxPackets; + this.txBytes = txBytes; + this.txPackets = txPackets; + this.operations = operations; + } + + /** + * Get start timestamp of the bucket's time interval, in milliseconds since the Unix epoch. + */ + public long getBucketStart() { + return bucketStart; + } + + /** + * Get active time of the bucket's time interval, in milliseconds. + */ + public long getActiveTime() { + return activeTime; + } + + /** Get number of bytes received for this {@link Entry}. */ + public long getRxBytes() { + return rxBytes; + } + + /** Get number of packets received for this {@link Entry}. */ + public long getRxPackets() { + return rxPackets; + } + + /** Get number of bytes transmitted for this {@link Entry}. */ + public long getTxBytes() { + return txBytes; + } + + /** Get number of packets transmitted for this {@link Entry}. */ + public long getTxPackets() { + return txPackets; + } + + /** Get count of network operations performed for this {@link Entry}. */ + public long getOperations() { + return operations; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o.getClass() != getClass()) return false; + Entry entry = (Entry) o; + return bucketStart == entry.bucketStart + && activeTime == entry.activeTime && rxBytes == entry.rxBytes + && rxPackets == entry.rxPackets && txBytes == entry.txBytes + && txPackets == entry.txPackets && operations == entry.operations; + } + + @Override + public int hashCode() { + return (int) (bucketStart * 2 + + activeTime * 3 + + rxBytes * 5 + + rxPackets * 7 + + txBytes * 11 + + txPackets * 13 + + operations * 17); + } + + @Override + public String toString() { + return "Entry{" + + "bucketStart=" + bucketStart + + ", activeTime=" + activeTime + + ", rxBytes=" + rxBytes + + ", rxPackets=" + rxPackets + + ", txBytes=" + txBytes + + ", txPackets=" + txPackets + + ", operations=" + operations + + "}"; + } } /** @hide */ @@ -324,6 +460,22 @@ public final class NetworkStatsHistory implements Parcelable { return entry; } + /** + * Get List of {@link Entry} of the {@link NetworkStatsHistory} instance. + * + * @return + */ + @NonNull + public List getEntries() { + // TODO: Return a wrapper that uses this list instead, to prevent the returned result + // from being changed. + final ArrayList ret = new ArrayList<>(size()); + for (int i = 0; i < size(); i++) { + ret.add(getValues(i, null /* recycle */)); + } + return ret; + } + /** @hide */ public void setValues(int i, Entry entry) { // Unwind old values @@ -928,4 +1080,80 @@ public final class NetworkStatsHistory implements Parcelable { } } + /** + * Builder class for {@link NetworkStatsHistory}. + */ + public static final class Builder { + private final long mBucketDuration; + private final List mBucketStart; + private final List mActiveTime; + private final List mRxBytes; + private final List mRxPackets; + private final List mTxBytes; + private final List mTxPackets; + private final List mOperations; + + /** + * Creates a new Builder with given bucket duration and initial capacity to construct + * {@link NetworkStatsHistory} objects. + * + * @param bucketDuration Duration of the buckets of the object, in milliseconds. + * @param initialCapacity Estimated number of records. + */ + public Builder(long bucketDuration, int initialCapacity) { + mBucketDuration = bucketDuration; + mBucketStart = new ArrayList<>(initialCapacity); + mActiveTime = new ArrayList<>(initialCapacity); + mRxBytes = new ArrayList<>(initialCapacity); + mRxPackets = new ArrayList<>(initialCapacity); + mTxBytes = new ArrayList<>(initialCapacity); + mTxPackets = new ArrayList<>(initialCapacity); + mOperations = new ArrayList<>(initialCapacity); + } + + /** + * Add an {@link Entry} into the {@link NetworkStatsHistory} instance. + * + * @param entry The target {@link Entry} object. + * @return The builder object. + */ + @NonNull + public Builder addEntry(@NonNull Entry entry) { + mBucketStart.add(entry.bucketStart); + mActiveTime.add(entry.activeTime); + mRxBytes.add(entry.rxBytes); + mRxPackets.add(entry.rxPackets); + mTxBytes.add(entry.txBytes); + mTxPackets.add(entry.txPackets); + mOperations.add(entry.operations); + return this; + } + + private static long sum(@NonNull List list) { + long sum = 0; + for (long entry : list) { + sum += entry; + } + return sum; + } + + /** + * Builds the instance of the {@link NetworkStatsHistory}. + * + * @return the built instance of {@link NetworkStatsHistory}. + */ + @NonNull + public NetworkStatsHistory build() { + return new NetworkStatsHistory(mBucketDuration, + CollectionUtils.toLongArray(mBucketStart), + CollectionUtils.toLongArray(mActiveTime), + CollectionUtils.toLongArray(mRxBytes), + CollectionUtils.toLongArray(mRxPackets), + CollectionUtils.toLongArray(mTxBytes), + CollectionUtils.toLongArray(mTxPackets), + CollectionUtils.toLongArray(mOperations), + mBucketStart.size(), + sum(mRxBytes) + sum(mTxBytes)); + } + } } From ed76c1b8ea2d40c1f2ea44d4e0157b2a57400cf2 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Tue, 28 Dec 2021 06:33:23 +0000 Subject: [PATCH 789/881] Move Ethernet related files to f/b/packages/ConnectivityT. ethernet-service is going to be moved into Connectivity mainline module. Notice that below sources are also only used in the ethernet framework during compiling the filegroup: framework-connectivity-ethernet-sources. Move them from f/b to f/b/packages/ConnectivityT as well. Ethernet framework only related files: - IInternalNetworkManagementListener.aidl - InternalNetworkManagementException.java - InternalNetworkManagementException.aidl - InternalNetworkUpdateRequest.java - InternalNetworkUpdateRequest.aidl Ethernet service only related files: - DelayedDiskWrite.java(IpConfigStore imports this class) Bug: 210586283 Test: build pass atest FrameworksNetTests atest EthernetServiceTests Change-Id: I1ec2d1d182c04f3f2acc9b757d5061ca749a4a3c --- framework-t/Sources.bp | 5 +++++ .../InternalNetworkManagementException.aidl | 0 .../InternalNetworkManagementException.java | 0 .../net/InternalNetworkUpdateRequest.aidl | 0 .../net/InternalNetworkUpdateRequest.java | 0 service-t/Sources.bp | 1 + .../android/server/net/DelayedDiskWrite.java | 22 ++++++++++++++++--- 7 files changed, 25 insertions(+), 3 deletions(-) rename {core/java => framework-t/src}/android/net/InternalNetworkManagementException.aidl (100%) rename {core/java => framework-t/src}/android/net/InternalNetworkManagementException.java (100%) rename {core/java => framework-t/src}/android/net/InternalNetworkUpdateRequest.aidl (100%) rename {core/java => framework-t/src}/android/net/InternalNetworkUpdateRequest.java (100%) rename {services/core/java => service-t/src}/com/android/server/net/DelayedDiskWrite.java (82%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index d3d8bba16c..223bdcdd9c 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -129,6 +129,11 @@ filegroup { "src/android/net/EthernetNetworkSpecifier.java", "src/android/net/IEthernetManager.aidl", "src/android/net/IEthernetServiceListener.aidl", + "src/android/net/IInternalNetworkManagementListener.aidl", + "src/android/net/InternalNetworkUpdateRequest.java", + "src/android/net/InternalNetworkUpdateRequest.aidl", + "src/android/net/InternalNetworkManagementException.java", + "src/android/net/InternalNetworkManagementException.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/framework-t/src/android/net/InternalNetworkManagementException.aidl similarity index 100% rename from core/java/android/net/InternalNetworkManagementException.aidl rename to framework-t/src/android/net/InternalNetworkManagementException.aidl diff --git a/core/java/android/net/InternalNetworkManagementException.java b/framework-t/src/android/net/InternalNetworkManagementException.java similarity index 100% rename from core/java/android/net/InternalNetworkManagementException.java rename to framework-t/src/android/net/InternalNetworkManagementException.java diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl similarity index 100% rename from core/java/android/net/InternalNetworkUpdateRequest.aidl rename to framework-t/src/android/net/InternalNetworkUpdateRequest.aidl diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/framework-t/src/android/net/InternalNetworkUpdateRequest.java similarity index 100% rename from core/java/android/net/InternalNetworkUpdateRequest.java rename to framework-t/src/android/net/InternalNetworkUpdateRequest.java diff --git a/service-t/Sources.bp b/service-t/Sources.bp index b261e165a1..36dd20054c 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -66,6 +66,7 @@ filegroup { filegroup { name: "services.connectivity-ethernet-sources", srcs: [ + "src/com/android/server/net/DelayedDiskWrite.java", "src/com/android/server/net/IpConfigStore.java", ], path: "src", diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/service-t/src/com/android/server/net/DelayedDiskWrite.java similarity index 82% rename from services/core/java/com/android/server/net/DelayedDiskWrite.java rename to service-t/src/com/android/server/net/DelayedDiskWrite.java index 8f09eb7c19..35dc455725 100644 --- a/services/core/java/com/android/server/net/DelayedDiskWrite.java +++ b/service-t/src/com/android/server/net/DelayedDiskWrite.java @@ -26,21 +26,37 @@ import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; +/** + * This class provides APIs to do a delayed data write to a given {@link OutputStream}. + */ public class DelayedDiskWrite { + private static final String TAG = "DelayedDiskWrite"; + private HandlerThread mDiskWriteHandlerThread; private Handler mDiskWriteHandler; /* Tracks multiple writes on the same thread */ private int mWriteSequence = 0; - private final String TAG = "DelayedDiskWrite"; + /** + * Used to do a delayed data write to a given {@link OutputStream}. + */ public interface Writer { - public void onWriteCalled(DataOutputStream out) throws IOException; + /** + * write data to a given {@link OutputStream}. + */ + void onWriteCalled(DataOutputStream out) throws IOException; } + /** + * Do a delayed data write to a given output stream opened from filePath. + */ public void write(final String filePath, final Writer w) { write(filePath, w, true); } + /** + * Do a delayed data write to a given output stream opened from filePath. + */ public void write(final String filePath, final Writer w, final boolean open) { if (TextUtils.isEmpty(filePath)) { throw new IllegalArgumentException("empty file path"); @@ -77,7 +93,7 @@ public class DelayedDiskWrite { if (out != null) { try { out.close(); - } catch (Exception e) {} + } catch (Exception e) { } } // Quit if no more writes sent From 0bb493e12e863a423710ecaa336c2b376905398d Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Sun, 16 Jan 2022 16:29:17 +0000 Subject: [PATCH 790/881] [MS58] Expose Apis which will be used by data migration utility This includes: 1. NetworkIdentity 2. NetworkIdentitySet 3. NetworkStatsHistory NetworkStatsCollection Apis will be exposed in a separate CL. Test: TH Bug: 204830222 Change-Id: I47b2d3ac3b86cb4e6879afaae34326ca3c050ffa --- .../src/android/net/NetworkIdentity.java | 49 +++++++++++++------ .../src/android/net/NetworkIdentitySet.java | 26 +++++----- .../android/net/NetworkStatsCollection.java | 27 ++++++---- .../src/android/net/NetworkStatsHistory.java | 4 +- 4 files changed, 68 insertions(+), 38 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index ae0e8aa02e..d3d5a087cc 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -16,6 +16,7 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; @@ -24,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; +import android.annotation.SystemApi; import android.content.Context; import android.net.wifi.WifiInfo; import android.service.NetworkIdentityProto; @@ -46,8 +48,8 @@ import java.util.Objects; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) -public class NetworkIdentity implements Comparable { +@SystemApi(client = MODULE_LIBRARIES) +public class NetworkIdentity { private static final String TAG = "NetworkIdentity"; /** @hide */ @@ -299,30 +301,30 @@ public class NetworkIdentity implements Comparable { return oemManaged; } - @Override - public int compareTo(@NonNull NetworkIdentity another) { - Objects.requireNonNull(another); - int res = Integer.compare(mType, another.mType); + /** @hide */ + public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) { + Objects.requireNonNull(right); + int res = Integer.compare(left.mType, right.mType); if (res == 0) { - res = Integer.compare(mRatType, another.mRatType); + res = Integer.compare(left.mRatType, right.mRatType); } - if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) { - res = mSubscriberId.compareTo(another.mSubscriberId); + if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) { + res = left.mSubscriberId.compareTo(right.mSubscriberId); } - if (res == 0 && mWifiNetworkKey != null && another.mWifiNetworkKey != null) { - res = mWifiNetworkKey.compareTo(another.mWifiNetworkKey); + if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) { + res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey); } if (res == 0) { - res = Boolean.compare(mRoaming, another.mRoaming); + res = Boolean.compare(left.mRoaming, right.mRoaming); } if (res == 0) { - res = Boolean.compare(mMetered, another.mMetered); + res = Boolean.compare(left.mMetered, right.mMetered); } if (res == 0) { - res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork); + res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork); } if (res == 0) { - res = Integer.compare(mOemManaged, another.mOemManaged); + res = Integer.compare(left.mOemManaged, right.mOemManaged); } return res; } @@ -362,7 +364,14 @@ public class NetworkIdentity implements Comparable { /** * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance. - * This is to read roaming, metered, wifikey... from the snapshot for convenience. + * This is a useful shorthand that will read from the snapshot and set the + * following fields, if they are set in the snapshot : + * - type + * - subscriberId + * - roaming + * - metered + * - oemManaged + * - wifiNetworkKey * * @param snapshot The target {@link NetworkStateSnapshot} object. * @return The builder object. @@ -415,6 +424,8 @@ public class NetworkIdentity implements Comparable { /** * Set the Radio Access Technology(RAT) type of the network. * + * No RAT type is specified by default. Call clearRatType to reset. + * * @param ratType the Radio Access Technology(RAT) type if applicable. See * {@code TelephonyManager.NETWORK_TYPE_*}. * @@ -470,6 +481,8 @@ public class NetworkIdentity implements Comparable { /** * Set whether this network is roaming. * + * This field is false by default. Call with false to reset. + * * @param roaming the roaming status of the network. * @return this builder. */ @@ -482,6 +495,8 @@ public class NetworkIdentity implements Comparable { /** * Set whether this network is metered. * + * This field is false by default. Call with false to reset. + * * @param metered the meteredness of the network. * @return this builder. */ @@ -494,6 +509,8 @@ public class NetworkIdentity implements Comparable { /** * Set whether this network is the default network. * + * This field is false by default. Call with false to reset. + * * @param defaultNetwork the default network status of the network. * @return this builder. */ diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java index 041f070512..dfa347f6f1 100644 --- a/framework-t/src/android/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -27,6 +27,7 @@ import java.io.DataOutput; import java.io.IOException; import java.util.HashSet; import java.util.Objects; +import java.util.Set; /** * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} @@ -34,9 +35,7 @@ import java.util.Objects; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) -public class NetworkIdentitySet extends HashSet implements - Comparable { +public class NetworkIdentitySet extends HashSet { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_ROAMING = 2; private static final int VERSION_ADD_NETWORK_ID = 3; @@ -51,6 +50,11 @@ public class NetworkIdentitySet extends HashSet implements super(); } + /** @hide */ + public NetworkIdentitySet(@NonNull Set ident) { + super(ident); + } + /** @hide */ public NetworkIdentitySet(DataInput in) throws IOException { final int version = in.readInt(); @@ -189,15 +193,15 @@ public class NetworkIdentitySet extends HashSet implements } } - @Override - public int compareTo(@NonNull NetworkIdentitySet another) { - Objects.requireNonNull(another); - if (isEmpty()) return -1; - if (another.isEmpty()) return 1; + public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) { + Objects.requireNonNull(left); + Objects.requireNonNull(right); + if (left.isEmpty()) return -1; + if (right.isEmpty()) return 1; - final NetworkIdentity ident = iterator().next(); - final NetworkIdentity anotherIdent = another.iterator().next(); - return ident.compareTo(anotherIdent); + final NetworkIdentity leftIdent = left.iterator().next(); + final NetworkIdentity rightIdent = right.iterator().next(); + return NetworkIdentity.compare(leftIdent, rightIdent); } /** diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index f169fed6b9..58ca21fdfa 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -72,6 +72,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Objects; +import java.util.Set; /** * Collection of {@link NetworkStatsHistory}, stored based on combined key of @@ -702,7 +703,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private ArrayList getSortedKeys() { final ArrayList keys = new ArrayList<>(); keys.addAll(mStats.keySet()); - Collections.sort(keys); + Collections.sort(keys, (left, right) -> Key.compare(left, right)); return keys; } @@ -812,7 +813,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * the identifier that associate with the {@link NetworkStatsHistory} object to identify * a certain record in the {@link NetworkStatsCollection} object. */ - public static class Key implements Comparable { + public static class Key { /** @hide */ public final NetworkIdentitySet ident; /** @hide */ @@ -832,6 +833,11 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * @param set Set of the record, see {@code NetworkStats#SET_*}. * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}. */ + public Key(@NonNull Set ident, int uid, int set, int tag) { + this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag); + } + + /** @hide */ public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) { this.ident = Objects.requireNonNull(ident); this.uid = uid; @@ -855,21 +861,22 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W return false; } - @Override - public int compareTo(@NonNull Key another) { - Objects.requireNonNull(another); + /** @hide */ + public static int compare(@NonNull Key left, @NonNull Key right) { + Objects.requireNonNull(left); + Objects.requireNonNull(right); int res = 0; - if (ident != null && another.ident != null) { - res = ident.compareTo(another.ident); + if (left.ident != null && right.ident != null) { + res = NetworkIdentitySet.compare(left.ident, right.ident); } if (res == 0) { - res = Integer.compare(uid, another.uid); + res = Integer.compare(left.uid, right.uid); } if (res == 0) { - res = Integer.compare(set, another.set); + res = Integer.compare(left.set, right.set); } if (res == 0) { - res = Integer.compare(tag, another.tag); + res = Integer.compare(left.tag, right.tag); } return res; } diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java index a09b3bb7db..78c137073a 100644 --- a/framework-t/src/android/net/NetworkStatsHistory.java +++ b/framework-t/src/android/net/NetworkStatsHistory.java @@ -16,6 +16,7 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; @@ -31,6 +32,7 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; @@ -67,7 +69,7 @@ import java.util.Random; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) +@SystemApi(client = MODULE_LIBRARIES) public final class NetworkStatsHistory implements Parcelable { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_PACKETS = 2; From 8ead2283290893937ab6024b8f9a5968e054e82c Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Mon, 24 Jan 2022 07:45:37 +0000 Subject: [PATCH 791/881] Replace the NetdService usage in the EthernetService. Ethernet service related files are going to be moved into Connectivity module. NetdService won't be visible to EthernetService. Use asInterface to get the Netd service instead. Bug: 210586283 Test: m Change-Id: I3bf504cd947f74bf5830659915483fe5331ac9eb --- .../src/com/android/server/ethernet/EthernetService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetService.java b/service-t/src/com/android/server/ethernet/EthernetService.java index 492a55aff1..e6fee9e7bc 100644 --- a/service-t/src/com/android/server/ethernet/EthernetService.java +++ b/service-t/src/com/android/server/ethernet/EthernetService.java @@ -18,7 +18,6 @@ package com.android.server.ethernet; import android.content.Context; import android.net.INetd; -import android.net.util.NetdService; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -41,11 +40,12 @@ public final class EthernetService extends SystemService { final EthernetNetworkFactory factory = new EthernetNetworkFactory(handler, context); mImpl = new EthernetServiceImpl( context, handler, - new EthernetTracker(context, handler, factory, getNetd())); + new EthernetTracker(context, handler, factory, getNetd(context))); } - private INetd getNetd() { - final INetd netd = NetdService.getInstance(); + private INetd getNetd(Context context) { + final INetd netd = + INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)); Objects.requireNonNull(netd, "could not get netd instance"); return netd; } From c28dd15332ec595b318a1eea15798db2b9814602 Mon Sep 17 00:00:00 2001 From: junyulai Date: Sun, 23 Jan 2022 17:20:19 +0800 Subject: [PATCH 792/881] [MS38] Remove android.os.HandlerExecutor dependencies Mainline module can't use internal HandlerExecutor, so inline the implementation instead. Test: atest FrameworksNetTests NetworkPolicyManagerServiceTest Bug: 204830222 Change-Id: I54c2258cb3cee5fb862409441de293d6fed6b32c --- .../src/com/android/server/net/NetworkStatsService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 9b90f3b545..1105de3dd9 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -106,7 +106,6 @@ import android.os.Binder; import android.os.DropBoxManager; import android.os.Environment; import android.os.Handler; -import android.os.HandlerExecutor; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; @@ -450,7 +449,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { handlerThread.start(); mHandler = new NetworkStatsHandler(handlerThread.getLooper()); mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, - new HandlerExecutor(mHandler), this); + (command) -> mHandler.post(command) , this); mContentResolver = mContext.getContentResolver(); mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, mNetworkStatsSubscriptionsMonitor); @@ -557,7 +556,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // watch for tethering changes final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class); tetheringManager.registerTetheringEventCallback( - new HandlerExecutor(mHandler), mTetherListener); + (command) -> mHandler.post(command), mTetherListener); // listen for periodic polling events final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); From 18a2105afa1c1961951b2eaa68a2cf16fe7f4ad2 Mon Sep 17 00:00:00 2001 From: junyulai Date: Sun, 23 Jan 2022 01:22:16 +0800 Subject: [PATCH 793/881] [MS67.1] Expose registerUsageCallback with template Test: atest FrameworksNetTests Bug: 204830222 Change-Id: I643e2d96144210852fc8916ec9c483f2b207a48b --- .../app/usage/NetworkStatsManager.java | 145 +++++++++++------- .../src/android/net/INetworkStatsService.aidl | 3 +- .../android/net/netstats/IUsageCallback.aidl | 29 ++++ .../server/net/NetworkStatsObservers.java | 56 ++++--- .../server/net/NetworkStatsService.java | 13 +- 5 files changed, 155 insertions(+), 91 deletions(-) create mode 100644 framework-t/src/android/net/netstats/IUsageCallback.aidl diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 8813f98451..453e8e61bf 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -39,14 +40,11 @@ import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; +import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; -import android.os.Binder; import android.os.Build; import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.Messenger; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.text.TextUtils; @@ -57,6 +55,7 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; /** * Provides access to network usage history and statistics. Usage data is collected in @@ -723,26 +722,35 @@ public class NetworkStatsManager { } } - /** @hide */ - public void registerUsageCallback(NetworkTemplate template, int networkType, - long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { + /** + * Registers to receive notifications about data usage on specified networks. + * + *

The callbacks will continue to be called as long as the process is alive or + * {@link #unregisterUsageCallback} is called. + * + * @param template Template used to match networks. See {@link NetworkTemplate}. + * @param thresholdBytes Threshold in bytes to be notified on. + * @param executor The executor on which callback will be invoked. The provided {@link Executor} + * must run callback sequentially, otherwise the order of callbacks cannot be + * guaranteed. + * @param callback The {@link UsageCallback} that the system will call when data usage + * has exceeded the specified threshold. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes, + @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) { + Objects.requireNonNull(template, "NetworkTemplate cannot be null"); Objects.requireNonNull(callback, "UsageCallback cannot be null"); + Objects.requireNonNull(executor, "Executor cannot be null"); - final Looper looper; - if (handler == null) { - looper = Looper.myLooper(); - } else { - looper = handler.getLooper(); - } - - DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, + final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, template, thresholdBytes); try { - CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, - template.getSubscriberId(), callback); + final UsageCallbackWrapper callbackWrapper = + new UsageCallbackWrapper(executor, callback); callback.request = mService.registerUsageCallback( - mContext.getOpPackageName(), request, new Messenger(callbackHandler), - new Binder()); + mContext.getOpPackageName(), request, callbackWrapper); if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); if (callback.request == null) { @@ -795,12 +803,15 @@ public class NetworkStatsManager { NetworkTemplate template = createTemplate(networkType, subscriberId); if (DBG) { Log.d(TAG, "registerUsageCallback called with: {" - + " networkType=" + networkType - + " subscriberId=" + subscriberId - + " thresholdBytes=" + thresholdBytes - + " }"); + + " networkType=" + networkType + + " subscriberId=" + subscriberId + + " thresholdBytes=" + thresholdBytes + + " }"); } - registerUsageCallback(template, networkType, thresholdBytes, callback, handler); + + final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r); + + registerUsageCallback(template, thresholdBytes, executor, callback); } /** @@ -825,6 +836,26 @@ public class NetworkStatsManager { * Base class for usage callbacks. Should be extended by applications wanting notifications. */ public static abstract class UsageCallback { + /** + * Called when data usage has reached the given threshold. + * + * Called by {@code NetworkStatsService} when the registered threshold is reached. + * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system + * will not call {@link #onThresholdReached(int, String)}. + * + * @param template The {@link NetworkTemplate} that associated with this callback. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public void onThresholdReached(@NonNull NetworkTemplate template) { + // Backward compatibility for those who didn't override this function. + final int networkType = networkTypeForTemplate(template); + if (networkType != ConnectivityManager.TYPE_NONE) { + final String subscriberId = template.getSubscriberIds().isEmpty() ? null + : template.getSubscriberIds().iterator().next(); + onThresholdReached(networkType, subscriberId); + } + } /** * Called when data usage has reached the given threshold. @@ -835,6 +866,25 @@ public class NetworkStatsManager { * @hide used for internal bookkeeping */ private DataUsageRequest request; + + /** + * Get network type from a template if feasible. + * + * @param template the target {@link NetworkTemplate}. + * @return legacy network type, only supports for the types which is already supported in + * {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}. + * {@link ConnectivityManager#TYPE_NONE} for other types. + */ + private static int networkTypeForTemplate(@NonNull NetworkTemplate template) { + switch (template.getMatchRule()) { + case NetworkTemplate.MATCH_MOBILE: + return ConnectivityManager.TYPE_MOBILE; + case NetworkTemplate.MATCH_WIFI: + return ConnectivityManager.TYPE_WIFI; + default: + return ConnectivityManager.TYPE_NONE; + } + } } /** @@ -953,43 +1003,32 @@ public class NetworkStatsManager { } } - private static class CallbackHandler extends Handler { - private final int mNetworkType; - private final String mSubscriberId; - private UsageCallback mCallback; + private static class UsageCallbackWrapper extends IUsageCallback.Stub { + // Null if unregistered. + private volatile UsageCallback mCallback; - CallbackHandler(Looper looper, int networkType, String subscriberId, - UsageCallback callback) { - super(looper); - mNetworkType = networkType; - mSubscriberId = subscriberId; + private final Executor mExecutor; + + UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) { mCallback = callback; + mExecutor = executor; } @Override - public void handleMessage(Message message) { - DataUsageRequest request = - (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY); - - switch (message.what) { - case CALLBACK_LIMIT_REACHED: { - if (mCallback != null) { - mCallback.onThresholdReached(mNetworkType, mSubscriberId); - } else { - Log.e(TAG, "limit reached with released callback for " + request); - } - break; - } - case CALLBACK_RELEASED: { - if (DBG) Log.d(TAG, "callback released for " + request); - mCallback = null; - break; - } + public void onThresholdReached(DataUsageRequest request) { + // Copy it to a local variable in case mCallback changed inside the if condition. + final UsageCallback callback = mCallback; + if (callback != null) { + mExecutor.execute(() -> callback.onThresholdReached(request.template)); + } else { + Log.e(TAG, "onThresholdReached with released callback for " + request); } } - private static Object getObject(Message msg, String key) { - return msg.getData().getParcelable(key); + @Override + public void onCallbackReleased(DataUsageRequest request) { + if (DBG) Log.d(TAG, "callback released for " + request); + mCallback = null; } } diff --git a/framework-t/src/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl index da0aa99b93..efe626d3c9 100644 --- a/framework-t/src/android/net/INetworkStatsService.aidl +++ b/framework-t/src/android/net/INetworkStatsService.aidl @@ -24,6 +24,7 @@ import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; +import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.os.IBinder; @@ -71,7 +72,7 @@ interface INetworkStatsService { /** Registers a callback on data usage. */ DataUsageRequest registerUsageCallback(String callingPackage, - in DataUsageRequest request, in Messenger messenger, in IBinder binder); + in DataUsageRequest request, in IUsageCallback callback); /** Unregisters a callback on data usage. */ void unregisterUsageRequest(in DataUsageRequest request); diff --git a/framework-t/src/android/net/netstats/IUsageCallback.aidl b/framework-t/src/android/net/netstats/IUsageCallback.aidl new file mode 100644 index 0000000000..4e8a5b2309 --- /dev/null +++ b/framework-t/src/android/net/netstats/IUsageCallback.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.netstats; + +import android.net.DataUsageRequest; + +/** + * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback. + * + * @hide + */ +oneway interface IUsageCallback { + void onThresholdReached(in DataUsageRequest request); + void onCallbackReleased(in DataUsageRequest request); +} diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java index b57a4f920b..e85a59e8be 100644 --- a/service-t/src/com/android/server/net/NetworkStatsObservers.java +++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java @@ -26,13 +26,12 @@ import android.net.NetworkStatsAccess; import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; -import android.os.Bundle; +import android.net.netstats.IUsageCallback; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.Messenger; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; @@ -75,10 +74,10 @@ class NetworkStatsObservers { * * @return the normalized request wrapped within {@link RequestInfo}. */ - public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger, - IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) { + public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback, + int callingUid, @NetworkStatsAccess.Level int accessLevel) { DataUsageRequest request = buildRequest(inputRequest); - RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid, + RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid, accessLevel); if (LOGV) Log.v(TAG, "Registering observer for " + request); @@ -206,11 +205,10 @@ class NetworkStatsObservers { request.template, thresholdInBytes); } - private RequestInfo buildRequestInfo(DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, - @NetworkStatsAccess.Level int accessLevel) { + private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback, + int callingUid, @NetworkStatsAccess.Level int accessLevel) { if (accessLevel <= NetworkStatsAccess.Level.USER) { - return new UserUsageRequestInfo(this, request, messenger, binder, callingUid, + return new UserUsageRequestInfo(this, request, callback, callingUid, accessLevel); } else { // Safety check in case a new access level is added and we forgot to update this @@ -218,7 +216,7 @@ class NetworkStatsObservers { throw new IllegalArgumentException( "accessLevel " + accessLevel + " is less than DEVICESUMMARY."); } - return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid, + return new NetworkUsageRequestInfo(this, request, callback, callingUid, accessLevel); } } @@ -230,25 +228,23 @@ class NetworkStatsObservers { private abstract static class RequestInfo implements IBinder.DeathRecipient { private final NetworkStatsObservers mStatsObserver; protected final DataUsageRequest mRequest; - private final Messenger mMessenger; - private final IBinder mBinder; + private final IUsageCallback mCallback; protected final int mCallingUid; protected final @NetworkStatsAccess.Level int mAccessLevel; protected NetworkStatsRecorder mRecorder; protected NetworkStatsCollection mCollection; RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, + IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { mStatsObserver = statsObserver; mRequest = request; - mMessenger = messenger; - mBinder = binder; + mCallback = callback; mCallingUid = callingUid; mAccessLevel = accessLevel; try { - mBinder.linkToDeath(this, 0); + mCallback.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } @@ -257,7 +253,7 @@ class NetworkStatsObservers { @Override public void binderDied() { if (LOGV) { - Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")"); + Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")"); } mStatsObserver.unregister(mRequest, Process.SYSTEM_UID); callCallback(NetworkStatsManager.CALLBACK_RELEASED); @@ -270,9 +266,7 @@ class NetworkStatsObservers { } private void unlinkDeathRecipient() { - if (mBinder != null) { - mBinder.unlinkToDeath(this, 0); - } + mCallback.asBinder().unlinkToDeath(this, 0); } /** @@ -294,17 +288,19 @@ class NetworkStatsObservers { } private void callCallback(int callbackType) { - Bundle bundle = new Bundle(); - bundle.putParcelable(DataUsageRequest.PARCELABLE_KEY, mRequest); - Message msg = Message.obtain(); - msg.what = callbackType; - msg.setData(bundle); try { if (LOGV) { Log.v(TAG, "sending notification " + callbackTypeToName(callbackType) + " for " + mRequest); } - mMessenger.send(msg); + switch (callbackType) { + case NetworkStatsManager.CALLBACK_LIMIT_REACHED: + mCallback.onThresholdReached(mRequest); + break; + case NetworkStatsManager.CALLBACK_RELEASED: + mCallback.onCallbackReleased(mRequest); + break; + } } catch (RemoteException e) { // May occur naturally in the race of binder death. Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest); @@ -334,9 +330,9 @@ class NetworkStatsObservers { private static class NetworkUsageRequestInfo extends RequestInfo { NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, + IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { - super(statsObserver, request, messenger, binder, callingUid, accessLevel); + super(statsObserver, request, callback, callingUid, accessLevel); } @Override @@ -376,9 +372,9 @@ class NetworkStatsObservers { private static class UserUsageRequestInfo extends RequestInfo { UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, - Messenger messenger, IBinder binder, int callingUid, + IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { - super(statsObserver, request, messenger, binder, callingUid, accessLevel); + super(statsObserver, request, callback, callingUid, accessLevel); } @Override diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 1105de3dd9..1f87f7bf96 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -99,6 +99,7 @@ import android.net.TetheringManager; import android.net.TrafficStats; import android.net.UnderlyingNetworkInfo; import android.net.Uri; +import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; @@ -110,7 +111,6 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; -import android.os.Messenger; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceSpecificException; @@ -1136,21 +1136,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public DataUsageRequest registerUsageCallback(String callingPackage, - DataUsageRequest request, Messenger messenger, IBinder binder) { + public DataUsageRequest registerUsageCallback(@NonNull String callingPackage, + @NonNull DataUsageRequest request, @NonNull IUsageCallback callback) { Objects.requireNonNull(callingPackage, "calling package is null"); Objects.requireNonNull(request, "DataUsageRequest is null"); Objects.requireNonNull(request.template, "NetworkTemplate is null"); - Objects.requireNonNull(messenger, "messenger is null"); - Objects.requireNonNull(binder, "binder is null"); + Objects.requireNonNull(callback, "callback is null"); int callingUid = Binder.getCallingUid(); @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage); DataUsageRequest normalizedRequest; final long token = Binder.clearCallingIdentity(); try { - normalizedRequest = mStatsObservers.register(request, messenger, binder, - callingUid, accessLevel); + normalizedRequest = mStatsObservers.register( + request, callback, callingUid, accessLevel); } finally { Binder.restoreCallingIdentity(token); } From 9db383cf1d90aec2f2be7d40a3425fac38d3bad3 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 28 Dec 2021 03:23:02 +0800 Subject: [PATCH 794/881] Use public resouce in android.R package Use public resource since IpSec is planed to be moved into Connectivity mainline module. Bug: 204153604 Test: build Change-Id: I0aafef6b9b08307c3aebce597a2dd24925c6b09a Merged-In: I0aafef6b9b08307c3aebce597a2dd24925c6b09a --- framework-t/src/android/net/IpSecAlgorithm.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework-t/src/android/net/IpSecAlgorithm.java b/framework-t/src/android/net/IpSecAlgorithm.java index a84e7a9c63..10a22ac360 100644 --- a/framework-t/src/android/net/IpSecAlgorithm.java +++ b/framework-t/src/android/net/IpSecAlgorithm.java @@ -343,7 +343,7 @@ public final class IpSecAlgorithm implements Parcelable { // Load and validate the optional algorithm resource. Undefined or duplicate algorithms in // the resource are not allowed. final String[] resourceAlgos = systemResources.getStringArray( - com.android.internal.R.array.config_optionalIpSecAlgorithms); + android.R.array.config_optionalIpSecAlgorithms); for (String str : resourceAlgos) { if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) { // This error should be caught by CTS and never be thrown to API callers From f6487fb3c1ea11d42eaa3864ba53454a0dd0c2b5 Mon Sep 17 00:00:00 2001 From: junyulai Date: Sun, 23 Jan 2022 03:22:13 +0800 Subject: [PATCH 795/881] [MS68.1] Register usage callback from NetworkPolicyManagerService Use usage callback to replace the need of intent receiver. Test: atest TrafficStatsTest NetworkUsageStatsTest FrameworksNetTests Bug: 204830222 Change-Id: I40967c2b6c86d25c7db93e6d3a4908b72ed76154 --- .../src/android/app/usage/NetworkStatsManager.java | 3 ++- .../android/server/net/NetworkStatsObservers.java | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 453e8e61bf..28f930ff12 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -729,7 +729,8 @@ public class NetworkStatsManager { * {@link #unregisterUsageCallback} is called. * * @param template Template used to match networks. See {@link NetworkTemplate}. - * @param thresholdBytes Threshold in bytes to be notified on. + * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower + * than 2MiB will be clamped for non-privileged callers. * @param executor The executor on which callback will be invoked. The provided {@link Executor} * must run callback sequentially, otherwise the order of callbacks cannot be * guaranteed. diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java index e85a59e8be..19536247b2 100644 --- a/service-t/src/com/android/server/net/NetworkStatsObservers.java +++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java @@ -76,7 +76,7 @@ class NetworkStatsObservers { */ public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { - DataUsageRequest request = buildRequest(inputRequest); + DataUsageRequest request = buildRequest(inputRequest, callingUid); RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid, accessLevel); @@ -194,10 +194,12 @@ class NetworkStatsObservers { } } - private DataUsageRequest buildRequest(DataUsageRequest request) { - // Cap the minimum threshold to a safe default to avoid too many callbacks - long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes); - if (thresholdInBytes < request.thresholdInBytes) { + private DataUsageRequest buildRequest(DataUsageRequest request, int callingUid) { + // For non-system uid, cap the minimum threshold to a safe default to avoid too + // many callbacks. + long thresholdInBytes = (callingUid == Process.SYSTEM_UID ? request.thresholdInBytes + : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes)); + if (thresholdInBytes > request.thresholdInBytes) { Log.w(TAG, "Threshold was too low for " + request + ". Overriding to a safer default of " + thresholdInBytes + " bytes"); } From 82a33b8e6463c68900f484e64062469a501a5cdc Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 25 Jan 2022 07:40:06 +0000 Subject: [PATCH 796/881] [MS69.1] Fix TrafficStats.init crashs for supplemental process Supplemental apps has limited capabilities and service discovery is restricted. Hence, calling TrafficStats.init would result in crash. This change includes: 1. Print log instead of crashing process when running into any unexpected cases. Test: atest SupplementalProcessManagerTests Bug: 216062904 Change-Id: I7f827ccc485c997745779053b5936a6cb30e8219 --- framework-t/src/android/net/TrafficStats.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java index 77b7f16671..c2f0cdfb04 100644 --- a/framework-t/src/android/net/TrafficStats.java +++ b/framework-t/src/android/net/TrafficStats.java @@ -31,6 +31,7 @@ import android.media.MediaPlayer; import android.os.Binder; import android.os.Build; import android.os.RemoteException; +import android.util.Log; import com.android.server.NetworkManagementSocketTagger; @@ -212,6 +213,13 @@ public class TrafficStats { } final NetworkStatsManager statsManager = context.getSystemService(NetworkStatsManager.class); + if (statsManager == null) { + // TODO: Currently Process.isSupplemental is not working yet, because it depends on + // process to run in a certain UID range, which is not true for now. Change this + // to Log.wtf once Process.isSupplemental is ready. + Log.e(TAG, "TrafficStats not initialized, uid=" + Binder.getCallingUid()); + return; + } sStatsService = statsManager.getBinder(); } From 9d749d5128bea462bdd3001c5749fb8f1b95ee07 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 22 Jan 2022 22:29:24 +0800 Subject: [PATCH 797/881] [DU09-0]Adding the NetworkStatsCollection Builder The purpose is provide NetworkStatsCollection.Builder as public API for adding the stats {@link NetworkStatsHistory} Bug: 215862801 Test: atest NetworkStatsCollectionTest Change-Id: I65ad589473cbb7785cbe8297f793ce9f18a55c35 --- .../android/net/NetworkStatsCollection.java | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 58ca21fdfa..735c44d5c8 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -16,6 +16,7 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; import static android.net.NetworkStats.IFACE_ALL; @@ -34,6 +35,8 @@ import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRation import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.NetworkStatsHistory.Entry; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; import android.service.NetworkStatsCollectionProto; @@ -71,6 +74,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -80,7 +85,7 @@ import java.util.Set; * * @hide */ -// @SystemApi(client = MODULE_LIBRARIES) +@SystemApi(client = MODULE_LIBRARIES) public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer { private static final String TAG = NetworkStatsCollection.class.getSimpleName(); /** File header magic number: "ANET" */ @@ -809,6 +814,71 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W return false; } + /** + * Get the all historical stats of the collection {@link NetworkStatsCollection}. + * + * @return All {@link NetworkStatsHistory} in this collection. + */ + @NonNull + public Map getEntries() { + return new ArrayMap(mStats); + } + + /** + * Builder class for {@link NetworkStatsCollection}. + */ + public static final class Builder { + private final long mBucketDuration; + private final ArrayMap mEntries = new ArrayMap<>(); + + /** + * Creates a new Builder with given bucket duration. + * + * @param bucketDuration Duration of the buckets of the object, in milliseconds. + */ + public Builder(long bucketDuration) { + mBucketDuration = bucketDuration; + } + + /** + * Add association of the history with the specified key in this map. + * + * @param key The object used to identify a network, see {@link Key}. + * @param history {@link NetworkStatsHistory} instance associated to the given {@link Key}. + * @return The builder object. + */ + @NonNull + public NetworkStatsCollection.Builder addEntry(@NonNull Key key, + @NonNull NetworkStatsHistory history) { + Objects.requireNonNull(key); + Objects.requireNonNull(history); + final List historyEntries = history.getEntries(); + + final NetworkStatsHistory.Builder historyBuilder = + new NetworkStatsHistory.Builder(mBucketDuration, historyEntries.size()); + for (Entry entry : historyEntries) { + historyBuilder.addEntry(entry); + } + + mEntries.put(key, historyBuilder.build()); + return this; + } + + /** + * Builds the instance of the {@link NetworkStatsCollection}. + * + * @return the built instance of {@link NetworkStatsCollection}. + */ + @NonNull + public NetworkStatsCollection build() { + final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); + for (int i = 0; i < mEntries.size(); i++) { + collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i)); + } + return collection; + } + } + /** * the identifier that associate with the {@link NetworkStatsHistory} object to identify * a certain record in the {@link NetworkStatsCollection} object. From ad252f83473990880a6736e254ea5046ce843293 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 26 Jan 2022 01:11:08 +0800 Subject: [PATCH 798/881] [MS74] Expose NetworkTemplate#matches This is used by NetworkPolicyManagerService to find relevant networks of a given NetworkPolicy. Test: TH Bug: 204830222 Change-Id: I7176ab727bf208e0fd05ecb9c2bcb00cd3438031 --- framework-t/src/android/net/NetworkTemplate.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index cad80752b8..dba3991330 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -652,7 +652,9 @@ public final class NetworkTemplate implements Parcelable { * * @hide */ - public boolean matches(NetworkIdentity ident) { + @SystemApi(client = MODULE_LIBRARIES) + public boolean matches(@NonNull NetworkIdentity ident) { + Objects.requireNonNull(ident); if (!matchesMetered(ident)) return false; if (!matchesRoaming(ident)) return false; if (!matchesDefaultNetwork(ident)) return false; From ce3dbdb7418ade46f968fe685deab1f122761e5f Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 26 Jan 2022 07:33:13 +0000 Subject: [PATCH 799/881] [MS78.1] Fix NetworkIdentity#Builder crashing on 5G NSA networks Test: atest NetworkIdentityTest Fix: 216193400 Change-Id: Iaeae0c66f222ae8730439c5aedf5d5818855875d --- framework-t/src/android/net/NetworkIdentity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index d3d5a087cc..77fc17192c 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -434,7 +434,8 @@ public class NetworkIdentity { @NonNull public Builder setRatType(@Annotation.NetworkType int ratType) { if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType) - && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN) { + && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN + && ratType != NetworkTemplate.NETWORK_TYPE_5G_NSA) { throw new IllegalArgumentException("Invalid ratType " + ratType); } mRatType = ratType; From ad9ee7d92668114e4becbc85e7800466d75d249a Mon Sep 17 00:00:00 2001 From: markchien Date: Wed, 26 Jan 2022 22:39:07 +0800 Subject: [PATCH 800/881] Update UidCounterSetMap directly from NetworkStatsService Currently NetworkStatsService call NetworkManagementSocketTagger#setKernelCounterSet which would call into netd to update UidCounterSet bpf map. This change let NetworkStatsService get UidCounterSetMap and update it directly. After this change, NetworkManagementSocketTagger#setKernelCounterSet could be removed because NetworkStatsService is the only caller. Test: dump UidCounterSetMap to ensure it still have value after removing netd code. Change-Id: I7ae14106ded4fa55122e93e76c3057052a2fa33e --- .../server/net/NetworkStatsService.java | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 243d621647..874b1a06a5 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -60,7 +60,6 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport; import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; -import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; import android.annotation.NonNull; import android.annotation.Nullable; @@ -121,6 +120,7 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; +import android.system.ErrnoException; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionPlan; import android.text.TextUtils; @@ -139,10 +139,14 @@ import com.android.internal.util.FileRotator; import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.BestClock; import com.android.net.module.util.BinderUtils; +import com.android.net.module.util.BpfMap; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.IBpfMap; import com.android.net.module.util.LocationPermissionChecker; import com.android.net.module.util.NetworkStatsUtils; import com.android.net.module.util.PermissionUtils; +import com.android.net.module.util.Struct.U32; +import com.android.net.module.util.Struct.U8; import java.io.File; import java.io.FileDescriptor; @@ -207,6 +211,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final String NETSTATS_COMBINE_SUBTYPE_ENABLED = "netstats_combine_subtype_enabled"; + // This is current path but may be changed soon. + private static final String UID_COUNTERSET_MAP_PATH = + "/sys/fs/bpf/map_netd_uid_counterset_map"; + private final Context mContext; private final NetworkStatsFactory mStatsFactory; private final AlarmManager mAlarmManager; @@ -325,8 +333,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @GuardedBy("mStatsLock") private NetworkStatsCollection mXtStatsCached; - /** Current counter sets for each UID. */ + /** + * Current counter sets for each UID. + * TODO: maybe remove mActiveUidCounterSet and read UidCouneterSet value from mUidCounterSetMap + * directly ? But if mActiveUidCounterSet would be accessed very frequently, maybe keep + * mActiveUidCounterSet to avoid accessing kernel too frequently. + */ private SparseIntArray mActiveUidCounterSet = new SparseIntArray(); + private final IBpfMap mUidCounterSetMap; /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); @@ -459,6 +473,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext); mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler); mInterfaceMapUpdater.start(); + mUidCounterSetMap = mDeps.getUidCounterSetMap(); } /** @@ -520,6 +535,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @NonNull Context ctx, @NonNull Handler handler) { return new BpfInterfaceMapUpdater(ctx, handler); } + + /** Get counter sets map for each UID. */ + public IBpfMap getUidCounterSetMap() { + try { + return new BpfMap(UID_COUNTERSET_MAP_PATH, BpfMap.BPF_F_RDWR, + U32.class, U8.class); + } catch (ErrnoException e) { + Log.wtf(TAG, "Cannot create uid counter set map: " + e); + return null; + } + } } /** @@ -1077,6 +1103,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + private void setKernelCounterSet(int uid, int set) { + if (mUidCounterSetMap == null) { + Log.wtf(TAG, "Fail to set UidCounterSet: Null bpf map"); + return; + } + + if (set == SET_DEFAULT) { + try { + mUidCounterSetMap.deleteEntry(new U32(uid)); + } catch (ErrnoException e) { + Log.w(TAG, "UidCounterSetMap.deleteEntry(" + uid + ") failed with errno: " + e); + } + return; + } + + try { + mUidCounterSetMap.updateEntry(new U32(uid), new U8((short) set)); + } catch (ErrnoException e) { + Log.w(TAG, "UidCounterSetMap.updateEntry(" + uid + ", " + set + + ") failed with errno: " + e); + } + } + @VisibleForTesting public void setUidForeground(int uid, boolean uidForeground) { PermissionUtils.enforceNetworkStackPermission(mContext); From 0bfd365a4f5f3eed8e0279179a129939f3ed8b21 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 26 Jan 2022 23:27:19 +0800 Subject: [PATCH 801/881] Move NETWORK_TYPE_5G_NSA from NetworkTemplate to NetworkStatsManager Move NETWORK_TYPE_5G_NSA to NetworkStatsManager. Also expose it as module API so that it can be used out of module. Bug: 210073043 Test: builds, FrameworksNetTests Change-Id: I670c7e1405107bbe30b92fe1a8d81652c46de6d9 --- .../app/usage/NetworkStatsManager.java | 12 ++++++++++ .../src/android/net/NetworkIdentity.java | 3 ++- .../src/android/net/NetworkTemplate.java | 22 +++++++------------ .../net/NetworkStatsSubscriptionsMonitor.java | 2 +- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 28f930ff12..d7e513f121 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -145,6 +145,18 @@ public class NetworkStatsManager { /** @hide */ public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2; + /** + * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is + * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along + * with NR state as connected. This is a concept added by NetworkStats on top of the telephony + * constants for backward compatibility of metrics so this should not be overlapped with any of + * the {@code TelephonyManager.NETWORK_TYPE_*} constants. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int NETWORK_TYPE_5G_NSA = -2; + private int mFlags; /** @hide */ diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 77fc17192c..73b9c72699 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -26,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.app.usage.NetworkStatsManager; import android.content.Context; import android.net.wifi.WifiInfo; import android.service.NetworkIdentityProto; @@ -435,7 +436,7 @@ public class NetworkIdentity { public Builder setRatType(@Annotation.NetworkType int ratType) { if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType) && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN - && ratType != NetworkTemplate.NETWORK_TYPE_5G_NSA) { + && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) { throw new IllegalArgumentException("Invalid ratType " + ratType); } mRatType = ratType; diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index dba3991330..649f54b09e 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -41,6 +41,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.app.usage.NetworkStatsManager; import android.compat.annotation.UnsupportedAppUsage; import android.net.wifi.WifiInfo; import android.os.Build; @@ -136,15 +137,6 @@ public final class NetworkTemplate implements Parcelable { * {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync. */ public static final int NETWORK_TYPE_ALL = -1; - /** - * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is - * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along - * with NR state as connected. This should not be overlapped with any of the - * {@code TelephonyManager.NETWORK_TYPE_*} constants. - * - * @hide - */ - public static final int NETWORK_TYPE_5G_NSA = -2; /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -791,9 +783,10 @@ public final class NetworkTemplate implements Parcelable { return TelephonyManager.NETWORK_TYPE_LTE; case TelephonyManager.NETWORK_TYPE_NR: return TelephonyManager.NETWORK_TYPE_NR; - // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. - case NetworkTemplate.NETWORK_TYPE_5G_NSA: - return NetworkTemplate.NETWORK_TYPE_5G_NSA; + // Virtual RAT type for 5G NSA mode, see + // {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. + case NetworkStatsManager.NETWORK_TYPE_5G_NSA: + return NetworkStatsManager.NETWORK_TYPE_5G_NSA; default: return TelephonyManager.NETWORK_TYPE_UNKNOWN; } @@ -815,8 +808,9 @@ public final class NetworkTemplate implements Parcelable { } // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and // it is not in TelephonyManager#NETWORK_TYPE_* constants. - // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}. - collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA)); + // See {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. + collapsedRatTypes.add( + NetworkTemplate.getCollapsedRatType(NetworkStatsManager.NETWORK_TYPE_5G_NSA)); // Ensure that unknown type is returned. collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); return toIntArray(collapsedRatTypes); diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 4875f1cf5a..b6c3af5a7b 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -16,7 +16,7 @@ package com.android.server.net; -import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA; +import static android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA; import static android.net.NetworkTemplate.getCollapsedRatType; import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED; import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; From 1618171b38eff53ed568ef5164e1dbe683e6292f Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 27 Jan 2022 00:03:41 +0800 Subject: [PATCH 802/881] Move the implement of getAllCollapsedRatTypes to StatsPullAtomService To make data usage as a mainline module, move getAllCollapsedRatTypes to StatsPullAtomService since currently it is the only user. Also, the method needs to call getCollapsedRatType, thus move getCollapsedRatType to NetworkStatsManager and expose it as module API. Bug: 210073043 Test: builds, FrameworksNetTests Change-Id: Ibe41b50f173464694c21dd22841552bdb69a6a14 --- .../app/usage/NetworkStatsManager.java | 48 +++++++++++ .../src/android/net/NetworkTemplate.java | 86 +------------------ .../server/net/NetworkStatsService.java | 2 +- .../net/NetworkStatsSubscriptionsMonitor.java | 4 +- 4 files changed, 53 insertions(+), 87 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index d7e513f121..84adef53e4 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -1123,4 +1123,52 @@ public class NetworkStatsManager { throw e.rethrowFromSystemServer(); } } + + /** + * Get a RAT type representative of a group of RAT types for network statistics. + * + * Collapse the given Radio Access Technology (RAT) type into a bucket that + * is representative of the original RAT type for network statistics. The + * mapping mostly corresponds to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*} + * but with adaptations specific to the virtual types introduced by + * networks stats. + * + * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static int getCollapsedRatType(int ratType) { + switch (ratType) { + case TelephonyManager.NETWORK_TYPE_GPRS: + case TelephonyManager.NETWORK_TYPE_GSM: + case TelephonyManager.NETWORK_TYPE_EDGE: + case TelephonyManager.NETWORK_TYPE_IDEN: + case TelephonyManager.NETWORK_TYPE_CDMA: + case TelephonyManager.NETWORK_TYPE_1xRTT: + return TelephonyManager.NETWORK_TYPE_GSM; + case TelephonyManager.NETWORK_TYPE_EVDO_0: + case TelephonyManager.NETWORK_TYPE_EVDO_A: + case TelephonyManager.NETWORK_TYPE_EVDO_B: + case TelephonyManager.NETWORK_TYPE_EHRPD: + case TelephonyManager.NETWORK_TYPE_UMTS: + case TelephonyManager.NETWORK_TYPE_HSDPA: + case TelephonyManager.NETWORK_TYPE_HSUPA: + case TelephonyManager.NETWORK_TYPE_HSPA: + case TelephonyManager.NETWORK_TYPE_HSPAP: + case TelephonyManager.NETWORK_TYPE_TD_SCDMA: + return TelephonyManager.NETWORK_TYPE_UMTS; + case TelephonyManager.NETWORK_TYPE_LTE: + case TelephonyManager.NETWORK_TYPE_IWLAN: + return TelephonyManager.NETWORK_TYPE_LTE; + case TelephonyManager.NETWORK_TYPE_NR: + return TelephonyManager.NETWORK_TYPE_NR; + // Virtual RAT type for 5G NSA mode, see + // {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. + case NetworkStatsManager.NETWORK_TYPE_5G_NSA: + return NetworkStatsManager.NETWORK_TYPE_5G_NSA; + default: + return TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + } } diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 649f54b09e..27e717fb59 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -48,7 +48,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; -import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; @@ -59,9 +58,7 @@ import com.android.net.module.util.NetworkStatsUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; -import java.util.Collection; import java.util.Comparator; -import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; @@ -703,7 +700,8 @@ public final class NetworkTemplate implements Parcelable { private boolean matchesCollapsedRatType(NetworkIdentity ident) { return mRatType == NETWORK_TYPE_ALL - || getCollapsedRatType(mRatType) == getCollapsedRatType(ident.mRatType); + || NetworkStatsManager.getCollapsedRatType(mRatType) + == NetworkStatsManager.getCollapsedRatType(ident.mRatType); } /** @@ -746,86 +744,6 @@ public final class NetworkTemplate implements Parcelable { } } - /** - * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types. - * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}. - * - * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}. - * - * @hide - */ - // TODO: 1. Consider move this to TelephonyManager if used by other modules. - // 2. Consider make this configurable. - // 3. Use TelephonyManager APIs when available. - // TODO: @SystemApi when ready. - public static int getCollapsedRatType(int ratType) { - switch (ratType) { - case TelephonyManager.NETWORK_TYPE_GPRS: - case TelephonyManager.NETWORK_TYPE_GSM: - case TelephonyManager.NETWORK_TYPE_EDGE: - case TelephonyManager.NETWORK_TYPE_IDEN: - case TelephonyManager.NETWORK_TYPE_CDMA: - case TelephonyManager.NETWORK_TYPE_1xRTT: - return TelephonyManager.NETWORK_TYPE_GSM; - case TelephonyManager.NETWORK_TYPE_EVDO_0: - case TelephonyManager.NETWORK_TYPE_EVDO_A: - case TelephonyManager.NETWORK_TYPE_EVDO_B: - case TelephonyManager.NETWORK_TYPE_EHRPD: - case TelephonyManager.NETWORK_TYPE_UMTS: - case TelephonyManager.NETWORK_TYPE_HSDPA: - case TelephonyManager.NETWORK_TYPE_HSUPA: - case TelephonyManager.NETWORK_TYPE_HSPA: - case TelephonyManager.NETWORK_TYPE_HSPAP: - case TelephonyManager.NETWORK_TYPE_TD_SCDMA: - return TelephonyManager.NETWORK_TYPE_UMTS; - case TelephonyManager.NETWORK_TYPE_LTE: - case TelephonyManager.NETWORK_TYPE_IWLAN: - return TelephonyManager.NETWORK_TYPE_LTE; - case TelephonyManager.NETWORK_TYPE_NR: - return TelephonyManager.NETWORK_TYPE_NR; - // Virtual RAT type for 5G NSA mode, see - // {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. - case NetworkStatsManager.NETWORK_TYPE_5G_NSA: - return NetworkStatsManager.NETWORK_TYPE_5G_NSA; - default: - return TelephonyManager.NETWORK_TYPE_UNKNOWN; - } - } - - /** - * Return all supported collapsed RAT types that could be returned by - * {@link #getCollapsedRatType(int)}. - * - * @hide - */ - // TODO: @SystemApi when ready. - @NonNull - public static final int[] getAllCollapsedRatTypes() { - final int[] ratTypes = TelephonyManager.getAllNetworkTypes(); - final HashSet collapsedRatTypes = new HashSet<>(); - for (final int ratType : ratTypes) { - collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType)); - } - // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and - // it is not in TelephonyManager#NETWORK_TYPE_* constants. - // See {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}. - collapsedRatTypes.add( - NetworkTemplate.getCollapsedRatType(NetworkStatsManager.NETWORK_TYPE_5G_NSA)); - // Ensure that unknown type is returned. - collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN); - return toIntArray(collapsedRatTypes); - } - - @NonNull - private static int[] toIntArray(@NonNull Collection list) { - final int[] array = new int[list.size()]; - int i = 0; - for (final Integer item : list) { - array[i++] = item; - } - return array; - } - /** * Check if matches Wi-Fi network template. */ diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 243d621647..5c069e9d40 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -244,7 +244,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}. * When disabled, mobile data is broken down by a granular ratType representative of the - * actual ratType. {@see NetworkTemplate#getCollapsedRatType}. + * actual ratType. {@see android.app.usage.NetworkStatsManager#getCollapsedRatType}. * Enabling this decreases the level of detail but saves performance, disk space and * amount of data logged. */ diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index b6c3af5a7b..3e35e603e8 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -17,7 +17,7 @@ package com.android.server.net; import static android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA; -import static android.net.NetworkTemplate.getCollapsedRatType; +import static android.app.usage.NetworkStatsManager.getCollapsedRatType; import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED; import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; @@ -57,7 +57,7 @@ public class NetworkStatsSubscriptionsMonitor extends * * @param subscriberId IMSI of the subscription. * @param collapsedRatType collapsed RAT type. - * @see android.net.NetworkTemplate#getCollapsedRatType(int). + * @see android.app.usage.NetworkStatsManager#getCollapsedRatType(int). */ void onCollapsedRatTypeChanged(@NonNull String subscriberId, @Annotation.NetworkType int collapsedRatType); From de9b4def5feecba5d26fa899d97c8f62d2397ab9 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 27 Jan 2022 22:15:46 +0800 Subject: [PATCH 803/881] [DU12]Remove NetworkType Annotation Bug: 216619447 Test: atest NetworkTemplateTest NetworkStatsCollectionTest NetworkStatsSubscriptionsMonitorTest Change-Id: I58689201a684f581a4b88df058a5e0683da61926 --- framework-t/src/android/net/NetworkIdentity.java | 6 ++---- framework-t/src/android/net/NetworkTemplate.java | 5 ++--- .../server/net/NetworkStatsSubscriptionsMonitor.java | 4 +--- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 73b9c72699..56faa52e82 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -30,7 +30,6 @@ import android.app.usage.NetworkStatsManager; import android.content.Context; import android.net.wifi.WifiInfo; import android.service.NetworkIdentityProto; -import android.telephony.Annotation; import android.telephony.TelephonyManager; import android.util.proto.ProtoOutputStream; @@ -275,8 +274,7 @@ public class NetworkIdentity { @Deprecated @NonNull public static NetworkIdentity buildNetworkIdentity(Context context, - @NonNull NetworkStateSnapshot snapshot, - boolean defaultNetwork, @Annotation.NetworkType int ratType) { + @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) { final NetworkIdentity.Builder builder = new NetworkIdentity.Builder() .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork); if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) { @@ -433,7 +431,7 @@ public class NetworkIdentity { * @return this builder. */ @NonNull - public Builder setRatType(@Annotation.NetworkType int ratType) { + public Builder setRatType(int ratType) { if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType) && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) { diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 27e717fb59..9b58b016bb 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -47,7 +47,6 @@ import android.net.wifi.WifiInfo; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import android.telephony.Annotation.NetworkType; import android.text.TextUtils; import android.util.ArraySet; @@ -203,7 +202,7 @@ public final class NetworkTemplate implements Parcelable { * @hide */ public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId, - @NetworkType int ratType, int metered) { + int ratType, int metered) { if (TextUtils.isEmpty(subscriberId)) { return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */, null /* matchSubscriberIds */, @@ -1039,7 +1038,7 @@ public final class NetworkTemplate implements Parcelable { * @return this builder. */ @NonNull - public Builder setRatType(@NetworkType int ratType) { + public Builder setRatType(int ratType) { // Input will be validated with the match rule when building the template. mRatType = ratType; return this; diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 3e35e603e8..5bba0b17aa 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -24,7 +24,6 @@ import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; import android.annotation.NonNull; import android.content.Context; -import android.telephony.Annotation; import android.telephony.SubscriptionManager; import android.telephony.TelephonyCallback; import android.telephony.TelephonyDisplayInfo; @@ -59,8 +58,7 @@ public class NetworkStatsSubscriptionsMonitor extends * @param collapsedRatType collapsed RAT type. * @see android.app.usage.NetworkStatsManager#getCollapsedRatType(int). */ - void onCollapsedRatTypeChanged(@NonNull String subscriberId, - @Annotation.NetworkType int collapsedRatType); + void onCollapsedRatTypeChanged(@NonNull String subscriberId, int collapsedRatType); } private final Delegate mDelegate; From 741c5e64167776091e26bb43774db2dc4a6f70b9 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Thu, 13 Jan 2022 18:36:24 -0800 Subject: [PATCH 804/881] Updates so Network Mgmt Callbacks Are Sent Updates so that network management API updates in the ethernet stack can handle concurrent requests correctly in regards to notifying caller supplied callbacks. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I8073251b2c63309da031c2b1c98d61614deadfe8 --- .../ethernet/EthernetNetworkFactory.java | 163 ++++++++++++------ .../ethernet/EthernetNetworkFactoryTest.java | 126 ++++++++++++-- 2 files changed, 221 insertions(+), 68 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 7b727a3ce3..c610f00ab1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -22,10 +22,12 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; import android.net.IInternalNetworkManagementListener; +import android.net.InternalNetworkManagementException; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; import android.net.LinkProperties; +import android.net.Network; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; @@ -203,14 +205,9 @@ public class EthernetNetworkFactory extends NetworkFactory { @Nullable final IInternalNetworkManagementListener listener) { enforceInterfaceIsTracked(ifaceName); final NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName); - // TODO: The listener will have issues if called in quick succession for the same interface - // before the IP layer restarts. Update the listener logic to address multiple successive - // calls for a particular interface. - iface.mNetworkManagementListener = listener; - if (iface.updateInterface(ipConfig, capabilities)) { - mTrackingInterfaces.put(ifaceName, iface); - updateCapabilityFilter(); - } + iface.updateInterface(ipConfig, capabilities, listener); + mTrackingInterfaces.put(ifaceName, iface); + updateCapabilityFilter(); } private void enforceInterfaceIsTracked(@NonNull final String ifaceName) { @@ -247,6 +244,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void removeInterface(String interfaceName) { NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName); if (iface != null) { + iface.maybeSendNetworkManagementCallbackForAbort(); iface.stop(); } @@ -302,6 +300,21 @@ public class EthernetNetworkFactory extends NetworkFactory { return network; } + private static void maybeSendNetworkManagementCallback( + @Nullable final IInternalNetworkManagementListener listener, + @Nullable final Network network, + @Nullable final InternalNetworkManagementException e) { + if (null == listener) { + return; + } + + try { + listener.onComplete(network, e); + } catch (RemoteException re) { + Log.e(TAG, "Can't send onComplete for network management callback", re); + } + } + @VisibleForTesting static class NetworkInterfaceState { final String name; @@ -320,8 +333,7 @@ public class EthernetNetworkFactory extends NetworkFactory { private volatile @Nullable IpClientManager mIpClient; private @NonNull NetworkCapabilities mCapabilities; - private @Nullable IpClientCallbacksImpl mIpClientCallback; - private @Nullable IInternalNetworkManagementListener mNetworkManagementListener; + private @Nullable EthernetIpClientCallback mIpClientCallback; private @Nullable EthernetNetworkAgent mNetworkAgent; private @Nullable IpConfiguration mIpConfig; @@ -348,9 +360,14 @@ public class EthernetNetworkFactory extends NetworkFactory { long refCount = 0; - private class IpClientCallbacksImpl extends IpClientCallbacks { + private class EthernetIpClientCallback extends IpClientCallbacks { private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); + @Nullable IInternalNetworkManagementListener mNetworkManagementListener; + + EthernetIpClientCallback(@Nullable final IInternalNetworkManagementListener listener) { + mNetworkManagementListener = listener; + } @Override public void onIpClientCreated(IIpClient ipClient) { @@ -368,12 +385,12 @@ public class EthernetNetworkFactory extends NetworkFactory { @Override public void onProvisioningSuccess(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStarted(newLp)); + mHandler.post(() -> onIpLayerStarted(newLp, mNetworkManagementListener)); } @Override public void onProvisioningFailure(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStopped(newLp)); + mHandler.post(() -> onIpLayerStopped(mNetworkManagementListener)); } @Override @@ -431,30 +448,25 @@ public class EthernetNetworkFactory extends NetworkFactory { mLegacyType = getLegacyType(mCapabilities); } - boolean updateInterface(@NonNull final IpConfiguration ipConfig, - @Nullable final NetworkCapabilities capabilities) { - final boolean shouldUpdateIpConfig = !Objects.equals(mIpConfig, ipConfig); - final boolean shouldUpdateCapabilities = null != capabilities - && !Objects.equals(mCapabilities, capabilities); + void updateInterface(@NonNull final IpConfiguration ipConfig, + @Nullable final NetworkCapabilities capabilities, + @Nullable final IInternalNetworkManagementListener listener) { if (DBG) { Log.d(TAG, "updateInterface, iface: " + name - + ", shouldUpdateIpConfig: " + shouldUpdateIpConfig - + ", shouldUpdateCapabilities: " + shouldUpdateCapabilities + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig + ", capabilities: " + capabilities + ", old capabilities: " + mCapabilities + + ", listener: " + listener ); } - if (shouldUpdateIpConfig) { mIpConfig = ipConfig; }; - if (shouldUpdateCapabilities) { setCapabilities(capabilities); }; - if (shouldUpdateIpConfig || shouldUpdateCapabilities) { - // TODO: Update this logic to only do a restart if required. Although a restart may - // be required due to the capabilities or ipConfiguration values, not all - // capabilities changes require a restart. - restart(); - return true; - } - return false; + mIpConfig = ipConfig; + setCapabilities(capabilities); + // Send an abort callback if a request is filed before the previous one has completed. + maybeSendNetworkManagementCallbackForAbort(); + // TODO: Update this logic to only do a restart if required. Although a restart may + // be required due to the capabilities or ipConfiguration values, not all + // capabilities changes require a restart. + restart(listener); } boolean isRestricted() { @@ -462,6 +474,10 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void start() { + start(null); + } + + private void start(@Nullable final IInternalNetworkManagementListener listener) { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); return; @@ -470,9 +486,10 @@ public class EthernetNetworkFactory extends NetworkFactory { Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name)); } - mIpClientCallback = new IpClientCallbacksImpl(); + mIpClientCallback = new EthernetIpClientCallback(listener); mDeps.makeIpClient(mContext, name, mIpClientCallback); mIpClientCallback.awaitIpClientStart(); + if (sTcpBufferSizes == null) { sTcpBufferSizes = mContext.getResources().getString( com.android.internal.R.string.config_ethernet_tcp_buffers); @@ -480,8 +497,13 @@ public class EthernetNetworkFactory extends NetworkFactory { provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes); } - void onIpLayerStarted(LinkProperties linkProperties) { + void onIpLayerStarted(@NonNull final LinkProperties linkProperties, + @Nullable final IInternalNetworkManagementListener listener) { if(mIpClient == null) { + // This call comes from a message posted on the handler thread, but the IpClient has + // since been stopped such as may be the case if updateInterfaceLinkState() is + // queued on the handler thread prior. As network management callbacks are sent in + // stop(), there is no need to send them again here. if (DBG) Log.d(TAG, "IpClient is not initialized."); return; } @@ -516,33 +538,53 @@ public class EthernetNetworkFactory extends NetworkFactory { }); mNetworkAgent.register(); mNetworkAgent.markConnected(); - sendNetworkManagementCallback(); + realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null); } - private void sendNetworkManagementCallback() { - if (null != mNetworkManagementListener) { - try { - mNetworkManagementListener.onComplete(mNetworkAgent.getNetwork(), null); - } catch (RemoteException e) { - Log.e(TAG, "Can't send onComplete for network management callback", e); - } finally { - mNetworkManagementListener = null; - } - } - } - - void onIpLayerStopped(LinkProperties linkProperties) { + void onIpLayerStopped(@Nullable final IInternalNetworkManagementListener listener) { + // This cannot happen due to provisioning timeout, because our timeout is 0. It can + // happen due to errors while provisioning or on provisioning loss. if(mIpClient == null) { if (DBG) Log.d(TAG, "IpClient is not initialized."); return; } - // This cannot happen due to provisioning timeout, because our timeout is 0. It can only - // happen if we're provisioned and we lose provisioning. - stop(); - // If the interface has disappeared provisioning will fail over and over again, so - // there is no point in starting again - if (null != mDeps.getNetworkInterfaceByName(name)) { - start(); + // There is no point in continuing if the interface is gone as stop() will be triggered + // by removeInterface() when processed on the handler thread and start() won't + // work for a non-existent interface. + if (null == mDeps.getNetworkInterfaceByName(name)) { + if (DBG) Log.d(TAG, name + " is no longer available."); + // Send a callback in case a provisioning request was in progress. + maybeSendNetworkManagementCallbackForAbort(); + return; + } + restart(listener); + } + + private void maybeSendNetworkManagementCallbackForAbort() { + realizeNetworkManagementCallback(null, + new InternalNetworkManagementException( + "The IP provisioning request has been aborted.")); + } + + // Must be called on the handler thread + private void realizeNetworkManagementCallback(@Nullable final Network network, + @Nullable final InternalNetworkManagementException e) { + ensureRunningOnEthernetHandlerThread(); + if (null == mIpClientCallback) { + return; + } + + EthernetNetworkFactory.maybeSendNetworkManagementCallback( + mIpClientCallback.mNetworkManagementListener, network, e); + // Only send a single callback per listener. + mIpClientCallback.mNetworkManagementListener = null; + } + + private void ensureRunningOnEthernetHandlerThread() { + if (mHandler.getLooper().getThread() != Thread.currentThread()) { + throw new IllegalStateException( + "Not running on the Ethernet thread: " + + Thread.currentThread().getName()); } } @@ -577,8 +619,11 @@ public class EthernetNetworkFactory extends NetworkFactory { if (mLinkUp == up) return false; mLinkUp = up; - stop(); - if (up) { + if (!up) { // was up, goes down + maybeSendNetworkManagementCallbackForAbort(); + stop(); + } else { // was down, goes up + stop(); start(); } @@ -627,10 +672,14 @@ public class EthernetNetworkFactory extends NetworkFactory { .build(); } - void restart(){ + void restart() { + restart(null); + } + + void restart(@Nullable final IInternalNetworkManagementListener listener){ if (DBG) Log.d(TAG, "reconnecting Ethernet"); stop(); - start(); + start(listener); } @Override diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 52ddf3c8ad..d569990a18 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -16,8 +16,11 @@ package com.android.server.ethernet; +import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -63,6 +66,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.R; import com.android.net.module.util.InterfaceParams; +import com.android.testutils.DevSdkIgnoreRule; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -72,9 +77,7 @@ import org.mockito.MockitoAnnotations; import java.util.Objects; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; @RunWith(AndroidJUnit4.class) @SmallTest @@ -84,7 +87,7 @@ public class EthernetNetworkFactoryTest { private static final String IP_ADDR = "192.0.2.2/25"; private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); private static final String HW_ADDR = "01:02:03:04:05:06"; - private final TestLooper mLooper = new TestLooper(); + private TestLooper mLooper; private Handler mHandler; private EthernetNetworkFactory mNetFactory = null; private IpClientCallbacks mIpClientCallbacks; @@ -99,14 +102,18 @@ public class EthernetNetworkFactoryTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mHandler = new Handler(mLooper.getLooper()); - mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mDeps); - setupNetworkAgentMock(); setupIpClientMock(); setupContext(); } + //TODO: Move away from usage of TestLooper in order to move this logic back into @Before. + private void initEthernetNetworkFactory() { + mLooper = new TestLooper(); + mHandler = new Handler(mLooper.getLooper()); + mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mDeps); + } + private void setupNetworkAgentMock() { when(mDeps.makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any())) .thenAnswer(new AnswerWithArguments() { @@ -288,6 +295,7 @@ public class EthernetNetworkFactoryTest { @Test public void testAcceptRequest() throws Exception { + initEthernetNetworkFactory(); createInterfaceUndergoingProvisioning(TEST_IFACE); assertTrue(mNetFactory.acceptRequest(createDefaultRequest())); @@ -299,6 +307,7 @@ public class EthernetNetworkFactoryTest { @Test public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception { + initEthernetNetworkFactory(); createInterfaceUndergoingProvisioning(TEST_IFACE); // verify that the IpClient gets shut down when interface state changes to down. assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); @@ -307,6 +316,7 @@ public class EthernetNetworkFactoryTest { @Test public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); verifyStop(); @@ -314,6 +324,7 @@ public class EthernetNetworkFactoryTest { @Test public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception { + initEthernetNetworkFactory(); createUnprovisionedInterface(TEST_IFACE); assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); // There should not be an active IPClient or NetworkAgent. @@ -324,6 +335,7 @@ public class EthernetNetworkFactoryTest { @Test public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception { + initEthernetNetworkFactory(); // if interface was never added, link state cannot be updated. assertFalse(mNetFactory.updateInterfaceLinkState("eth1", true)); verify(mDeps, never()).makeIpClient(any(), any(), any()); @@ -331,6 +343,7 @@ public class EthernetNetworkFactoryTest { @Test public void testNeedNetworkForOnProvisionedInterface() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); mNetFactory.needNetworkFor(createDefaultRequest()); verify(mIpClient, never()).startProvisioning(any()); @@ -338,6 +351,7 @@ public class EthernetNetworkFactoryTest { @Test public void testNeedNetworkForOnUnprovisionedInterface() throws Exception { + initEthernetNetworkFactory(); createUnprovisionedInterface(TEST_IFACE); mNetFactory.needNetworkFor(createDefaultRequest()); verify(mIpClient).startProvisioning(any()); @@ -348,6 +362,7 @@ public class EthernetNetworkFactoryTest { @Test public void testNeedNetworkForOnInterfaceUndergoingProvisioning() throws Exception { + initEthernetNetworkFactory(); createInterfaceUndergoingProvisioning(TEST_IFACE); mNetFactory.needNetworkFor(createDefaultRequest()); verify(mIpClient, never()).startProvisioning(any()); @@ -358,6 +373,7 @@ public class EthernetNetworkFactoryTest { @Test public void testProvisioningLoss() throws Exception { + initEthernetNetworkFactory(); when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); createAndVerifyProvisionedInterface(TEST_IFACE); @@ -369,18 +385,24 @@ public class EthernetNetworkFactoryTest { @Test public void testProvisioningLossForDisappearedInterface() throws Exception { + initEthernetNetworkFactory(); // mocked method returns null by default, but just to be explicit in the test: when(mDeps.getNetworkInterfaceByName(eq(TEST_IFACE))).thenReturn(null); createAndVerifyProvisionedInterface(TEST_IFACE); triggerOnProvisioningFailure(); - verifyStop(); + // the interface disappeared and getNetworkInterfaceByName returns null, we should not retry verify(mIpClient, never()).startProvisioning(any()); + verify(mNetworkAgent, never()).register(); + verify(mIpClient, never()).shutdown(); + verify(mNetworkAgent, never()).unregister(); + verify(mIpClient, never()).startProvisioning(any()); } @Test public void testIpClientIsNotStartedWhenLinkIsDown() throws Exception { + initEthernetNetworkFactory(); createUnprovisionedInterface(TEST_IFACE); mNetFactory.updateInterfaceLinkState(TEST_IFACE, false); @@ -399,6 +421,7 @@ public class EthernetNetworkFactoryTest { @Test public void testLinkPropertiesChanged() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); LinkProperties lp = new LinkProperties(); @@ -409,6 +432,7 @@ public class EthernetNetworkFactoryTest { @Test public void testNetworkUnwanted() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); mNetworkAgent.getCallbacks().onNetworkUnwanted(); @@ -418,6 +442,7 @@ public class EthernetNetworkFactoryTest { @Test public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception { + initEthernetNetworkFactory(); // ensures provisioning is restarted after provisioning loss when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); createAndVerifyProvisionedInterface(TEST_IFACE); @@ -441,6 +466,7 @@ public class EthernetNetworkFactoryTest { @Test public void testTransportOverrideIsCorrectlySet() throws Exception { + initEthernetNetworkFactory(); // createProvisionedInterface() has verifications in place for transport override // functionality which for EthernetNetworkFactory is network score and legacy type mappings. createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_ETHERNET, @@ -461,6 +487,7 @@ public class EthernetNetworkFactoryTest { @Test public void testReachabilityLoss() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); triggerOnReachabilityLost(); @@ -471,6 +498,7 @@ public class EthernetNetworkFactoryTest { @Test public void testIgnoreOnIpLayerStartedCallbackAfterIpClientHasStopped() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); @@ -484,6 +512,7 @@ public class EthernetNetworkFactoryTest { @Test public void testIgnoreOnIpLayerStoppedCallbackAfterIpClientHasStopped() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); @@ -497,26 +526,37 @@ public class EthernetNetworkFactoryTest { @Test public void testIgnoreLinkPropertiesCallbackAfterIpClientHasStopped() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); LinkProperties lp = new LinkProperties(); - mIpClientCallbacks.onProvisioningFailure(lp); + // The test requires the two proceeding methods to happen one after the other in ENF and + // verifies onLinkPropertiesChange doesn't complete execution for a downed interface. + // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks + // to null which will throw an NPE in the test if executed synchronously. + mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); mIpClientCallbacks.onLinkPropertiesChange(lp); mLooper.dispatchAll(); - verifyStop(); + verifyStop(); // ipClient has been shut down first, we should not update verify(mNetworkAgent, never()).sendLinkPropertiesImpl(same(lp)); } @Test public void testIgnoreNeighborLossCallbackAfterIpClientHasStopped() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); - mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + + // The test requires the two proceeding methods to happen one after the other in ENF and + // verifies onReachabilityLost doesn't complete execution for a downed interface. + // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks + // to null which will throw an NPE in the test if executed synchronously. + mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); mIpClientCallbacks.onReachabilityLost("Neighbor Lost"); mLooper.dispatchAll(); - verifyStop(); + verifyStop(); // ipClient has been shut down first, we should not update verify(mIpClient, never()).startProvisioning(any()); verify(mNetworkAgent, never()).register(); @@ -567,6 +607,7 @@ public class EthernetNetworkFactoryTest { @Test public void testUpdateInterfaceCallsListenerCorrectlyOnSuccess() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); final NetworkCapabilities capabilities = createDefaultFilterCaps(); final IpConfiguration ipConfiguration = createStaticIpConfig(); @@ -580,8 +621,71 @@ public class EthernetNetworkFactoryTest { assertNull(ret.second); } + @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available + @Test + public void testUpdateInterfaceAbortsOnConcurrentRemoveInterface() throws Exception { + initEthernetNetworkFactory(); + verifyNetworkManagementCallIsAbortedWhenInterrupted( + TEST_IFACE, + () -> mNetFactory.removeInterface(TEST_IFACE)); + } + + @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available + @Test + public void testUpdateInterfaceAbortsOnConcurrentUpdateInterfaceLinkState() throws Exception { + initEthernetNetworkFactory(); + verifyNetworkManagementCallIsAbortedWhenInterrupted( + TEST_IFACE, + () -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + } + + @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available + @Test + public void testUpdateInterfaceCallsListenerCorrectlyOnConcurrentRequests() throws Exception { + initEthernetNetworkFactory(); + final NetworkCapabilities capabilities = createDefaultFilterCaps(); + final IpConfiguration ipConfiguration = createStaticIpConfig(); + final TestNetworkManagementListener successfulListener = + new TestNetworkManagementListener(); + + // If two calls come in before the first one completes, the first listener will be aborted + // and the second one will be successful. + verifyNetworkManagementCallIsAbortedWhenInterrupted( + TEST_IFACE, + () -> { + mNetFactory.updateInterface( + TEST_IFACE, ipConfiguration, capabilities, successfulListener); + triggerOnProvisioningSuccess(); + }); + + final Pair successfulResult = + successfulListener.expectOnComplete(); + assertEquals(mMockNetwork, successfulResult.first); + assertNull(successfulResult.second); + } + + private void verifyNetworkManagementCallIsAbortedWhenInterrupted( + @NonNull final String iface, + @NonNull final Runnable interruptingRunnable) throws Exception { + createAndVerifyProvisionedInterface(iface); + final NetworkCapabilities capabilities = createDefaultFilterCaps(); + final IpConfiguration ipConfiguration = createStaticIpConfig(); + final TestNetworkManagementListener failedListener = new TestNetworkManagementListener(); + + // An active update request will be aborted on interrupt prior to provisioning completion. + mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener); + interruptingRunnable.run(); + + final Pair failedResult = + failedListener.expectOnComplete(); + assertNull(failedResult.first); + assertNotNull(failedResult.second); + assertTrue(failedResult.second.getMessage().contains("aborted")); + } + @Test public void testUpdateInterfaceRestartsAgentCorrectly() throws Exception { + initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); final NetworkCapabilities capabilities = createDefaultFilterCaps(); final IpConfiguration ipConfiguration = createStaticIpConfig(); From bf254864a4269d8ab86a12830ea0871555f1fc08 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 27 Jan 2022 15:37:43 +0900 Subject: [PATCH 805/881] Clear counters and delete tag data from NetworkStatsService. Currently, NetworkStatsService deletes tag data by calling NetworkManagementSocketTagger, which then calls into libcutils "qtaguid" code. Instead, make NetworkStatsService call into libcutils directly and delete the NetworkManagementSocketTagger code. In the future, this will make it easier for NetworkStatsService to perform this operation by calling directly into BpfNetMaps. Because the unit test does not yet have working JNI code, provide an internal TagStatsDeleter interface that can be mocked out via the Dependencies class. This is a bit ugly but it will be deleted as soon as the code uses BpfNetMaps directly. Delete NetworkManagementSocketTagger#setKernelCounterSet since it was replaced in aosp/1958917. Also remove unused includes and make formatting changes suggested by clang-format. Test: m Test: atest NetworkStatsServiceTest Test: atest NetworkUsageStatsTest Test: atest TrafficStatsTest Test: stats deleted when CtsUsageStatsTestCases completes and test APK is uninstalled Change-Id: I62987000afc185199821580232bfb7668c8e301e --- .../server/net/NetworkStatsService.java | 19 +++++++++++++++++-- ...android_server_net_NetworkStatsService.cpp | 15 +++++++++------ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 8e584d084f..748b0ae020 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -59,7 +59,6 @@ import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport; import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; -import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; import android.annotation.NonNull; import android.annotation.Nullable; @@ -121,6 +120,7 @@ import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.system.ErrnoException; +import android.system.Os; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionPlan; import android.text.TextUtils; @@ -546,6 +546,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return null; } } + + public TagStatsDeleter getTagStatsDeleter() { + return NetworkStatsService::nativeDeleteTagData; + } } /** @@ -1801,7 +1805,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Clear kernel stats associated with UID for (int uid : uids) { - resetKernelUidStats(uid); + final int ret = mDeps.getTagStatsDeleter().deleteTagData(uid); + if (ret < 0) { + Log.w(TAG, "problem clearing counters for uid " + uid + ": " + Os.strerror(-ret)); + } } } @@ -2380,4 +2387,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static native long nativeGetTotalStat(int type); private static native long nativeGetIfaceStat(String iface, int type); private static native long nativeGetUidStat(int uid, int type); + + // TODO: use BpfNetMaps to delete tag data and remove this. + @VisibleForTesting + interface TagStatsDeleter { + int deleteTagData(int uid); + } + + private static native int nativeDeleteTagData(int uid); } diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index 5178132e4a..f8a81682bd 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -16,20 +16,18 @@ #define LOG_TAG "NetworkStatsNative" +#include #include #include #include #include -#include -#include - -#include "core_jni_helpers.h" #include #include -#include +#include +#include #include +#include -#include "android-base/unique_fd.h" #include "bpf/BpfUtils.h" #include "netdbpf/BpfNetworkStats.h" @@ -104,10 +102,15 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) { } } +static int deleteTagData(JNIEnv* /* env */, jclass /* clazz */, jint uid) { + return qtaguid_deleteTagData(0, uid); +} + static const JNINativeMethod gMethods[] = { {"nativeGetTotalStat", "(I)J", (void*)getTotalStat}, {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat}, {"nativeGetUidStat", "(II)J", (void*)getUidStat}, + {"nativeDeleteTagData", "(I)I", (void*)deleteTagData}, }; int register_android_server_net_NetworkStatsService(JNIEnv* env) { From aa6eed54a74396e0d53c4168aff67e02020c02db Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 28 Jan 2022 09:53:45 +0800 Subject: [PATCH 806/881] [MS59.3] Expose NetworkStatsDataMigrationUtils Test: TH Bug: 204830222 Change-Id: I15a45fbadeb69b70a0e983b00de9e934d29749d6 --- .../src/android/app/usage/NetworkStatsManager.java | 12 ++++-------- .../com/android/server/net/NetworkStatsService.java | 6 +++--- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 84adef53e4..5ce7e59b38 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -41,6 +41,7 @@ import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; import android.net.netstats.IUsageCallback; +import android.net.netstats.NetworkStatsDataMigrationUtils; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Build; @@ -126,17 +127,12 @@ public class NetworkStatsManager { private final INetworkStatsService mService; /** - * Type constants for reading different types of Data Usage. + * @deprecated Use {@link NetworkStatsDataMigrationUtils#PREFIX_XT} + * instead. * @hide */ - // @SystemApi(client = MODULE_LIBRARIES) + @Deprecated public static final String PREFIX_DEV = "dev"; - /** @hide */ - public static final String PREFIX_XT = "xt"; - /** @hide */ - public static final String PREFIX_UID = "uid"; - /** @hide */ - public static final String PREFIX_UID_TAG = "uid_tag"; /** @hide */ public static final int FLAG_POLL_ON_OPEN = 1 << 0; diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 8e584d084f..3abb64fce1 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -20,9 +20,6 @@ import static android.Manifest.permission.NETWORK_STATS_PROVIDER; import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.app.usage.NetworkStatsManager.PREFIX_DEV; -import static android.app.usage.NetworkStatsManager.PREFIX_UID; -import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG; -import static android.app.usage.NetworkStatsManager.PREFIX_XT; import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.ACTION_USER_REMOVED; @@ -50,6 +47,9 @@ import static android.net.TrafficStats.KB_IN_BYTES; import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.TrafficStats.UID_TETHERING; import static android.net.TrafficStats.UNSUPPORTED; +import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID; +import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG; +import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT; import static android.os.Trace.TRACE_TAG_NETWORK; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.text.format.DateUtils.DAY_IN_MILLIS; From adab7b1cc3ba4da747e37388f094a77214c31772 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sat, 29 Jan 2022 21:37:59 +0900 Subject: [PATCH 807/881] Move kernelToTag to NetworkStatsFactory. ... to prepare for the deletion of NetworkManagementSocketTagger. Test: atest FrameworksNetTests Change-Id: Id3ad67fa640ddb9ab446e10dcf8e6a588d661dd9 --- .../android/server/net/NetworkStatsFactory.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java index 17f3455d20..668d1cba92 100644 --- a/service-t/src/com/android/server/net/NetworkStatsFactory.java +++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java @@ -22,8 +22,6 @@ import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; -import static com.android.server.NetworkManagementSocketTagger.kernelToTag; - import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -469,6 +467,19 @@ public class NetworkStatsFactory { } } + /** + * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming + * format like {@code 0x7fffffff00000000}. + */ + public static int kernelToTag(String string) { + int length = string.length(); + if (length > 10) { + return Long.decode(string.substring(0, length - 8)).intValue(); + } else { + return 0; + } + } + /** * Parse statistics from file into given {@link NetworkStats} object. Values * are expected to monotonically increase since device boot. From 81b707f491e12a89df456bf232ac3b3d6e35f83b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sat, 29 Jan 2022 21:07:33 +0900 Subject: [PATCH 808/881] Move socket tagging implementation to mainline. Currently, socket tagging is implemented in the framework. The Java code is in NetworkManagmentSocketTagger.java and the JNI is in libandroid and loaded by the general framework JNI loader. - Move the Java implementation to TrafficStats, which is the only caller of NetworkManagmentSocketTagger. This simplifies the code a bit because a number of methods can be deleted. - Move the JNI code to a new JNI library in the APEX. The library depends only on the NDK and statically links the NDK-only version of libnativehelper. Its size is only 5k on ARM and 10k on ARM64. - Temporarily make the framework depend on this library until the rest of the T connectivity code moves to the APEX. Test: atest NetworkUsageStatsTest CtsNetTestCases:TrafficStatsTest Change-Id: I050c7c515237f68b78d08987bc443f50a7949c06 --- framework-t/Sources.bp | 32 ++++++- framework-t/jni/android_net_TrafficStats.cpp | 46 ++++++++++ framework-t/jni/onload.cpp | 39 +++++++++ framework-t/src/android/net/TrafficStats.java | 86 ++++++++++++++++--- 4 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 framework-t/jni/android_net_TrafficStats.cpp create mode 100644 framework-t/jni/onload.cpp diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 223bdcdd9c..327b1fb2f5 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -39,7 +39,6 @@ filegroup { "src/android/net/TrafficStats.java", "src/android/net/UnderlyingNetworkInfo.*", "src/android/net/netstats/**/*.*", - "src/com/android/server/NetworkManagementSocketTagger.java", ], path: "src", visibility: [ @@ -176,3 +175,34 @@ filegroup { "//packages/modules/Connectivity:__subpackages__", ], } + +cc_library_shared { + name: "libframework-connectivity-tiramisu-jni", + min_sdk_version: "30", + cflags: [ + "-Wall", + "-Werror", + "-Wno-unused-parameter", + // Don't warn about S API usage even with + // min_sdk 30: the library is only loaded + // on S+ devices + "-Wno-unguarded-availability", + "-Wthread-safety", + ], + srcs: [ + "jni/android_net_TrafficStats.cpp", + "jni/onload.cpp", + ], + shared_libs: [ + "liblog", + ], + static_libs: [ + "libnativehelper_compat_libc++", + ], + stl: "none", + apex_available: [ + "com.android.tethering", + // TODO: remove when ConnectivityT moves to APEX. + "//apex_available:platform", + ], +} diff --git a/framework-t/jni/android_net_TrafficStats.cpp b/framework-t/jni/android_net_TrafficStats.cpp new file mode 100644 index 0000000000..f3c58b112f --- /dev/null +++ b/framework-t/jni/android_net_TrafficStats.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +namespace android { + +static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, jint tag, jint uid) { + int fd = AFileDescriptor_getFd(env, fileDescriptor); + if (fd == -1) return -EBADF; + return android_tag_socket_with_uid(fd, tag, uid); +} + +static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) { + int fd = AFileDescriptor_getFd(env, fileDescriptor); + if (fd == -1) return -EBADF; + return android_untag_socket(fd); +} + +static const JNINativeMethod gMethods[] = { + /* name, signature, funcPtr */ + { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*) tagSocketFd }, + { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*) untagSocketFd }, +}; + +int register_android_net_TrafficStats(JNIEnv* env) { + return jniRegisterNativeMethods(env, "android/net/TrafficStats", gMethods, NELEM(gMethods)); +} + +}; // namespace android + diff --git a/framework-t/jni/onload.cpp b/framework-t/jni/onload.cpp new file mode 100644 index 0000000000..1fb42c6347 --- /dev/null +++ b/framework-t/jni/onload.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "FrameworkConnectivityJNI" + +#include +#include + +namespace android { + +int register_android_net_TrafficStats(JNIEnv* env); + +extern "C" jint JNI_OnLoad(JavaVM* vm, void*) { + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { + __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed"); + return JNI_ERR; + } + + if (register_android_net_TrafficStats(env) < 0) return JNI_ERR; + + return JNI_VERSION_1_6; +} + +}; // namespace android + diff --git a/framework-t/src/android/net/TrafficStats.java b/framework-t/src/android/net/TrafficStats.java index c2f0cdfb04..bc836d857e 100644 --- a/framework-t/src/android/net/TrafficStats.java +++ b/framework-t/src/android/net/TrafficStats.java @@ -31,12 +31,9 @@ import android.media.MediaPlayer; import android.os.Binder; import android.os.Build; import android.os.RemoteException; +import android.os.StrictMode; import android.util.Log; -import com.android.server.NetworkManagementSocketTagger; - -import dalvik.system.SocketTagger; - import java.io.FileDescriptor; import java.io.IOException; import java.net.DatagramSocket; @@ -56,6 +53,10 @@ import java.net.SocketException; * use {@link NetworkStatsManager} instead. */ public class TrafficStats { + static { + System.loadLibrary("framework-connectivity-tiramisu-jni"); + } + private static final String TAG = TrafficStats.class.getSimpleName(); /** * The return value to indicate that the device does not support the statistic. @@ -232,9 +233,68 @@ public class TrafficStats { */ @SystemApi(client = MODULE_LIBRARIES) public static void attachSocketTagger() { - NetworkManagementSocketTagger.install(); + dalvik.system.SocketTagger.set(new SocketTagger()); } + private static class SocketTagger extends dalvik.system.SocketTagger { + + // TODO: set to false + private static final boolean LOGD = true; + + SocketTagger() { + } + + @Override + public void tag(FileDescriptor fd) throws SocketException { + final UidTag tagInfo = sThreadUidTag.get(); + if (LOGD) { + Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x" + + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid); + } + if (tagInfo.tag == -1) { + StrictMode.noteUntaggedSocket(); + } + + if (tagInfo.tag == -1 && tagInfo.uid == -1) return; + final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid); + if (errno < 0) { + Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", " + + tagInfo.tag + ", " + + tagInfo.uid + ") failed with errno" + errno); + } + } + + @Override + public void untag(FileDescriptor fd) throws SocketException { + if (LOGD) { + Log.i(TAG, "untagSocket(" + fd.getInt$() + ")"); + } + + final UidTag tagInfo = sThreadUidTag.get(); + if (tagInfo.tag == -1 && tagInfo.uid == -1) return; + + final int errno = native_untagSocketFd(fd); + if (errno < 0) { + Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno); + } + } + } + + private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid); + private static native int native_untagSocketFd(FileDescriptor fd); + + private static class UidTag { + public int tag = -1; + public int uid = -1; + } + + private static ThreadLocal sThreadUidTag = new ThreadLocal() { + @Override + protected UidTag initialValue() { + return new UidTag(); + } + }; + /** * Set active tag to use when accounting {@link Socket} traffic originating * from the current thread. Only one active tag per thread is supported. @@ -249,7 +309,7 @@ public class TrafficStats { * @see #clearThreadStatsTag() */ public static void setThreadStatsTag(int tag) { - NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); + getAndSetThreadStatsTag(tag); } /** @@ -267,7 +327,9 @@ public class TrafficStats { * restore any existing values after a nested operation is finished */ public static int getAndSetThreadStatsTag(int tag) { - return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); + final int old = sThreadUidTag.get().tag; + sThreadUidTag.get().tag = tag; + return old; } /** @@ -327,7 +389,7 @@ public class TrafficStats { * @see #setThreadStatsTag(int) */ public static int getThreadStatsTag() { - return NetworkManagementSocketTagger.getThreadSocketStatsTag(); + return sThreadUidTag.get().tag; } /** @@ -337,7 +399,7 @@ public class TrafficStats { * @see #setThreadStatsTag(int) */ public static void clearThreadStatsTag() { - NetworkManagementSocketTagger.setThreadSocketStatsTag(-1); + sThreadUidTag.get().tag = -1; } /** @@ -357,7 +419,7 @@ public class TrafficStats { */ @SuppressLint("RequiresPermission") public static void setThreadStatsUid(int uid) { - NetworkManagementSocketTagger.setThreadSocketStatsUid(uid); + sThreadUidTag.get().uid = uid; } /** @@ -368,7 +430,7 @@ public class TrafficStats { * @see #setThreadStatsUid(int) */ public static int getThreadStatsUid() { - return NetworkManagementSocketTagger.getThreadSocketStatsUid(); + return sThreadUidTag.get().uid; } /** @@ -395,7 +457,7 @@ public class TrafficStats { */ @SuppressLint("RequiresPermission") public static void clearThreadStatsUid() { - NetworkManagementSocketTagger.setThreadSocketStatsUid(-1); + setThreadStatsUid(-1); } /** From aeb8a06c236e799a187d92e6f5270a1adec169f2 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Mon, 17 Jan 2022 15:43:10 -0800 Subject: [PATCH 809/881] InternalNetworkManagementException Changes Update to InternalNetworkManagementException in order to allow all members to be parcelable. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I17f119a66face8a927546657490969aa3073c54b --- .../InternalNetworkManagementException.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/framework-t/src/android/net/InternalNetworkManagementException.java b/framework-t/src/android/net/InternalNetworkManagementException.java index 7f4e403f22..798e9c3b52 100644 --- a/framework-t/src/android/net/InternalNetworkManagementException.java +++ b/framework-t/src/android/net/InternalNetworkManagementException.java @@ -20,22 +20,34 @@ import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** @hide */ public final class InternalNetworkManagementException extends RuntimeException implements Parcelable { /* @hide */ - public InternalNetworkManagementException(@NonNull final Throwable t) { - super(t); + public InternalNetworkManagementException(@NonNull final String errorMessage) { + super(errorMessage); } - private InternalNetworkManagementException(@NonNull final Parcel source) { - super(source.readString()); + @Override + public int hashCode() { + return Objects.hash(getMessage()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + final InternalNetworkManagementException that = (InternalNetworkManagementException) obj; + + return Objects.equals(getMessage(), that.getMessage()); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString(getCause().getMessage()); + dest.writeString(getMessage()); } @Override @@ -53,7 +65,7 @@ public final class InternalNetworkManagementException @Override public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) { - return new InternalNetworkManagementException(source); + return new InternalNetworkManagementException(source.readString()); } }; } From a46242b7ab47621f0d4100e591aab38c179195ed Mon Sep 17 00:00:00 2001 From: James Mattis Date: Fri, 28 Jan 2022 13:42:38 -0800 Subject: [PATCH 810/881] Renaming Ethernet Network Management Classes Renaming InternalNetwork* files and classes related to ethernet network management to EthernetNetwork* as ethernet is the only trasnport these particular files are used with. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: Ieb3915c032ef5fcd6b36eb09878119de7668bb4b --- framework-t/Sources.bp | 10 ++++---- .../src/android/net/EthernetManager.java | 18 ++++++------- ...> EthernetNetworkManagementException.aidl} | 2 +- ...> EthernetNetworkManagementException.java} | 18 ++++++------- ...aidl => EthernetNetworkUpdateRequest.aidl} | 2 +- ...java => EthernetNetworkUpdateRequest.java} | 22 ++++++++-------- .../src/android/net/IEthernetManager.aidl | 12 ++++----- .../IEthernetNetworkManagementListener.aidl | 25 +++++++++++++++++++ 8 files changed, 67 insertions(+), 42 deletions(-) rename framework-t/src/android/net/{InternalNetworkManagementException.aidl => EthernetNetworkManagementException.aidl} (93%) rename framework-t/src/android/net/{InternalNetworkManagementException.java => EthernetNetworkManagementException.java} (73%) rename framework-t/src/android/net/{InternalNetworkUpdateRequest.aidl => EthernetNetworkUpdateRequest.aidl} (94%) rename framework-t/src/android/net/{InternalNetworkUpdateRequest.java => EthernetNetworkUpdateRequest.java} (80%) create mode 100644 framework-t/src/android/net/IEthernetNetworkManagementListener.aidl diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 327b1fb2f5..54538d91a5 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -125,14 +125,14 @@ filegroup { name: "framework-connectivity-ethernet-sources", srcs: [ "src/android/net/EthernetManager.java", + "src/android/net/EthernetNetworkManagementException.java", + "src/android/net/EthernetNetworkManagementException.aidl", "src/android/net/EthernetNetworkSpecifier.java", + "src/android/net/EthernetNetworkUpdateRequest.java", + "src/android/net/EthernetNetworkUpdateRequest.aidl", "src/android/net/IEthernetManager.aidl", + "src/android/net/IEthernetNetworkManagementListener.aidl", "src/android/net/IEthernetServiceListener.aidl", - "src/android/net/IInternalNetworkManagementListener.aidl", - "src/android/net/InternalNetworkUpdateRequest.java", - "src/android/net/InternalNetworkUpdateRequest.aidl", - "src/android/net/InternalNetworkManagementException.java", - "src/android/net/InternalNetworkManagementException.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index ece54df966..f472d563c4 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -320,15 +320,15 @@ public class EthernetManager { } private static final class InternalNetworkManagementListener - extends IInternalNetworkManagementListener.Stub { + extends IEthernetNetworkManagementListener.Stub { @NonNull private final Executor mExecutor; @NonNull - private final BiConsumer mListener; + private final BiConsumer mListener; InternalNetworkManagementListener( @NonNull final Executor executor, - @NonNull final BiConsumer listener) { + @NonNull final BiConsumer listener) { Objects.requireNonNull(executor, "Pass a non-null executor"); Objects.requireNonNull(listener, "Pass a non-null listener"); mExecutor = executor; @@ -338,14 +338,14 @@ public class EthernetManager { @Override public void onComplete( @Nullable final Network network, - @Nullable final InternalNetworkManagementException e) { + @Nullable final EthernetNetworkManagementException e) { mExecutor.execute(() -> mListener.accept(network, e)); } } private InternalNetworkManagementListener getInternalNetworkManagementListener( @Nullable final Executor executor, - @Nullable final BiConsumer listener) { + @Nullable final BiConsumer listener) { if (null != listener) { Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); } @@ -360,9 +360,9 @@ public class EthernetManager { private void updateConfiguration( @NonNull String iface, - @NonNull InternalNetworkUpdateRequest request, + @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable BiConsumer listener) { final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { @@ -375,7 +375,7 @@ public class EthernetManager { private void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable BiConsumer listener) { final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { @@ -388,7 +388,7 @@ public class EthernetManager { private void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable BiConsumer listener) { final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { diff --git a/framework-t/src/android/net/InternalNetworkManagementException.aidl b/framework-t/src/android/net/EthernetNetworkManagementException.aidl similarity index 93% rename from framework-t/src/android/net/InternalNetworkManagementException.aidl rename to framework-t/src/android/net/EthernetNetworkManagementException.aidl index dcce706989..adf9e5a4db 100644 --- a/framework-t/src/android/net/InternalNetworkManagementException.aidl +++ b/framework-t/src/android/net/EthernetNetworkManagementException.aidl @@ -16,4 +16,4 @@ package android.net; - parcelable InternalNetworkManagementException; \ No newline at end of file + parcelable EthernetNetworkManagementException; \ No newline at end of file diff --git a/framework-t/src/android/net/InternalNetworkManagementException.java b/framework-t/src/android/net/EthernetNetworkManagementException.java similarity index 73% rename from framework-t/src/android/net/InternalNetworkManagementException.java rename to framework-t/src/android/net/EthernetNetworkManagementException.java index 798e9c3b52..a35f28e172 100644 --- a/framework-t/src/android/net/InternalNetworkManagementException.java +++ b/framework-t/src/android/net/EthernetNetworkManagementException.java @@ -23,11 +23,11 @@ import android.os.Parcelable; import java.util.Objects; /** @hide */ -public final class InternalNetworkManagementException +public final class EthernetNetworkManagementException extends RuntimeException implements Parcelable { /* @hide */ - public InternalNetworkManagementException(@NonNull final String errorMessage) { + public EthernetNetworkManagementException(@NonNull final String errorMessage) { super(errorMessage); } @@ -40,7 +40,7 @@ public final class InternalNetworkManagementException public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; - final InternalNetworkManagementException that = (InternalNetworkManagementException) obj; + final EthernetNetworkManagementException that = (EthernetNetworkManagementException) obj; return Objects.equals(getMessage(), that.getMessage()); } @@ -56,16 +56,16 @@ public final class InternalNetworkManagementException } @NonNull - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { @Override - public InternalNetworkManagementException[] newArray(int size) { - return new InternalNetworkManagementException[size]; + public EthernetNetworkManagementException[] newArray(int size) { + return new EthernetNetworkManagementException[size]; } @Override - public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) { - return new InternalNetworkManagementException(source.readString()); + public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) { + return new EthernetNetworkManagementException(source.readString()); } }; } diff --git a/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl b/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl similarity index 94% rename from framework-t/src/android/net/InternalNetworkUpdateRequest.aidl rename to framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl index da00cb97af..debc348ea3 100644 --- a/framework-t/src/android/net/InternalNetworkUpdateRequest.aidl +++ b/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl @@ -16,4 +16,4 @@ package android.net; - parcelable InternalNetworkUpdateRequest; \ No newline at end of file + parcelable EthernetNetworkUpdateRequest; \ No newline at end of file diff --git a/framework-t/src/android/net/InternalNetworkUpdateRequest.java b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java similarity index 80% rename from framework-t/src/android/net/InternalNetworkUpdateRequest.java rename to framework-t/src/android/net/EthernetNetworkUpdateRequest.java index f42c4b7c42..4d229d23b1 100644 --- a/framework-t/src/android/net/InternalNetworkUpdateRequest.java +++ b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java @@ -23,7 +23,7 @@ import android.os.Parcelable; import java.util.Objects; /** @hide */ -public final class InternalNetworkUpdateRequest implements Parcelable { +public final class EthernetNetworkUpdateRequest implements Parcelable { @NonNull private final StaticIpConfiguration mIpConfig; @NonNull @@ -40,7 +40,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { } /** @hide */ - public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, + public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, @NonNull final NetworkCapabilities networkCapabilities) { Objects.requireNonNull(ipConfig); Objects.requireNonNull(networkCapabilities); @@ -48,7 +48,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); } - private InternalNetworkUpdateRequest(@NonNull final Parcel source) { + private EthernetNetworkUpdateRequest(@NonNull final Parcel source) { Objects.requireNonNull(source); mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source); mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source); @@ -56,7 +56,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { @Override public String toString() { - return "InternalNetworkUpdateRequest{" + return "EthernetNetworkUpdateRequest{" + "mIpConfig=" + mIpConfig + ", mNetworkCapabilities=" + mNetworkCapabilities + '}'; } @@ -65,7 +65,7 @@ public final class InternalNetworkUpdateRequest implements Parcelable { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o; + EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o; return Objects.equals(that.getIpConfig(), mIpConfig) && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities); @@ -88,16 +88,16 @@ public final class InternalNetworkUpdateRequest implements Parcelable { } @NonNull - public static final Parcelable.Creator CREATOR = - new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { @Override - public InternalNetworkUpdateRequest[] newArray(int size) { - return new InternalNetworkUpdateRequest[size]; + public EthernetNetworkUpdateRequest[] newArray(int size) { + return new EthernetNetworkUpdateRequest[size]; } @Override - public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) { - return new InternalNetworkUpdateRequest(source); + public EthernetNetworkUpdateRequest createFromParcel(@NonNull Parcel source) { + return new EthernetNetworkUpdateRequest(source); } }; } diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index e688bea1cf..544d02ba76 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -18,8 +18,8 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; -import android.net.IInternalNetworkManagementListener; -import android.net.InternalNetworkUpdateRequest; +import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkUpdateRequest; import android.net.ITetheredInterfaceCallback; /** @@ -38,8 +38,8 @@ interface IEthernetManager void setIncludeTestInterfaces(boolean include); void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); - void updateConfiguration(String iface, in InternalNetworkUpdateRequest request, - in IInternalNetworkManagementListener listener); - void connectNetwork(String iface, in IInternalNetworkManagementListener listener); - void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener); + void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request, + in IEthernetNetworkManagementListener listener); + void connectNetwork(String iface, in IEthernetNetworkManagementListener listener); + void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener); } diff --git a/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl b/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl new file mode 100644 index 0000000000..93edccfdaf --- /dev/null +++ b/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2021, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.EthernetNetworkManagementException; +import android.net.Network; + +/** @hide */ +oneway interface IEthernetNetworkManagementListener { + void onComplete(in Network network, in EthernetNetworkManagementException exception); +} \ No newline at end of file From c3bfad406f48beea682ca7cdd2c135d9e0fd0af5 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Thu, 20 Jan 2022 16:25:05 -0800 Subject: [PATCH 811/881] Implementation of Eth Connect & Disconnect Network Implementation of EthernetService APIs for ConnectNetwork() and DisconnectNetwork(). Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I4c3e361d052206cb28b97fc439bfeac8e7e0fec0 --- .../ethernet/EthernetNetworkFactory.java | 26 +++++- .../server/ethernet/EthernetServiceImpl.java | 2 + .../server/ethernet/EthernetTracker.java | 19 +++- .../ethernet/EthernetNetworkFactoryTest.java | 92 +++++++++++++++---- .../ethernet/EthernetServiceImplTest.java | 30 ++++-- .../server/ethernet/EthernetTrackerTest.java | 35 +++++-- 6 files changed, 163 insertions(+), 41 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index c610f00ab1..0832b50738 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -252,8 +252,13 @@ public class EthernetNetworkFactory extends NetworkFactory { } /** Returns true if state has been modified */ - boolean updateInterfaceLinkState(String ifaceName, boolean up) { + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up, + @Nullable final IInternalNetworkManagementListener listener) { if (!mTrackingInterfaces.containsKey(ifaceName)) { + maybeSendNetworkManagementCallback(listener, null, + new InternalNetworkManagementException( + ifaceName + " can't be updated as it is not available.")); return false; } @@ -262,7 +267,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName); - return iface.updateLinkState(up); + return iface.updateLinkState(up, listener); } boolean hasInterface(String ifaceName) { @@ -615,16 +620,27 @@ public class EthernetNetworkFactory extends NetworkFactory { } /** Returns true if state has been modified */ - boolean updateLinkState(boolean up) { - if (mLinkUp == up) return false; + boolean updateLinkState(final boolean up, + @Nullable final IInternalNetworkManagementListener listener) { + if (mLinkUp == up) { + EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null, + new InternalNetworkManagementException( + "No changes with requested link state " + up + " for " + name)); + return false; + } mLinkUp = up; if (!up) { // was up, goes down + // Save an instance of the current network to use with the callback before stop(). + final Network network = mNetworkAgent != null ? mNetworkAgent.getNetwork() : null; + // Send an abort on a provisioning request callback if necessary before stopping. maybeSendNetworkManagementCallbackForAbort(); stop(); + // If only setting the interface down, send a callback to signal completion. + EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, network, null); } else { // was down, goes up stop(); - start(); + start(listener); } return true; diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index b2844779c8..6f6a04a273 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -243,6 +243,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Nullable final IInternalNetworkManagementListener listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); validateNetworkManagementState(iface, "connectNetwork()"); + mTracker.connectNetwork(iface, listener); } @Override @@ -250,5 +251,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Nullable final IInternalNetworkManagementListener listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); validateNetworkManagementState(iface, "disconnectNetwork()"); + mTracker.disconnectNetwork(iface, listener); } } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 53af955d69..97845120db 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -190,6 +190,18 @@ public class EthernetTracker { mFactory.updateInterface(iface, ipConfig, capabilities, listener)); } + @VisibleForTesting(visibility = PACKAGE) + protected void connectNetwork(@NonNull final String iface, + @Nullable final IInternalNetworkManagementListener listener) { + mHandler.post(() -> updateInterfaceState(iface, true, listener)); + } + + @VisibleForTesting(visibility = PACKAGE) + protected void disconnectNetwork(@NonNull final String iface, + @Nullable final IInternalNetworkManagementListener listener) { + mHandler.post(() -> updateInterfaceState(iface, false, listener)); + } + IpConfiguration getIpConfiguration(String iface) { return mIpConfigurations.get(iface); } @@ -354,9 +366,14 @@ public class EthernetTracker { } private void updateInterfaceState(String iface, boolean up) { + updateInterfaceState(iface, up, null /* listener */); + } + + private void updateInterfaceState(@NonNull final String iface, final boolean up, + @Nullable final IInternalNetworkManagementListener listener) { final int mode = getInterfaceMode(iface); final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) - && mFactory.updateInterfaceLinkState(iface, up); + && mFactory.updateInterfaceLinkState(iface, up, listener); if (factoryLinkStateUpdated) { boolean restricted = isRestrictedInterface(iface); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index d569990a18..b8f0ada5a4 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -23,7 +23,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; @@ -84,6 +83,7 @@ import java.util.concurrent.TimeUnit; public class EthernetNetworkFactoryTest { private static final int TIMEOUT_MS = 2_000; private static final String TEST_IFACE = "test123"; + private static final IInternalNetworkManagementListener NULL_LISTENER = null; private static final String IP_ADDR = "192.0.2.2/25"; private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); private static final String HW_ADDR = "01:02:03:04:05:06"; @@ -238,7 +238,7 @@ public class EthernetNetworkFactoryTest { final IpConfiguration ipConfig = createDefaultIpConfig(); mNetFactory.addInterface(iface, HW_ADDR, ipConfig, createInterfaceCapsBuilder(transportType).build()); - assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); + assertTrue(mNetFactory.updateInterfaceLinkState(iface, true, NULL_LISTENER)); verifyStart(ipConfig); clearInvocations(mDeps); clearInvocations(mIpClient); @@ -309,36 +309,74 @@ public class EthernetNetworkFactoryTest { public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception { initEthernetNetworkFactory(); createInterfaceUndergoingProvisioning(TEST_IFACE); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + // verify that the IpClient gets shut down when interface state changes to down. - assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + final boolean ret = + mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener); + + assertTrue(ret); verify(mIpClient).shutdown(); + assertSuccessfulListener(listener, null); } @Test public void testUpdateInterfaceLinkStateForProvisionedInterface() throws Exception { initEthernetNetworkFactory(); createAndVerifyProvisionedInterface(TEST_IFACE); - assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + + final boolean ret = + mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener); + + assertTrue(ret); verifyStop(); + assertSuccessfulListener(listener, mMockNetwork); } @Test public void testUpdateInterfaceLinkStateForUnprovisionedInterface() throws Exception { initEthernetNetworkFactory(); createUnprovisionedInterface(TEST_IFACE); - assertTrue(mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + + final boolean ret = + mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */, listener); + + assertTrue(ret); // There should not be an active IPClient or NetworkAgent. verify(mDeps, never()).makeIpClient(any(), any(), any()); verify(mDeps, never()) .makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); + assertSuccessfulListener(listener, null); } @Test public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception { initEthernetNetworkFactory(); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + // if interface was never added, link state cannot be updated. - assertFalse(mNetFactory.updateInterfaceLinkState("eth1", true)); - verify(mDeps, never()).makeIpClient(any(), any(), any()); + final boolean ret = + mNetFactory.updateInterfaceLinkState(TEST_IFACE, true /* up */, listener); + + assertFalse(ret); + verifyNoStopOrStart(); + assertFailedListener(listener, "can't be updated as it is not configured"); + } + + @Test + public void testUpdateInterfaceLinkStateWithNoChanges() throws Exception { + initEthernetNetworkFactory(); + createAndVerifyProvisionedInterface(TEST_IFACE); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + + final boolean ret = + mNetFactory.updateInterfaceLinkState(TEST_IFACE, true /* up */, listener); + + assertFalse(ret); + verifyNoStopOrStart(); + assertFailedListener(listener, "No changes"); } @Test @@ -394,6 +432,10 @@ public class EthernetNetworkFactoryTest { // the interface disappeared and getNetworkInterfaceByName returns null, we should not retry verify(mIpClient, never()).startProvisioning(any()); + verifyNoStopOrStart(); + } + + private void verifyNoStopOrStart() { verify(mNetworkAgent, never()).register(); verify(mIpClient, never()).shutdown(); verify(mNetworkAgent, never()).unregister(); @@ -404,7 +446,7 @@ public class EthernetNetworkFactoryTest { public void testIpClientIsNotStartedWhenLinkIsDown() throws Exception { initEthernetNetworkFactory(); createUnprovisionedInterface(TEST_IFACE); - mNetFactory.updateInterfaceLinkState(TEST_IFACE, false); + mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER); mNetFactory.needNetworkFor(createDefaultRequest()); @@ -534,7 +576,7 @@ public class EthernetNetworkFactoryTest { // verifies onLinkPropertiesChange doesn't complete execution for a downed interface. // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks // to null which will throw an NPE in the test if executed synchronously. - mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER)); mIpClientCallbacks.onLinkPropertiesChange(lp); mLooper.dispatchAll(); @@ -552,7 +594,7 @@ public class EthernetNetworkFactoryTest { // verifies onReachabilityLost doesn't complete execution for a downed interface. // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks // to null which will throw an NPE in the test if executed synchronously. - mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER)); mIpClientCallbacks.onReachabilityLost("Neighbor Lost"); mLooper.dispatchAll(); @@ -616,9 +658,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - final Pair ret = listener.expectOnComplete(); - assertEquals(mMockNetwork, ret.first); - assertNull(ret.second); + assertSuccessfulListener(listener, mMockNetwork); } @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available @@ -636,7 +676,7 @@ public class EthernetNetworkFactoryTest { initEthernetNetworkFactory(); verifyNetworkManagementCallIsAbortedWhenInterrupted( TEST_IFACE, - () -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false)); + () -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER)); } @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available @@ -658,12 +698,28 @@ public class EthernetNetworkFactoryTest { triggerOnProvisioningSuccess(); }); + assertSuccessfulListener(successfulListener, mMockNetwork); + } + + private void assertSuccessfulListener( + @NonNull final TestNetworkManagementListener successfulListener, + @NonNull final Network expectedNetwork) throws Exception { final Pair successfulResult = successfulListener.expectOnComplete(); - assertEquals(mMockNetwork, successfulResult.first); + assertEquals(expectedNetwork, successfulResult.first); assertNull(successfulResult.second); } + private void assertFailedListener(@NonNull final TestNetworkManagementListener failedListener, + @NonNull final String errMsg) + throws Exception { + final Pair failedResult = + failedListener.expectOnComplete(); + assertNull(failedResult.first); + assertNotNull(failedResult.second); + assertTrue(failedResult.second.getMessage().contains(errMsg)); + } + private void verifyNetworkManagementCallIsAbortedWhenInterrupted( @NonNull final String iface, @NonNull final Runnable interruptingRunnable) throws Exception { @@ -676,11 +732,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener); interruptingRunnable.run(); - final Pair failedResult = - failedListener.expectOnComplete(); - assertNull(failedResult.first); - assertNotNull(failedResult.second); - assertTrue(failedResult.second.getMessage().contains("aborted")); + assertFailedListener(failedListener, "aborted"); } @Test diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 1c0888398a..6593aa5898 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -65,6 +65,15 @@ public class EthernetServiceImplTest { shouldTrackIface(TEST_IFACE, true); } + private void toggleAutomotiveFeature(final boolean isEnabled) { + doReturn(isEnabled) + .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); + } + + private void shouldTrackIface(@NonNull final String iface, final boolean shouldTrack) { + doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface); + } + @Test public void testSetConfigurationRejectsWhenEthNotStarted() { mEthernetServiceImpl.mStarted.set(false); @@ -143,11 +152,6 @@ public class EthernetServiceImplTest { }); } - private void toggleAutomotiveFeature(final boolean isEnabled) { - doReturn(isEnabled) - .when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); - } - @Test public void testUpdateConfigurationRejectsWithUntrackedIface() { shouldTrackIface(TEST_IFACE, false); @@ -172,10 +176,6 @@ public class EthernetServiceImplTest { }); } - private void shouldTrackIface(@NonNull final String iface, final boolean shouldTrack) { - doReturn(shouldTrack).when(mEthernetTracker).isTrackingInterface(iface); - } - @Test public void testUpdateConfiguration() { mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); @@ -184,4 +184,16 @@ public class EthernetServiceImplTest { eq(UPDATE_REQUEST.getIpConfig()), eq(UPDATE_REQUEST.getNetworkCapabilities()), eq(NULL_LISTENER)); } + + @Test + public void testConnectNetwork() { + mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER); + verify(mEthernetTracker).connectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER)); + } + + @Test + public void testDisconnectNetwork() { + mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); + verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER)); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 5aca2e40a0..5087a9bcf4 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -19,9 +19,13 @@ package com.android.server.ethernet; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; @@ -55,8 +59,10 @@ import java.util.ArrayList; @SmallTest @RunWith(AndroidJUnit4.class) public class EthernetTrackerTest { + private static final String TEST_IFACE = "test123"; private static final int TIMEOUT_MS = 1_000; private static final String THREAD_NAME = "EthernetServiceThread"; + private static final IInternalNetworkManagementListener NULL_LISTENER = null; private EthernetTracker tracker; private HandlerThread mHandlerThread; @Mock private Context mContext; @@ -68,6 +74,7 @@ public class EthernetTrackerTest { public void setUp() { MockitoAnnotations.initMocks(this); initMockResources(); + when(mFactory.updateInterfaceLinkState(anyString(), anyBoolean(), any())).thenReturn(false); mHandlerThread = new HandlerThread(THREAD_NAME); mHandlerThread.start(); tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd); @@ -294,16 +301,15 @@ public class EthernetTrackerTest { @Test public void testCreateEthernetTrackerConfigReturnsCorrectValue() { - final String iface = "1"; final String capabilities = "2"; final String ipConfig = "3"; final String transport = "4"; - final String configString = String.join(";", iface, capabilities, ipConfig, transport); + final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport); final EthernetTracker.EthernetTrackerConfig config = EthernetTracker.createEthernetTrackerConfig(configString); - assertEquals(iface, config.mIface); + assertEquals(TEST_IFACE, config.mIface); assertEquals(capabilities, config.mCapabilities); assertEquals(ipConfig, config.mIpConfig); assertEquals(transport, config.mTransport); @@ -317,16 +323,33 @@ public class EthernetTrackerTest { @Test public void testUpdateConfiguration() { - final String iface = "testiface"; final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build(); final StaticIpConfiguration staticIpConfig = new StaticIpConfiguration(); final IInternalNetworkManagementListener listener = null; - tracker.updateConfiguration(iface, staticIpConfig, capabilities, listener); + tracker.updateConfiguration(TEST_IFACE, staticIpConfig, capabilities, listener); waitForIdle(); verify(mFactory).updateInterface( - eq(iface), eq(EthernetTracker.createIpConfiguration(staticIpConfig)), + eq(TEST_IFACE), eq(EthernetTracker.createIpConfiguration(staticIpConfig)), eq(capabilities), eq(listener)); } + + @Test + public void testConnectNetworkCorrectlyCallsFactory() { + tracker.connectNetwork(TEST_IFACE, NULL_LISTENER); + waitForIdle(); + + verify(mFactory).updateInterfaceLinkState(eq(TEST_IFACE), eq(true /* up */), + eq(NULL_LISTENER)); + } + + @Test + public void testDisconnectNetworkCorrectlyCallsFactory() { + tracker.disconnectNetwork(TEST_IFACE, NULL_LISTENER); + waitForIdle(); + + verify(mFactory).updateInterfaceLinkState(eq(TEST_IFACE), eq(false /* up */), + eq(NULL_LISTENER)); + } } From 3ccf899bdaf89ee00bc0b511022520edde40c6f8 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Fri, 28 Jan 2022 13:39:04 -0800 Subject: [PATCH 812/881] Renaming Ethernet Network Management Classes Renaming InternalNetwork* files and classes related to ethernet network management to EthernetNetwork* as ethernet is the only trasnport these particular files are used with. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I5be8543afd70f2edca76a9366cee4ccf61f0d0e7 --- .../ethernet/EthernetNetworkFactory.java | 38 +++++++++---------- .../server/ethernet/EthernetServiceImpl.java | 12 +++--- .../server/ethernet/EthernetTracker.java | 10 ++--- .../ethernet/EthernetNetworkFactoryTest.java | 18 ++++----- .../ethernet/EthernetServiceImplTest.java | 10 ++--- .../server/ethernet/EthernetTrackerTest.java | 6 +-- 6 files changed, 47 insertions(+), 47 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 0832b50738..a15fec4aba 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -21,8 +21,8 @@ import android.annotation.Nullable; import android.content.Context; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; -import android.net.IInternalNetworkManagementListener; -import android.net.InternalNetworkManagementException; +import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkManagementException; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -195,14 +195,14 @@ public class EthernetNetworkFactory extends NetworkFactory { * {@code null} is passed, then the network's current * {@link NetworkCapabilities} will be used in support of existing APIs as * the public API does not allow this. - * @param listener an optional {@link IInternalNetworkManagementListener} to notify callers of + * @param listener an optional {@link IEthernetNetworkManagementListener} to notify callers of * completion. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected void updateInterface(@NonNull final String ifaceName, @NonNull final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { enforceInterfaceIsTracked(ifaceName); final NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName); iface.updateInterface(ipConfig, capabilities, listener); @@ -254,10 +254,10 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (!mTrackingInterfaces.containsKey(ifaceName)) { maybeSendNetworkManagementCallback(listener, null, - new InternalNetworkManagementException( + new EthernetNetworkManagementException( ifaceName + " can't be updated as it is not available.")); return false; } @@ -306,9 +306,9 @@ public class EthernetNetworkFactory extends NetworkFactory { } private static void maybeSendNetworkManagementCallback( - @Nullable final IInternalNetworkManagementListener listener, + @Nullable final IEthernetNetworkManagementListener listener, @Nullable final Network network, - @Nullable final InternalNetworkManagementException e) { + @Nullable final EthernetNetworkManagementException e) { if (null == listener) { return; } @@ -368,9 +368,9 @@ public class EthernetNetworkFactory extends NetworkFactory { private class EthernetIpClientCallback extends IpClientCallbacks { private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); - @Nullable IInternalNetworkManagementListener mNetworkManagementListener; + @Nullable IEthernetNetworkManagementListener mNetworkManagementListener; - EthernetIpClientCallback(@Nullable final IInternalNetworkManagementListener listener) { + EthernetIpClientCallback(@Nullable final IEthernetNetworkManagementListener listener) { mNetworkManagementListener = listener; } @@ -455,7 +455,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void updateInterface(@NonNull final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { Log.d(TAG, "updateInterface, iface: " + name + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig @@ -482,7 +482,7 @@ public class EthernetNetworkFactory extends NetworkFactory { start(null); } - private void start(@Nullable final IInternalNetworkManagementListener listener) { + private void start(@Nullable final IEthernetNetworkManagementListener listener) { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); return; @@ -503,7 +503,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStarted(@NonNull final LinkProperties linkProperties, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if(mIpClient == null) { // This call comes from a message posted on the handler thread, but the IpClient has // since been stopped such as may be the case if updateInterfaceLinkState() is @@ -546,7 +546,7 @@ public class EthernetNetworkFactory extends NetworkFactory { realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null); } - void onIpLayerStopped(@Nullable final IInternalNetworkManagementListener listener) { + void onIpLayerStopped(@Nullable final IEthernetNetworkManagementListener listener) { // This cannot happen due to provisioning timeout, because our timeout is 0. It can // happen due to errors while provisioning or on provisioning loss. if(mIpClient == null) { @@ -567,13 +567,13 @@ public class EthernetNetworkFactory extends NetworkFactory { private void maybeSendNetworkManagementCallbackForAbort() { realizeNetworkManagementCallback(null, - new InternalNetworkManagementException( + new EthernetNetworkManagementException( "The IP provisioning request has been aborted.")); } // Must be called on the handler thread private void realizeNetworkManagementCallback(@Nullable final Network network, - @Nullable final InternalNetworkManagementException e) { + @Nullable final EthernetNetworkManagementException e) { ensureRunningOnEthernetHandlerThread(); if (null == mIpClientCallback) { return; @@ -621,10 +621,10 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ boolean updateLinkState(final boolean up, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (mLinkUp == up) { EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null, - new InternalNetworkManagementException( + new EthernetNetworkManagementException( "No changes with requested link state " + up + " for " + name)); return false; } @@ -692,7 +692,7 @@ public class EthernetNetworkFactory extends NetworkFactory { restart(null); } - void restart(@Nullable final IInternalNetworkManagementListener listener){ + void restart(@Nullable final IEthernetNetworkManagementListener listener){ if (DBG) Log.d(TAG, "reconnecting Ethernet"); stop(); start(listener); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 6f6a04a273..dffac37fd2 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -22,9 +22,9 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; -import android.net.IInternalNetworkManagementListener; +import android.net.IEthernetNetworkManagementListener; import android.net.ITetheredInterfaceCallback; -import android.net.InternalNetworkUpdateRequest; +import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; import android.os.Binder; import android.os.Handler; @@ -227,8 +227,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void updateConfiguration(@NonNull final String iface, - @NonNull final InternalNetworkUpdateRequest request, - @Nullable final IInternalNetworkManagementListener listener) { + @NonNull final EthernetNetworkUpdateRequest request, + @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "updateConfiguration called with: iface=" + iface + ", request=" + request + ", listener=" + listener); validateNetworkManagementState(iface, "updateConfiguration()"); @@ -240,7 +240,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void connectNetwork(@NonNull final String iface, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); validateNetworkManagementState(iface, "connectNetwork()"); mTracker.connectNetwork(iface, listener); @@ -248,7 +248,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void disconnectNetwork(@NonNull final String iface, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); validateNetworkManagementState(iface, "disconnectNetwork()"); mTracker.disconnectNetwork(iface, listener); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 97845120db..6c8e6d3a97 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -24,7 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.IEthernetServiceListener; -import android.net.IInternalNetworkManagementListener; +import android.net.IEthernetNetworkManagementListener; import android.net.INetd; import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfigurationParcel; @@ -178,7 +178,7 @@ public class EthernetTracker { protected void updateConfiguration(@NonNull final String iface, @NonNull final StaticIpConfiguration staticIpConfig, @NonNull final NetworkCapabilities capabilities, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities + ", staticIpConfig: " + staticIpConfig); @@ -192,13 +192,13 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void connectNetwork(@NonNull final String iface, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { mHandler.post(() -> updateInterfaceState(iface, true, listener)); } @VisibleForTesting(visibility = PACKAGE) protected void disconnectNetwork(@NonNull final String iface, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { mHandler.post(() -> updateInterfaceState(iface, false, listener)); } @@ -370,7 +370,7 @@ public class EthernetTracker { } private void updateInterfaceState(@NonNull final String iface, final boolean up, - @Nullable final IInternalNetworkManagementListener listener) { + @Nullable final IEthernetNetworkManagementListener listener) { final int mode = getInterfaceMode(iface); final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) && mFactory.updateInterfaceLinkState(iface, up, listener); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index b8f0ada5a4..7a90eeedd7 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -40,8 +40,8 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; -import android.net.IInternalNetworkManagementListener; -import android.net.InternalNetworkManagementException; +import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkManagementException; import android.net.IpConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -83,7 +83,7 @@ import java.util.concurrent.TimeUnit; public class EthernetNetworkFactoryTest { private static final int TIMEOUT_MS = 2_000; private static final String TEST_IFACE = "test123"; - private static final IInternalNetworkManagementListener NULL_LISTENER = null; + private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private static final String IP_ADDR = "192.0.2.2/25"; private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); private static final String HW_ADDR = "01:02:03:04:05:06"; @@ -627,17 +627,17 @@ public class EthernetNetworkFactoryTest { } private static final class TestNetworkManagementListener - implements IInternalNetworkManagementListener { - private final CompletableFuture> mDone + implements IEthernetNetworkManagementListener { + private final CompletableFuture> mDone = new CompletableFuture<>(); @Override public void onComplete(final Network network, - final InternalNetworkManagementException exception) { + final EthernetNetworkManagementException exception) { mDone.complete(new Pair<>(network, exception)); } - Pair expectOnComplete() throws Exception { + Pair expectOnComplete() throws Exception { return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); } @@ -704,7 +704,7 @@ public class EthernetNetworkFactoryTest { private void assertSuccessfulListener( @NonNull final TestNetworkManagementListener successfulListener, @NonNull final Network expectedNetwork) throws Exception { - final Pair successfulResult = + final Pair successfulResult = successfulListener.expectOnComplete(); assertEquals(expectedNetwork, successfulResult.first); assertNull(successfulResult.second); @@ -713,7 +713,7 @@ public class EthernetNetworkFactoryTest { private void assertFailedListener(@NonNull final TestNetworkManagementListener failedListener, @NonNull final String errMsg) throws Exception { - final Pair failedResult = + final Pair failedResult = failedListener.expectOnComplete(); assertNull(failedResult.first); assertNotNull(failedResult.second); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 6593aa5898..18d6f3b66d 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -25,8 +25,8 @@ import static org.mockito.Mockito.verify; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; -import android.net.IInternalNetworkManagementListener; -import android.net.InternalNetworkUpdateRequest; +import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; @@ -45,10 +45,10 @@ import org.mockito.MockitoAnnotations; @SmallTest public class EthernetServiceImplTest { private static final String TEST_IFACE = "test123"; - private static final InternalNetworkUpdateRequest UPDATE_REQUEST = - new InternalNetworkUpdateRequest( + private static final EthernetNetworkUpdateRequest UPDATE_REQUEST = + new EthernetNetworkUpdateRequest( new StaticIpConfiguration(), new NetworkCapabilities.Builder().build()); - private static final IInternalNetworkManagementListener NULL_LISTENER = null; + private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @Mock private Handler mHandler; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 5087a9bcf4..14f34d0dab 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -30,7 +30,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.net.InetAddresses; -import android.net.IInternalNetworkManagementListener; +import android.net.IEthernetNetworkManagementListener; import android.net.INetd; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -62,7 +62,7 @@ public class EthernetTrackerTest { private static final String TEST_IFACE = "test123"; private static final int TIMEOUT_MS = 1_000; private static final String THREAD_NAME = "EthernetServiceThread"; - private static final IInternalNetworkManagementListener NULL_LISTENER = null; + private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private EthernetTracker tracker; private HandlerThread mHandlerThread; @Mock private Context mContext; @@ -325,7 +325,7 @@ public class EthernetTrackerTest { public void testUpdateConfiguration() { final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build(); final StaticIpConfiguration staticIpConfig = new StaticIpConfiguration(); - final IInternalNetworkManagementListener listener = null; + final IEthernetNetworkManagementListener listener = null; tracker.updateConfiguration(TEST_IFACE, staticIpConfig, capabilities, listener); waitForIdle(); From 271548c96d50944cc93405e6b30605bbef1dece9 Mon Sep 17 00:00:00 2001 From: hepengtao Date: Tue, 19 Oct 2021 17:25:50 +0800 Subject: [PATCH 813/881] NSD: Specify on what interface to getAddrInfo When discover two different host with same host name from different network interface, specify on what interface to getAddrInfo. Bug: 203453164 Test: build & manual Signed-off-by: hepengtao Change-Id: Ifaccb7f3fac6b1dd789cc9ce7c8d964102754508 --- service-t/src/com/android/server/NsdService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java index 497107dbf9..eca4ccf680 100644 --- a/service-t/src/com/android/server/NsdService.java +++ b/service-t/src/com/android/server/NsdService.java @@ -488,7 +488,7 @@ public class NsdService extends INsdManager.Stub { removeRequestMap(clientId, id, clientInfo); int id2 = getUniqueId(); - if (getAddrInfo(id2, cooked[3])) { + if (getAddrInfo(id2, cooked[3], cooked[7])) { storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); } else { clientInfo.onResolveServiceFailed( @@ -833,8 +833,8 @@ public class NsdService extends INsdManager.Stub { return mDaemon.execute("stop-resolve", resolveId); } - private boolean getAddrInfo(int resolveId, String hostname) { - return mDaemon.execute("getaddrinfo", resolveId, hostname); + private boolean getAddrInfo(int resolveId, String hostname, String interfaceName) { + return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceName); } private boolean stopGetAddrInfo(int resolveId) { From 74a5a70b6f4c068400c6ac25babfc354c5e61a08 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Fri, 28 Jan 2022 19:43:48 -0800 Subject: [PATCH 814/881] Adding permission for Ethernet Network Management Adding MANAGE_ETHERNET_NETWORKS as a signature level permission to allow an application to dynamically change ethernet network values. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: Icf9c2accc86735cc981adc0d5a24802e0616ffaf Merged-In: Icf9c2accc86735cc981adc0d5a24802e0616ffaf --- framework-t/src/android/net/EthernetManager.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index f472d563c4..e0ce081c02 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -358,6 +358,7 @@ public class EthernetManager { return proxy; } + @RequiresPermission(android.Manifest.permission.MANAGE_ETHERNET_NETWORKS) private void updateConfiguration( @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, @@ -372,6 +373,7 @@ public class EthernetManager { } } + @RequiresPermission(android.Manifest.permission.MANAGE_ETHERNET_NETWORKS) private void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, @@ -385,6 +387,7 @@ public class EthernetManager { } } + @RequiresPermission(android.Manifest.permission.MANAGE_ETHERNET_NETWORKS) private void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, From 1b1222adea3e1d79b1a6d76e6793833e067d2da5 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Fri, 28 Jan 2022 19:46:40 -0800 Subject: [PATCH 815/881] Updating Eth Service to use Eth Network Permission Updating Ethernet Service network management APIs to require the manage ethernet networks permission. Bug: 210485380 Test: atest EthernetServiceTests Change-Id: Ibc9b2930fc0069efd7c6f4b833aba7d6c8e93311 --- .../server/ethernet/EthernetServiceImpl.java | 10 ++++-- .../ethernet/EthernetNetworkFactoryTest.java | 2 +- .../ethernet/EthernetServiceImplTest.java | 33 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index dffac37fd2..ffd6d4070e 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -208,6 +208,12 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { pw.decreaseIndent(); } + private void enforceNetworkManagementPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_ETHERNET_NETWORKS, + "EthernetServiceImpl"); + } + /** * Validate the state of ethernet for APIs tied to network management. * @@ -216,12 +222,12 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { */ private void validateNetworkManagementState(@NonNull final String iface, final @NonNull String methodName) { + enforceAutomotiveDevice(methodName); + enforceNetworkManagementPermission(); logIfEthernetNotStarted(); - // TODO: add permission check here for MANAGE_INTERNAL_NETWORKS when it's available. Objects.requireNonNull(iface, "Pass a non-null iface."); Objects.requireNonNull(methodName, "Pass a non-null methodName."); - enforceAutomotiveDevice(methodName); enforceInterfaceIsTracked(iface); } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 7a90eeedd7..6e7c267445 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -362,7 +362,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - assertFailedListener(listener, "can't be updated as it is not configured"); + assertFailedListener(listener, "can't be updated as it is not available"); } @Test diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 18d6f3b66d..0ac28c43dd 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -18,10 +18,13 @@ package com.android.server.ethernet; import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.verify; +import android.Manifest; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; @@ -176,6 +179,36 @@ public class EthernetServiceImplTest { }); } + private void denyManageEthPermission() { + doThrow(new SecurityException("")).when(mContext) + .enforceCallingOrSelfPermission( + eq(Manifest.permission.MANAGE_ETHERNET_NETWORKS), anyString()); + } + + @Test + public void testUpdateConfigurationRejectsWithoutManageEthPermission() { + denyManageEthPermission(); + assertThrows(SecurityException.class, () -> { + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); + }); + } + + @Test + public void testConnectNetworkRejectsWithoutManageEthPermission() { + denyManageEthPermission(); + assertThrows(SecurityException.class, () -> { + mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER); + }); + } + + @Test + public void testDisconnectNetworkRejectsWithoutManageEthPermission() { + denyManageEthPermission(); + assertThrows(SecurityException.class, () -> { + mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); + }); + } + @Test public void testUpdateConfiguration() { mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); From bca7618ded9d6b97fd04011ff59220c065584859 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 16 Dec 2021 15:31:16 +0900 Subject: [PATCH 816/881] Support discover/resolve on specific networks This adds a Network member to NsdServiceInfo, allowing discovered services to report which network they were discovered on, and clients to specify which network to resolve the service on. If clients use the discovered NsdServiceInfo to resolve a service, it will be resolved on the network where it was discovered instead of an unspecified network. Also add a network parameter to a new overload of NsdManager#discoverServices, so that clients can discover on specific networks. Bug: 190249673 Test: atest NsdManagerTest Change-Id: Idc4bf9fde0f4b0328204a8cd2eedc12fffbbbdba --- .../src/android/net/nsd/NsdManager.java | 16 ++- .../src/android/net/nsd/NsdServiceInfo.java | 39 ++++- .../src/com/android/server/NsdService.java | 134 ++++++++++++++++-- 3 files changed, 167 insertions(+), 22 deletions(-) diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java index 0f21e55b9f..ea69e092c4 100644 --- a/framework-t/src/android/net/nsd/NsdManager.java +++ b/framework-t/src/android/net/nsd/NsdManager.java @@ -16,6 +16,8 @@ package android.net.nsd; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; @@ -23,6 +25,7 @@ import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.Context; +import android.net.Network; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -633,6 +636,14 @@ public final class NsdManager { } } + /** + * Same as {@link #discoverServices(String, int, Network, DiscoveryListener)} with a null + * {@link Network}. + */ + public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { + discoverServices(serviceType, protocolType, null, listener); + } + /** * Initiate service discovery to browse for instances of a service type. Service discovery * consumes network bandwidth and will continue until the application calls @@ -657,11 +668,13 @@ public final class NsdManager { * @param serviceType The service type being discovered. Examples include "_http._tcp" for * http services or "_ipp._tcp" for printers * @param protocolType The service discovery protocol + * @param network Network to discover services on, or null to discover on all available networks * @param listener The listener notifies of a successful discovery and is used * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. * Cannot be null. Cannot be in use for an active service discovery. */ - public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { + public void discoverServices(@NonNull String serviceType, int protocolType, + @Nullable Network network, @NonNull DiscoveryListener listener) { if (TextUtils.isEmpty(serviceType)) { throw new IllegalArgumentException("Service type cannot be empty"); } @@ -669,6 +682,7 @@ public final class NsdManager { NsdServiceInfo s = new NsdServiceInfo(); s.setServiceType(serviceType); + s.setNetwork(network); int key = putListener(listener, s); try { diff --git a/framework-t/src/android/net/nsd/NsdServiceInfo.java b/framework-t/src/android/net/nsd/NsdServiceInfo.java index 0946499f16..8506db1fbe 100644 --- a/framework-t/src/android/net/nsd/NsdServiceInfo.java +++ b/framework-t/src/android/net/nsd/NsdServiceInfo.java @@ -17,7 +17,9 @@ package android.net.nsd; import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.net.Network; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -49,6 +51,9 @@ public final class NsdServiceInfo implements Parcelable { private int mPort; + @Nullable + private Network mNetwork; + public NsdServiceInfo() { } @@ -307,18 +312,37 @@ public final class NsdServiceInfo implements Parcelable { return txtRecord; } - public String toString() { - StringBuffer sb = new StringBuffer(); + /** + * Get the network where the service can be found. + * + * This is never null if this {@link NsdServiceInfo} was obtained from + * {@link NsdManager#discoverServices} or {@link NsdManager#resolveService}. + */ + @Nullable + public Network getNetwork() { + return mNetwork; + } + /** + * Set the network where the service can be found. + * @param network The network, or null to search for, or to announce, the service on all + * connected networks. + */ + public void setNetwork(@Nullable Network network) { + mNetwork = network; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); sb.append("name: ").append(mServiceName) .append(", type: ").append(mServiceType) .append(", host: ").append(mHost) - .append(", port: ").append(mPort); + .append(", port: ").append(mPort) + .append(", network: ").append(mNetwork); byte[] txtRecord = getTxtRecord(); - if (txtRecord != null) { - sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8)); - } + sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8)); return sb.toString(); } @@ -352,6 +376,8 @@ public final class NsdServiceInfo implements Parcelable { } dest.writeString(key); } + + dest.writeParcelable(mNetwork, 0); } /** Implement the Parcelable interface */ @@ -381,6 +407,7 @@ public final class NsdServiceInfo implements Parcelable { } info.mTxtRecord.put(in.readString(), valueArray); } + info.mNetwork = in.readParcelable(null, Network.class); return info; } diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java index eca4ccf680..ddf6d2c4ab 100644 --- a/service-t/src/com/android/server/NsdService.java +++ b/service-t/src/com/android/server/NsdService.java @@ -19,6 +19,9 @@ package com.android.server; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.net.LinkProperties; +import android.net.Network; import android.net.nsd.INsdManager; import android.net.nsd.INsdManagerCallback; import android.net.nsd.INsdServiceConnector; @@ -44,6 +47,9 @@ import com.android.net.module.util.DnsSdTxtRecord; import java.io.FileDescriptor; import java.io.PrintWriter; import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; import java.util.Arrays; import java.util.HashMap; import java.util.concurrent.CountDownLatch; @@ -60,6 +66,7 @@ public class NsdService extends INsdManager.Stub { private static final boolean DBG = true; private static final long CLEANUP_DELAY_MS = 10000; + private static final int IFACE_IDX_ANY = 0; private final Context mContext; private final NsdStateMachine mNsdStateMachine; @@ -297,7 +304,7 @@ public class NsdService extends INsdManager.Stub { maybeStartDaemon(); id = getUniqueId(); - if (discoverServices(id, args.serviceInfo.getServiceType())) { + if (discoverServices(id, args.serviceInfo)) { if (DBG) { Log.d(TAG, "Discover " + msg.arg2 + " " + id + args.serviceInfo.getServiceType()); @@ -430,13 +437,38 @@ public class NsdService extends INsdManager.Stub { } switch (code) { case NativeResponseCode.SERVICE_FOUND: - /* NNN uniqueId serviceName regType domain */ + /* NNN uniqueId serviceName regType domain interfaceIdx netId */ servInfo = new NsdServiceInfo(cooked[2], cooked[3]); + final int foundNetId; + try { + foundNetId = Integer.parseInt(cooked[6]); + } catch (NumberFormatException e) { + Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]); + break; + } + if (foundNetId == 0L) { + // Ignore services that do not have a Network: they are not usable + // by apps, as they would need privileged permissions to use + // interfaces that do not have an associated Network. + break; + } + servInfo.setNetwork(new Network(foundNetId)); clientInfo.onServiceFound(clientId, servInfo); break; case NativeResponseCode.SERVICE_LOST: - /* NNN uniqueId serviceName regType domain */ + /* NNN uniqueId serviceName regType domain interfaceIdx netId */ + final int lostNetId; + try { + lostNetId = Integer.parseInt(cooked[6]); + } catch (NumberFormatException e) { + Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]); + break; + } servInfo = new NsdServiceInfo(cooked[2], cooked[3]); + // The network could be null if it was torn down when the service is lost + // TODO: avoid returning null in that case, possibly by remembering found + // services on the same interface index and their network at the time + servInfo.setNetwork(lostNetId == 0 ? null : new Network(lostNetId)); clientInfo.onServiceLost(clientId, servInfo); break; case NativeResponseCode.SERVICE_DISCOVERY_FAILED: @@ -461,7 +493,7 @@ public class NsdService extends INsdManager.Stub { /* NNN regId errorCode */ break; case NativeResponseCode.SERVICE_RESOLVED: - /* NNN resolveId fullName hostName port txtlen txtdata */ + /* NNN resolveId fullName hostName port txtlen txtdata interfaceIdx */ int index = 0; while (index < cooked[2].length() && cooked[2].charAt(index) != '.') { if (cooked[2].charAt(index) == '\\') { @@ -473,6 +505,7 @@ public class NsdService extends INsdManager.Stub { Log.e(TAG, "Invalid service found " + raw); break; } + String name = cooked[2].substring(0, index); String rest = cooked[2].substring(index); String type = rest.replace(".local.", ""); @@ -483,12 +516,13 @@ public class NsdService extends INsdManager.Stub { clientInfo.mResolvedService.setServiceType(type); clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4])); clientInfo.mResolvedService.setTxtRecords(cooked[6]); + // Network will be added after SERVICE_GET_ADDR_SUCCESS stopResolveService(id); removeRequestMap(clientId, id, clientInfo); int id2 = getUniqueId(); - if (getAddrInfo(id2, cooked[3], cooked[7])) { + if (getAddrInfo(id2, cooked[3], cooked[7] /* interfaceIdx */)) { storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE); } else { clientInfo.onResolveServiceFailed( @@ -513,12 +547,31 @@ public class NsdService extends INsdManager.Stub { clientId, NsdManager.FAILURE_INTERNAL_ERROR); break; case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS: - /* NNN resolveId hostname ttl addr */ + /* NNN resolveId hostname ttl addr interfaceIdx netId */ + Network network = null; try { - clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4])); + final int netId = Integer.parseInt(cooked[6]); + network = netId == 0L ? null : new Network(netId); + } catch (NumberFormatException e) { + Log.wtf(TAG, "Invalid network in GET_ADDR_SUCCESS: " + cooked[6], e); + } + + InetAddress serviceHost = null; + try { + serviceHost = InetAddress.getByName(cooked[4]); + } catch (UnknownHostException e) { + Log.wtf(TAG, "Invalid host in GET_ADDR_SUCCESS", e); + } + + // If the resolved service is on an interface without a network, consider it + // as a failure: it would not be usable by apps as they would need + // privileged permissions. + if (network != null && serviceHost != null) { + clientInfo.mResolvedService.setHost(serviceHost); + clientInfo.mResolvedService.setNetwork(network); clientInfo.onResolveServiceSucceeded( clientId, clientInfo.mResolvedService); - } catch (java.net.UnknownHostException e) { + } else { clientInfo.onResolveServiceFailed( clientId, NsdManager.FAILURE_INTERNAL_ERROR); } @@ -815,8 +868,15 @@ public class NsdService extends INsdManager.Stub { return mDaemon.execute("update", regId, t.size(), t.getRawData()); } - private boolean discoverServices(int discoveryId, String serviceType) { - return mDaemon.execute("discover", discoveryId, serviceType); + private boolean discoverServices(int discoveryId, NsdServiceInfo serviceInfo) { + final Network network = serviceInfo.getNetwork(); + final int discoverInterface = getNetworkInterfaceIndex(network); + if (network != null && discoverInterface == IFACE_IDX_ANY) { + Log.e(TAG, "Interface to discover service on not found"); + return false; + } + return mDaemon.execute("discover", discoveryId, serviceInfo.getServiceType(), + discoverInterface); } private boolean stopServiceDiscovery(int discoveryId) { @@ -824,17 +884,61 @@ public class NsdService extends INsdManager.Stub { } private boolean resolveService(int resolveId, NsdServiceInfo service) { - String name = service.getServiceName(); - String type = service.getServiceType(); - return mDaemon.execute("resolve", resolveId, name, type, "local."); + final String name = service.getServiceName(); + final String type = service.getServiceType(); + final Network network = service.getNetwork(); + final int resolveInterface = getNetworkInterfaceIndex(network); + if (network != null && resolveInterface == IFACE_IDX_ANY) { + Log.e(TAG, "Interface to resolve service on not found"); + return false; + } + return mDaemon.execute("resolve", resolveId, name, type, "local.", resolveInterface); + } + + /** + * Guess the interface to use to resolve or discover a service on a specific network. + * + * This is an imperfect guess, as for example the network may be gone or not yet fully + * registered. This is fine as failing is correct if the network is gone, and a client + * attempting to resolve/discover on a network not yet setup would have a bad time anyway; also + * this is to support the legacy mdnsresponder implementation, which historically resolved + * services on an unspecified network. + */ + private int getNetworkInterfaceIndex(Network network) { + if (network == null) return IFACE_IDX_ANY; + + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + if (cm == null) { + Log.wtf(TAG, "No ConnectivityManager for resolveService"); + return IFACE_IDX_ANY; + } + final LinkProperties lp = cm.getLinkProperties(network); + if (lp == null) return IFACE_IDX_ANY; + + // Only resolve on non-stacked interfaces + final NetworkInterface iface; + try { + iface = NetworkInterface.getByName(lp.getInterfaceName()); + } catch (SocketException e) { + Log.e(TAG, "Error querying interface", e); + return IFACE_IDX_ANY; + } + + if (iface == null) { + Log.e(TAG, "Interface not found: " + lp.getInterfaceName()); + return IFACE_IDX_ANY; + } + + return iface.getIndex(); } private boolean stopResolveService(int resolveId) { return mDaemon.execute("stop-resolve", resolveId); } - private boolean getAddrInfo(int resolveId, String hostname, String interfaceName) { - return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceName); + private boolean getAddrInfo(int resolveId, String hostname, String interfaceIdx) { + // interfaceIdx is always obtained (as string) from the service resolved callback + return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceIdx); } private boolean stopGetAddrInfo(int resolveId) { From 1ddba4c56af65ce30315c27e760334789bfd4548 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 18 Jan 2022 19:44:57 +0900 Subject: [PATCH 817/881] Support discovering services with a NetworkRequest A common mistake when using service discovery is to mismanage networks, expecting to find or be able to access services on networks that may not be available yet, or may be stale/lost. This new API allows clients to start service discovery with just a NetworkRequest, letting NsdManager track networks and notify when services are found/lost for each network. Bug: 190249673 Test: atest NsdManagerTest Change-Id: I12e799aa48fce2d1a35f708c5617386b1cc70f21 --- .../src/android/net/nsd/NsdManager.java | 249 +++++++++++++++++- 1 file changed, 248 insertions(+), 1 deletion(-) diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java index ea69e092c4..512fbcee93 100644 --- a/framework-t/src/android/net/nsd/NsdManager.java +++ b/framework-t/src/android/net/nsd/NsdManager.java @@ -18,6 +18,7 @@ package android.net.nsd; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemService; @@ -25,16 +26,22 @@ import android.app.compat.CompatChanges; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.content.Context; +import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; import android.net.Network; +import android.net.NetworkRequest; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.Objects; @@ -281,9 +288,180 @@ public final class NsdManager { private final SparseArray mListenerMap = new SparseArray(); private final SparseArray mServiceMap = new SparseArray<>(); private final Object mMapLock = new Object(); + // Map of listener key sent by client -> per-network discovery tracker + @GuardedBy("mPerNetworkDiscoveryMap") + private final ArrayMap + mPerNetworkDiscoveryMap = new ArrayMap<>(); private final ServiceHandler mHandler; + private class PerNetworkDiscoveryTracker { + final String mServiceType; + final int mProtocolType; + final DiscoveryListener mBaseListener; + final ArrayMap mPerNetworkListeners = + new ArrayMap<>(); + + final NetworkCallback mNetworkCb = new NetworkCallback() { + @Override + public void onAvailable(@NonNull Network network) { + final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener( + network, mBaseListener); + mPerNetworkListeners.put(network, wrappedListener); + discoverServices(mServiceType, mProtocolType, network, wrappedListener); + } + + @Override + public void onLost(@NonNull Network network) { + final DelegatingDiscoveryListener listener = mPerNetworkListeners.get(network); + if (listener == null) return; + listener.notifyAllServicesLost(); + // Listener will be removed from map in discovery stopped callback + stopServiceDiscovery(listener); + } + }; + + // Accessed from mHandler + private boolean mStopRequested; + + public void start(@NonNull NetworkRequest request) { + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.registerNetworkCallback(request, mNetworkCb, mHandler); + mHandler.post(() -> mBaseListener.onDiscoveryStarted(mServiceType)); + } + + /** + * Stop discovery on all networks tracked by this class. + * + * This will request all underlying listeners to stop, and the last one to stop will call + * onDiscoveryStopped or onStopDiscoveryFailed. + * + * Must be called on the handler thread. + */ + public void requestStop() { + mHandler.post(() -> { + mStopRequested = true; + final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); + cm.unregisterNetworkCallback(mNetworkCb); + if (mPerNetworkListeners.size() == 0) { + mBaseListener.onDiscoveryStopped(mServiceType); + return; + } + for (int i = 0; i < mPerNetworkListeners.size(); i++) { + final DelegatingDiscoveryListener listener = mPerNetworkListeners.valueAt(i); + stopServiceDiscovery(listener); + } + }); + } + + private PerNetworkDiscoveryTracker(String serviceType, int protocolType, + DiscoveryListener baseListener) { + mServiceType = serviceType; + mProtocolType = protocolType; + mBaseListener = baseListener; + } + + /** + * Subset of NsdServiceInfo that is tracked to generate service lost notifications when a + * network is lost. + * + * Service lost notifications only contain service name, type and network, so only track + * that information (Network is known from the listener). This also implements + * equals/hashCode for usage in maps. + */ + private class TrackedNsdInfo { + private final String mServiceName; + private final String mServiceType; + TrackedNsdInfo(NsdServiceInfo info) { + mServiceName = info.getServiceName(); + mServiceType = info.getServiceType(); + } + + @Override + public int hashCode() { + return Objects.hash(mServiceName, mServiceType); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof TrackedNsdInfo)) return false; + final TrackedNsdInfo other = (TrackedNsdInfo) obj; + return Objects.equals(mServiceName, other.mServiceName) + && Objects.equals(mServiceType, other.mServiceType); + } + } + + private class DelegatingDiscoveryListener implements DiscoveryListener { + private final Network mNetwork; + private final DiscoveryListener mWrapped; + private final ArraySet mFoundInfo = new ArraySet<>(); + + private DelegatingDiscoveryListener(Network network, DiscoveryListener listener) { + mNetwork = network; + mWrapped = listener; + } + + void notifyAllServicesLost() { + for (int i = 0; i < mFoundInfo.size(); i++) { + final TrackedNsdInfo trackedInfo = mFoundInfo.valueAt(i); + final NsdServiceInfo serviceInfo = new NsdServiceInfo( + trackedInfo.mServiceName, trackedInfo.mServiceType); + serviceInfo.setNetwork(mNetwork); + mWrapped.onServiceLost(serviceInfo); + } + } + + @Override + public void onStartDiscoveryFailed(String serviceType, int errorCode) { + // The delegated listener is used when NsdManager takes care of starting/stopping + // discovery on multiple networks. Failure to start on one network is not a global + // failure to be reported up, as other networks may succeed: just log. + Log.e(TAG, "Failed to start discovery for " + serviceType + " on " + mNetwork + + " with code " + errorCode); + mPerNetworkListeners.remove(mNetwork); + } + + @Override + public void onDiscoveryStarted(String serviceType) { + // Wrapped listener was called upon registration, it is not called for discovery + // on each network + } + + @Override + public void onStopDiscoveryFailed(String serviceType, int errorCode) { + Log.e(TAG, "Failed to stop discovery for " + serviceType + " on " + mNetwork + + " with code " + errorCode); + mPerNetworkListeners.remove(mNetwork); + if (mStopRequested && mPerNetworkListeners.size() == 0) { + // Do not report onStopDiscoveryFailed when some underlying listeners failed: + // this does not mean that all listeners did, and onStopDiscoveryFailed is not + // actionable anyway. Just report that discovery stopped. + mWrapped.onDiscoveryStopped(serviceType); + } + } + + @Override + public void onDiscoveryStopped(String serviceType) { + mPerNetworkListeners.remove(mNetwork); + if (mStopRequested && mPerNetworkListeners.size() == 0) { + mWrapped.onDiscoveryStopped(serviceType); + } + } + + @Override + public void onServiceFound(NsdServiceInfo serviceInfo) { + mFoundInfo.add(new TrackedNsdInfo(serviceInfo)); + mWrapped.onServiceFound(serviceInfo); + } + + @Override + public void onServiceLost(NsdServiceInfo serviceInfo) { + mFoundInfo.remove(new TrackedNsdInfo(serviceInfo)); + mWrapped.onServiceLost(serviceInfo); + } + } + } + /** * Create a new Nsd instance. Applications use * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve @@ -641,7 +819,7 @@ public final class NsdManager { * {@link Network}. */ public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { - discoverServices(serviceType, protocolType, null, listener); + discoverServices(serviceType, protocolType, (Network) null, listener); } /** @@ -692,6 +870,67 @@ public final class NsdManager { } } + /** + * Initiate service discovery to browse for instances of a service type. Service discovery + * consumes network bandwidth and will continue until the application calls + * {@link #stopServiceDiscovery}. + * + *

The function call immediately returns after sending a request to start service + * discovery to the framework. The application is notified of a success to initiate + * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure + * through {@link DiscoveryListener#onStartDiscoveryFailed}. + * + *

Upon successful start, application is notified when a service is found with + * {@link DiscoveryListener#onServiceFound} or when a service is lost with + * {@link DiscoveryListener#onServiceLost}. + * + *

Upon failure to start, service discovery is not active and application does + * not need to invoke {@link #stopServiceDiscovery} + * + *

The application should call {@link #stopServiceDiscovery} when discovery of this + * service type is no longer required, and/or whenever the application is paused or + * stopped. + * + *

During discovery, new networks may connect or existing networks may disconnect - for + * example if wifi is reconnected. When a service was found on a network that disconnects, + * {@link DiscoveryListener#onServiceLost} will be called. If a new network connects that + * matches the {@link NetworkRequest}, {@link DiscoveryListener#onServiceFound} will be called + * for services found on that network. Applications that do not want to track networks + * themselves are encouraged to use this method instead of other overloads of + * {@code discoverServices}, as they will receive proper notifications when a service becomes + * available or unavailable due to network changes. + * + * @param serviceType The service type being discovered. Examples include "_http._tcp" for + * http services or "_ipp._tcp" for printers + * @param protocolType The service discovery protocol + * @param networkRequest Request specifying networks that should be considered when discovering + * @param listener The listener notifies of a successful discovery and is used + * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. + * Cannot be null. Cannot be in use for an active service discovery. + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + public void discoverServices(@NonNull String serviceType, int protocolType, + @NonNull NetworkRequest networkRequest, @NonNull DiscoveryListener listener) { + if (TextUtils.isEmpty(serviceType)) { + throw new IllegalArgumentException("Service type cannot be empty"); + } + Objects.requireNonNull(networkRequest, "NetworkRequest cannot be null"); + checkProtocol(protocolType); + + NsdServiceInfo s = new NsdServiceInfo(); + s.setServiceType(serviceType); + + final int baseListenerKey = putListener(listener, s); + + final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker( + serviceType, protocolType, listener); + + synchronized (mPerNetworkDiscoveryMap) { + mPerNetworkDiscoveryMap.put(baseListenerKey, discoveryInfo); + discoveryInfo.start(networkRequest); + } + } + /** * Stop service discovery initiated with {@link #discoverServices}. An active service * discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted} @@ -710,6 +949,14 @@ public final class NsdManager { */ public void stopServiceDiscovery(DiscoveryListener listener) { int id = getListenerKey(listener); + // If this is a PerNetworkDiscovery request, handle it as such + synchronized (mPerNetworkDiscoveryMap) { + final PerNetworkDiscoveryTracker info = mPerNetworkDiscoveryMap.get(id); + if (info != null) { + info.requestStop(); + return; + } + } try { mService.stopDiscovery(id); } catch (RemoteException e) { From fc3b420236653939a09a9fd5ce3bf9785e1300a9 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 2 Feb 2022 22:28:28 +0100 Subject: [PATCH 818/881] Add key / value data structures for IBpfMaps Add key / value structures for CookieTagMap, StatsMap, and UidStatsMap. This will be used for deleteTagData. Test: m Change-Id: I955ae7f7745d4c5f37eccbad80cdb841ef55ff56 --- service-t/Sources.bp | 5 ++ .../android/server/net/CookieTagMapKey.java | 33 +++++++++++++ .../android/server/net/CookieTagMapValue.java | 37 +++++++++++++++ .../com/android/server/net/StatsMapKey.java | 46 +++++++++++++++++++ .../com/android/server/net/StatsMapValue.java | 46 +++++++++++++++++++ .../android/server/net/UidStatsMapKey.java | 33 +++++++++++++ 6 files changed, 200 insertions(+) create mode 100644 service-t/src/com/android/server/net/CookieTagMapKey.java create mode 100644 service-t/src/com/android/server/net/CookieTagMapValue.java create mode 100644 service-t/src/com/android/server/net/StatsMapKey.java create mode 100644 service-t/src/com/android/server/net/StatsMapValue.java create mode 100644 service-t/src/com/android/server/net/UidStatsMapKey.java diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 24bc91d91e..d05370f9ba 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -28,6 +28,11 @@ filegroup { "src/com/android/server/net/NetworkStats*.java", "src/com/android/server/net/BpfInterfaceMapUpdater.java", "src/com/android/server/net/InterfaceMapValue.java", + "src/com/android/server/net/CookieTagMapKey.java", + "src/com/android/server/net/CookieTagMapValue.java", + "src/com/android/server/net/StatsMapKey.java", + "src/com/android/server/net/StatsMapValue.java", + "src/com/android/server/net/UidStatsMapKey.java", ], path: "src", visibility: [ diff --git a/service-t/src/com/android/server/net/CookieTagMapKey.java b/service-t/src/com/android/server/net/CookieTagMapKey.java new file mode 100644 index 0000000000..443e5b3847 --- /dev/null +++ b/service-t/src/com/android/server/net/CookieTagMapKey.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Key for cookie tag map. + */ +public class CookieTagMapKey extends Struct { + @Field(order = 0, type = Type.S64) + public final long socketCookie; + + public CookieTagMapKey(final long socketCookie) { + this.socketCookie = socketCookie; + } +} diff --git a/service-t/src/com/android/server/net/CookieTagMapValue.java b/service-t/src/com/android/server/net/CookieTagMapValue.java new file mode 100644 index 0000000000..93b9195f92 --- /dev/null +++ b/service-t/src/com/android/server/net/CookieTagMapValue.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Value for cookie tag map. + */ +public class CookieTagMapValue extends Struct { + @Field(order = 0, type = Type.U32) + public final long uid; + + @Field(order = 1, type = Type.U32) + public final long tag; + + public CookieTagMapValue(final long uid, final long tag) { + this.uid = uid; + this.tag = tag; + } +} diff --git a/service-t/src/com/android/server/net/StatsMapKey.java b/service-t/src/com/android/server/net/StatsMapKey.java new file mode 100644 index 0000000000..ea8d836383 --- /dev/null +++ b/service-t/src/com/android/server/net/StatsMapKey.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Key for both stats maps. + */ +public class StatsMapKey extends Struct { + @Field(order = 0, type = Type.U32) + public final long uid; + + @Field(order = 1, type = Type.U32) + public final long tag; + + @Field(order = 2, type = Type.U32) + public final long counterSet; + + @Field(order = 3, type = Type.U32) + public final long ifaceIndex; + + public StatsMapKey(final long uid, final long tag, final long counterSet, + final long ifaceIndex) { + this.uid = uid; + this.tag = tag; + this.counterSet = counterSet; + this.ifaceIndex = ifaceIndex; + } +} diff --git a/service-t/src/com/android/server/net/StatsMapValue.java b/service-t/src/com/android/server/net/StatsMapValue.java new file mode 100644 index 0000000000..48f26ce686 --- /dev/null +++ b/service-t/src/com/android/server/net/StatsMapValue.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Value used for both stats maps and uid stats map. + */ +public class StatsMapValue extends Struct { + @Field(order = 0, type = Type.U63) + public final long rxPackets; + + @Field(order = 1, type = Type.U63) + public final long rxBytes; + + @Field(order = 2, type = Type.U63) + public final long txPackets; + + @Field(order = 3, type = Type.U63) + public final long txBytes; + + public StatsMapValue(final long rxPackets, final long rxBytes, final long txPackets, + final long txBytes) { + this.rxPackets = rxPackets; + this.rxBytes = rxBytes; + this.txPackets = txPackets; + this.txBytes = txBytes; + } +} diff --git a/service-t/src/com/android/server/net/UidStatsMapKey.java b/service-t/src/com/android/server/net/UidStatsMapKey.java new file mode 100644 index 0000000000..2849f94c93 --- /dev/null +++ b/service-t/src/com/android/server/net/UidStatsMapKey.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import com.android.net.module.util.Struct; +import com.android.net.module.util.Struct.Field; +import com.android.net.module.util.Struct.Type; + +/** + * Key for uid stats map. + */ +public class UidStatsMapKey extends Struct { + @Field(order = 0, type = Type.U32) + public final long uid; + + public UidStatsMapKey(final long uid) { + this.uid = uid; + } +} From 5e1593f3a6f3196ac13c420d1c7453d437646b28 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Wed, 2 Feb 2022 14:32:40 -0800 Subject: [PATCH 819/881] Marking eth network management APIs @SystemApi Annotating ethernet network management APIs in EthernetManager with @SystemApi. Bug: 210485380 Test: atest EthernetServiceTests atest CtsNetTestCasesLatestSdk Change-Id: I10429441fd4d7b9bcaa7437b844420a43a415d72 Merged-In: I10429441fd4d7b9bcaa7437b844420a43a415d72 --- .../src/android/net/EthernetManager.java | 90 +++++++++++++++++-- .../EthernetNetworkManagementException.java | 2 + .../net/EthernetNetworkUpdateRequest.java | 3 +- 3 files changed, 88 insertions(+), 7 deletions(-) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index e0ce081c02..1f67f6d654 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -19,12 +19,14 @@ package android.net; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Build; import android.os.RemoteException; @@ -358,12 +360,43 @@ public class EthernetManager { return proxy; } - @RequiresPermission(android.Manifest.permission.MANAGE_ETHERNET_NETWORKS) - private void updateConfiguration( + /** + * Updates the configuration of an automotive device's ethernet network. + * + * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the + * configuration for this network. + * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for + * this network to put inside the {@code request}. + * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities} + * object for this network to put inside the {@code request}. + * + * If non-null, the listener will be called exactly once after this is called, unless + * a synchronous exception was thrown. + * + * @param iface the name of the interface to act upon. + * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's + * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @throws SecurityException if the process doesn't hold + * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. + * @throws UnsupportedOperationException if called on a non-automotive device or on an + * unsupported interface. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) + @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) + public void updateConfiguration( @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, @Nullable BiConsumer listener) { + Objects.requireNonNull(iface, "iface must be non-null"); + Objects.requireNonNull(request, "request must be non-null"); final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { @@ -373,11 +406,34 @@ public class EthernetManager { } } - @RequiresPermission(android.Manifest.permission.MANAGE_ETHERNET_NETWORKS) - private void connectNetwork( + /** + * Set an ethernet network's link state up. + * + * When the link is successfully turned up, the listener will be called with the resulting + * network. If any error or unexpected condition happens while the system tries to turn the + * interface up, the listener will be called with an appropriate exception. + * The listener is guaranteed to be called exactly once for each call to this method, but this + * may take an unbounded amount of time depending on the actual network conditions. + * + * @param iface the name of the interface to act upon. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @throws SecurityException if the process doesn't hold + * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. + * @throws UnsupportedOperationException if called on a non-automotive device. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) + @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) + public void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, @Nullable BiConsumer listener) { + Objects.requireNonNull(iface, "iface must be non-null"); final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { @@ -387,11 +443,33 @@ public class EthernetManager { } } - @RequiresPermission(android.Manifest.permission.MANAGE_ETHERNET_NETWORKS) - private void disconnectNetwork( + /** + * Set an ethernet network's link state down. + * + * When the link is successfully turned down, the listener will be called with the network that + * was torn down, if any. If any error or unexpected condition happens while the system tries to + * turn the interface down, the listener will be called with an appropriate exception. + * The listener is guaranteed to be called exactly once for each call to this method. + * + * @param iface the name of the interface to act upon. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @throws SecurityException if the process doesn't hold + * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. + * @throws UnsupportedOperationException if called on a non-automotive device. + * @hide + */ + @SystemApi + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) + @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) + public void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, @Nullable BiConsumer listener) { + Objects.requireNonNull(iface, "iface must be non-null"); final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( executor, listener); try { diff --git a/framework-t/src/android/net/EthernetNetworkManagementException.java b/framework-t/src/android/net/EthernetNetworkManagementException.java index a35f28e172..a69cc55363 100644 --- a/framework-t/src/android/net/EthernetNetworkManagementException.java +++ b/framework-t/src/android/net/EthernetNetworkManagementException.java @@ -17,12 +17,14 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.util.Objects; /** @hide */ +@SystemApi public final class EthernetNetworkManagementException extends RuntimeException implements Parcelable { diff --git a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java index 4d229d23b1..e879e40247 100644 --- a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java +++ b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java @@ -17,12 +17,14 @@ package android.net; import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import java.util.Objects; /** @hide */ +@SystemApi public final class EthernetNetworkUpdateRequest implements Parcelable { @NonNull private final StaticIpConfiguration mIpConfig; @@ -39,7 +41,6 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { return new NetworkCapabilities(mNetworkCapabilities); } - /** @hide */ public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, @NonNull final NetworkCapabilities networkCapabilities) { Objects.requireNonNull(ipConfig); From 36b96d51754d0143c269ceef710fc8d7d6517269 Mon Sep 17 00:00:00 2001 From: Milim Lee Date: Wed, 28 Apr 2021 13:56:11 +0900 Subject: [PATCH 820/881] Set EthernetNetworkSpecifier on ethernet networks Bug: 175199512 Test: atest EthernetServiceTests Change-Id: I4a4762a6509099a5c0954296cbf1b42e3a6cfc25 --- .../android/server/ethernet/EthernetNetworkFactory.java | 8 ++++++-- .../server/ethernet/EthernetNetworkFactoryTest.java | 7 ++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index a15fec4aba..cc8103b91d 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -176,12 +176,16 @@ public class EthernetNetworkFactory extends NetworkFactory { return; } + final NetworkCapabilities nc = new NetworkCapabilities.Builder(capabilities) + .setNetworkSpecifier(new EthernetNetworkSpecifier(ifaceName)) + .build(); + if (DBG) { - Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities); + Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + nc); } final NetworkInterfaceState iface = new NetworkInterfaceState( - ifaceName, hwAddress, mHandler, mContext, ipConfig, capabilities, this, mDeps); + ifaceName, hwAddress, mHandler, mContext, ipConfig, nc, this, mDeps); mTrackingInterfaces.put(ifaceName, iface); updateCapabilityFilter(); } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 7a90eeedd7..ae52a751b7 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -71,6 +71,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -265,8 +266,12 @@ public class EthernetNetworkFactoryTest { triggerOnProvisioningSuccess(); // provisioning succeeded, verify that the network agent is created, registered, marked // as connected and legacy type are correctly set. - verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), + final ArgumentCaptor ncCaptor = ArgumentCaptor.forClass( + NetworkCapabilities.class); + verify(mDeps).makeEthernetNetworkAgent(any(), any(), ncCaptor.capture(), any(), argThat(x -> x.getLegacyType() == expectedLegacyType), any(), any()); + assertEquals( + new EthernetNetworkSpecifier(iface), ncCaptor.getValue().getNetworkSpecifier()); verifyNetworkAgentRegistersAndConnects(); clearInvocations(mDeps); clearInvocations(mNetworkAgent); From 9adb65a4625ef1379552a37273d5578e13f86ce3 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 9 Feb 2022 08:53:59 +0900 Subject: [PATCH 821/881] Fix testIpClientIsNotStartedWhenLinkIsDown. This test is failing at HEAD because the known bug it is testing for is fixed. Check that IpClient is (correctly) not started when link is down. In order to ensure that the test is correct and that not starting IpClient is not caused by some other setup problem in the test, ensure that IpClient is also (correctly) started if later on link does come up. Test: atest EthernetServiceTests Test: atest --rerun-until-failure 100 EthernetNetworkFactoryTest#testIpClientIsNotStartedWhenLinkIsDown Change-Id: Id30bc9be1fc3ecf3d10c12d0b23c64814f4dbf9c --- .../server/ethernet/EthernetNetworkFactoryTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 6e7c267445..e10497e4e3 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -456,9 +456,10 @@ public class EthernetNetworkFactoryTest { .build(); mNetFactory.needNetworkFor(specificNetRequest); - // TODO(b/155707957): BUG: IPClient should not be started when the interface link state - // is down. - verify(mDeps).makeIpClient(any(), any(), any()); + verify(mDeps, never()).makeIpClient(any(), any(), any()); + + mNetFactory.updateInterfaceLinkState(TEST_IFACE, true, NULL_LISTENER); + verify(mDeps).makeIpClient(any(), eq(TEST_IFACE), any()); } @Test From 7b04f8f339d63019cbf8999e55498dfe7b6437a1 Mon Sep 17 00:00:00 2001 From: Yan Yan Date: Wed, 2 Feb 2022 16:39:45 -0800 Subject: [PATCH 822/881] Un-finalize IpSecManager Allows VCN and IKE unit tests to mock IpSecManager and thus stop depending on the hidden APIs in the Connectivity module (e.g. IpSecService binder interface). Otherwise, any changes on these related hidden APIs will require topic changes across multiple projects. Bug: 217572993 Test: make update-api Test: atest IpSecManagerTest, IpSecManagerTunnelTest Change-Id: I29f3ac96f83b4271f29a7051d33ccf47a0dd6c57 Merged-In: I29f3ac96f83b4271f29a7051d33ccf47a0dd6c57 --- framework-t/src/android/net/IpSecManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework-t/src/android/net/IpSecManager.java b/framework-t/src/android/net/IpSecManager.java index a423783bc1..9cb0947b23 100644 --- a/framework-t/src/android/net/IpSecManager.java +++ b/framework-t/src/android/net/IpSecManager.java @@ -61,7 +61,7 @@ import java.util.Objects; * Internet Protocol */ @SystemService(Context.IPSEC_SERVICE) -public final class IpSecManager { +public class IpSecManager { private static final String TAG = "IpSecManager"; /** From 531889a99304f7e2f48df7fd9f042a0608c3b643 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 9 Feb 2022 14:30:57 +0800 Subject: [PATCH 823/881] Correct typo in the year of copyright Test: m Change-Id: I68e9925b5b6deb7c5c9d57aa4a397c80f8b8d869 --- service-t/src/com/android/server/net/InterfaceMapValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/net/InterfaceMapValue.java b/service-t/src/com/android/server/net/InterfaceMapValue.java index 061f323447..42c0044e66 100644 --- a/service-t/src/com/android/server/net/InterfaceMapValue.java +++ b/service-t/src/com/android/server/net/InterfaceMapValue.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 83400b6b3b393f811d1fe269f346603e08c21002 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 12 Jan 2022 15:11:01 +0800 Subject: [PATCH 824/881] Split out the ipsec API surface and use framework-connectivity-tiramisu (cherry picked from commit 131a8663843fced7b44234bddc93759e56c29344) Bug: 204153604 Test: TH Change-Id: I6cc8aef6a0ab9ce4bcef2797196b1d1b3687acca Merged-In: I6cc8aef6a0ab9ce4bcef2797196b1d1b3687acca --- framework-t/Sources.bp | 2 +- ...nectivityFrameworkInitializerTiramisu.java | 9 ++++++ service-t/Sources.bp | 2 +- .../src/com/android/server/IpSecService.java | 29 +------------------ 4 files changed, 12 insertions(+), 30 deletions(-) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 54538d91a5..6329565ca5 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -158,7 +158,6 @@ filegroup { name: "framework-connectivity-tiramisu-sources", srcs: [ ":framework-connectivity-ethernet-sources", - ":framework-connectivity-ipsec-sources", ":framework-connectivity-netstats-sources", ], visibility: ["//frameworks/base"], @@ -167,6 +166,7 @@ filegroup { filegroup { name: "framework-connectivity-tiramisu-updatable-sources", srcs: [ + ":framework-connectivity-ipsec-sources", ":framework-connectivity-nsd-sources", ":framework-connectivity-tiramisu-internal-sources", ], diff --git a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java index 630f902ecf..577ac54666 100644 --- a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java +++ b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java @@ -48,5 +48,14 @@ public final class ConnectivityFrameworkInitializerTiramisu { return new NsdManager(context, service); } ); + + SystemServiceRegistry.registerContextAwareService( + Context.IPSEC_SERVICE, + IpSecManager.class, + (context, serviceBinder) -> { + IIpSecService service = IIpSecService.Stub.asInterface(serviceBinder); + return new IpSecManager(context, service); + } + ); } } diff --git a/service-t/Sources.bp b/service-t/Sources.bp index d05370f9ba..c3049dabef 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -88,7 +88,6 @@ filegroup { name: "services.connectivity-tiramisu-sources", srcs: [ ":services.connectivity-ethernet-sources", - ":services.connectivity-ipsec-sources", ":services.connectivity-netstats-sources", ], path: "src", @@ -98,6 +97,7 @@ filegroup { filegroup { name: "services.connectivity-tiramisu-updatable-sources", srcs: [ + ":services.connectivity-ipsec-sources", ":services.connectivity-nsd-sources", ], path: "src", diff --git a/service-t/src/com/android/server/IpSecService.java b/service-t/src/com/android/server/IpSecService.java index 179d9459fd..4bc40eae44 100644 --- a/service-t/src/com/android/server/IpSecService.java +++ b/service-t/src/com/android/server/IpSecService.java @@ -1008,16 +1008,10 @@ public class IpSecService extends IIpSecService.Stub { * * @param context Binder context for this service */ - private IpSecService(Context context) { + public IpSecService(Context context) { this(context, new Dependencies()); } - static IpSecService create(Context context) - throws InterruptedException { - final IpSecService service = new IpSecService(context); - return service; - } - @NonNull private AppOpsManager getAppOpsManager() { AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); @@ -1054,26 +1048,6 @@ public class IpSecService extends IIpSecService.Stub { } } - /** Called by system server when system is ready. */ - public void systemReady() { - if (isNetdAlive()) { - Log.d(TAG, "IpSecService is ready"); - } else { - Log.wtf(TAG, "IpSecService not ready: failed to connect to NetD Native Service!"); - } - } - - synchronized boolean isNetdAlive() { - try { - if (mNetd == null) { - return false; - } - return mNetd.isAlive(); - } catch (RemoteException re) { - return false; - } - } - /** * Checks that the provided InetAddress is valid for use in an IPsec SA. The address must not be * a wildcard address and must be in a numeric form such as 1.2.3.4 or 2001::1. @@ -1896,7 +1870,6 @@ public class IpSecService extends IIpSecService.Stub { mContext.enforceCallingOrSelfPermission(DUMP, TAG); pw.println("IpSecService dump:"); - pw.println("NetdNativeService Connection: " + (isNetdAlive() ? "alive" : "dead")); pw.println(); pw.println("mUserResourceTracker:"); From f51dca1070e0bfafe9cc4e2921a7c4838ae3613a Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Sun, 30 Jan 2022 13:09:17 +0000 Subject: [PATCH 825/881] Implement the new added EthernetManager APIs. EthernetManager is moving to the connectivity mainline module and some of its hidden methods are being exposed as module-lib APIs. This CL updates the implementation. 1. Rename onAvailabilityChanged to onInterfaceStateChanged in IEthernetServiceListener.aidl, to match the name of the public callback method. 2. Add the interface state, role and IpConfiguration to the callback, so that clients can use this information without having to call synchronous methods. 3. Call the new callback whenever any of the above parameters changes, or when a callback is registered. Also make some package-private methods in EthernetNetworkFactory protected @VisibleForTesting because otherwise mockito can't mock them. Bug: 210586283 Test: m Test: atest EthernetServiceTests EthernetTetheringTest Change-Id: Ib27bf119b0d61b78f19b6447a38b4468d8035c78 Merged-In: Ib27bf119b0d61b78f19b6447a38b4468d8035c78 --- .../ethernet/EthernetNetworkFactory.java | 16 ++- .../server/ethernet/EthernetServiceImpl.java | 6 +- .../server/ethernet/EthernetTracker.java | 119 +++++++++++++----- 3 files changed, 108 insertions(+), 33 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index a15fec4aba..2823391633 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.ConnectivityManager; +import android.net.EthernetManager; import android.net.EthernetNetworkSpecifier; import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; @@ -186,6 +187,18 @@ public class EthernetNetworkFactory extends NetworkFactory { updateCapabilityFilter(); } + @VisibleForTesting + protected int getInterfaceState(@NonNull String iface) { + final NetworkInterfaceState interfaceState = mTrackingInterfaces.get(iface); + if (interfaceState == null) { + return EthernetManager.STATE_ABSENT; + } else if (!interfaceState.mLinkUp) { + return EthernetManager.STATE_LINK_DOWN; + } else { + return EthernetManager.STATE_LINK_UP; + } + } + /** * Update a network's configuration and restart it if necessary. * @@ -270,7 +283,8 @@ public class EthernetNetworkFactory extends NetworkFactory { return iface.updateLinkState(up, listener); } - boolean hasInterface(String ifaceName) { + @VisibleForTesting + protected boolean hasInterface(String ifaceName) { return mTrackingInterfaces.containsKey(ifaceName); } diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index ffd6d4070e..c1c6d3a60b 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -143,10 +143,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { * Adds a listener. * @param listener A {@link IEthernetServiceListener} to add. */ - public void addListener(IEthernetServiceListener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } + public void addListener(IEthernetServiceListener listener) throws RemoteException { + Objects.requireNonNull(listener, "listener must not be null"); PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); mTracker.addListener(listener, checkUseRestrictedNetworksPermission()); } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 6c8e6d3a97..2571fe66fe 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -23,6 +23,7 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.net.EthernetManager; import android.net.IEthernetServiceListener; import android.net.IEthernetNetworkManagementListener; import android.net.INetd; @@ -165,7 +166,10 @@ public class EthernetTracker { Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration); } writeIpConfiguration(iface, ipConfiguration); - mHandler.post(() -> mFactory.updateInterface(iface, ipConfiguration, null, null)); + mHandler.post(() -> { + mFactory.updateInterface(iface, ipConfiguration, null, null); + broadcastInterfaceStateChange(iface); + }); } private void writeIpConfiguration(@NonNull final String iface, @@ -174,6 +178,55 @@ public class EthernetTracker { mIpConfigurations.put(iface, ipConfig); } + private IpConfiguration getIpConfigurationForCallback(String iface, int state) { + return (state == EthernetManager.STATE_ABSENT) ? null : getOrCreateIpConfiguration(iface); + } + + private void ensureRunningOnEthernetServiceThread() { + if (mHandler.getLooper().getThread() != Thread.currentThread()) { + throw new IllegalStateException( + "Not running on EthernetService thread: " + + Thread.currentThread().getName()); + } + } + + /** + * Broadcast the link state or IpConfiguration change of existing Ethernet interfaces to all + * listeners. + */ + protected void broadcastInterfaceStateChange(@NonNull String iface) { + ensureRunningOnEthernetServiceThread(); + final int state = mFactory.getInterfaceState(iface); + final int role = getInterfaceRole(iface); + final IpConfiguration config = getIpConfigurationForCallback(iface, state); + final int n = mListeners.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mListeners.getBroadcastItem(i).onInterfaceStateChanged(iface, state, role, config); + } catch (RemoteException e) { + // Do nothing here. + } + } + mListeners.finishBroadcast(); + } + + /** + * Unicast the interface state or IpConfiguration change of existing Ethernet interfaces to a + * specific listener. + */ + protected void unicastInterfaceStateChange(@NonNull IEthernetServiceListener listener, + @NonNull String iface) { + ensureRunningOnEthernetServiceThread(); + final int state = mFactory.getInterfaceState(iface); + final int role = getInterfaceRole(iface); + final IpConfiguration config = getIpConfigurationForCallback(iface, state); + try { + listener.onInterfaceStateChanged(iface, state, role, config); + } catch (RemoteException e) { + // Do nothing here. + } + } + @VisibleForTesting(visibility = PACKAGE) protected void updateConfiguration(@NonNull final String iface, @NonNull final StaticIpConfiguration staticIpConfig, @@ -186,8 +239,10 @@ public class EthernetTracker { final IpConfiguration ipConfig = createIpConfiguration(staticIpConfig); writeIpConfiguration(iface, ipConfig); mNetworkCapabilities.put(iface, capabilities); - mHandler.post(() -> - mFactory.updateInterface(iface, ipConfig, capabilities, listener)); + mHandler.post(() -> { + mFactory.updateInterface(iface, ipConfig, capabilities, listener); + broadcastInterfaceStateChange(iface); + }); } @VisibleForTesting(visibility = PACKAGE) @@ -225,11 +280,19 @@ public class EthernetTracker { } void addListener(IEthernetServiceListener listener, boolean canUseRestrictedNetworks) { - mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks)); + mHandler.post(() -> { + if (!mListeners.register(listener, new ListenerInfo(canUseRestrictedNetworks))) { + // Remote process has already died + return; + } + for (String iface : getInterfaces(canUseRestrictedNetworks)) { + unicastInterfaceStateChange(listener, iface); + } + }); } void removeListener(IEthernetServiceListener listener) { - mListeners.unregister(listener); + mHandler.post(() -> mListeners.unregister(listener)); } public void setIncludeTestInterfaces(boolean include) { @@ -295,6 +358,14 @@ public class EthernetTracker { } } + private int getInterfaceRole(final String iface) { + if (!mFactory.hasInterface(iface)) return EthernetManager.ROLE_NONE; + final int mode = getInterfaceMode(iface); + return (mode == INTERFACE_MODE_CLIENT) + ? EthernetManager.ROLE_CLIENT + : EthernetManager.ROLE_SERVER; + } + private int getInterfaceMode(final String iface) { if (iface.equals(mDefaultInterface)) { return mDefaultInterfaceMode; @@ -312,6 +383,7 @@ public class EthernetTracker { if (iface.equals(mDefaultInterface)) { mDefaultInterface = null; } + broadcastInterfaceStateChange(iface); } private void addInterface(String iface) { @@ -346,11 +418,7 @@ public class EthernetTracker { final int mode = getInterfaceMode(iface); if (mode == INTERFACE_MODE_CLIENT) { - IpConfiguration ipConfiguration = mIpConfigurations.get(iface); - if (ipConfiguration == null) { - ipConfiguration = createDefaultIpConfiguration(); - } - + IpConfiguration ipConfiguration = getOrCreateIpConfiguration(iface); Log.d(TAG, "Tracking interface in client mode: " + iface); mFactory.addInterface(iface, hwAddress, ipConfiguration, nc); } else { @@ -376,22 +444,7 @@ public class EthernetTracker { && mFactory.updateInterfaceLinkState(iface, up, listener); if (factoryLinkStateUpdated) { - boolean restricted = isRestrictedInterface(iface); - int n = mListeners.beginBroadcast(); - for (int i = 0; i < n; i++) { - try { - if (restricted) { - ListenerInfo listenerInfo = (ListenerInfo) mListeners.getBroadcastCookie(i); - if (!listenerInfo.canUseRestrictedNetworks) { - continue; - } - } - mListeners.getBroadcastItem(i).onAvailabilityChanged(iface, up); - } catch (RemoteException e) { - // Do nothing here. - } - } - mListeners.finishBroadcast(); + broadcastInterfaceStateChange(iface); } } @@ -438,6 +491,8 @@ public class EthernetTracker { } addInterface(iface); + + broadcastInterfaceStateChange(iface); } private void trackAvailableInterfaces() { @@ -463,11 +518,17 @@ public class EthernetTracker { @Override public void onInterfaceAdded(String iface) { + if (DBG) { + Log.i(TAG, "onInterfaceAdded, iface: " + iface); + } mHandler.post(() -> maybeTrackInterface(iface)); } @Override public void onInterfaceRemoved(String iface) { + if (DBG) { + Log.i(TAG, "onInterfaceRemoved, iface: " + iface); + } mHandler.post(() -> stopTrackingInterface(iface)); } } @@ -663,8 +724,10 @@ public class EthernetTracker { return ret; } - private static IpConfiguration createDefaultIpConfiguration() { - final IpConfiguration ret = new IpConfiguration(); + private IpConfiguration getOrCreateIpConfiguration(String iface) { + IpConfiguration ret = mIpConfigurations.get(iface); + if (ret != null) return ret; + ret = new IpConfiguration(); ret.setIpAssignment(IpAssignment.DHCP); ret.setProxySettings(ProxySettings.NONE); return ret; From ca0be94009194dbcae8023d7ac738501aedd5037 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Thu, 3 Feb 2022 19:09:36 -0800 Subject: [PATCH 826/881] Making EthernetNetworkSpecifier public Bug: 210485380 Test: atest EthernetServiceTests atest CtsNetTestCasesLatestSdk Change-Id: Ic0b7a3360745632eb024a97692e49f6c8dafa3ee Merged-In: Ic0b7a3360745632eb024a97692e49f6c8dafa3ee --- framework-t/src/android/net/EthernetNetworkSpecifier.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/framework-t/src/android/net/EthernetNetworkSpecifier.java b/framework-t/src/android/net/EthernetNetworkSpecifier.java index 925d12b574..e4d6e248d4 100644 --- a/framework-t/src/android/net/EthernetNetworkSpecifier.java +++ b/framework-t/src/android/net/EthernetNetworkSpecifier.java @@ -18,7 +18,6 @@ package android.net; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -29,9 +28,7 @@ import java.util.Objects; * A {@link NetworkSpecifier} used to identify ethernet interfaces. * * @see EthernetManager - * @hide */ -@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public final class EthernetNetworkSpecifier extends NetworkSpecifier implements Parcelable { /** @@ -61,6 +58,7 @@ public final class EthernetNetworkSpecifier extends NetworkSpecifier implements return mInterfaceName; } + /** @hide */ @Override public boolean canBeSatisfiedBy(@Nullable NetworkSpecifier other) { return equals(other); From 336d3c71b398b27267c2ce41ea952b9f04efc7dc Mon Sep 17 00:00:00 2001 From: markchien Date: Fri, 11 Feb 2022 14:08:02 +0800 Subject: [PATCH 827/881] Replace qtaguid_deleteTagData with java implementation Copies the behavior of TrafficController::deleteTagData. Test: atest NetworkStatsServiceTest Change-Id: I436ce514108486db712b455f1b5fd8dca345c65c --- .../server/net/NetworkStatsService.java | 132 ++++++++++++++++-- ...android_server_net_NetworkStatsService.cpp | 5 - 2 files changed, 117 insertions(+), 20 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 9f3371b724..eeb56d05e7 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -51,6 +51,7 @@ import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID; import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG; import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT; import static android.os.Trace.TRACE_TAG_NETWORK; +import static android.system.OsConstants.ENOENT; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; @@ -120,7 +121,6 @@ import android.provider.Settings.Global; import android.service.NetworkInterfaceProto; import android.service.NetworkStatsServiceDumpProto; import android.system.ErrnoException; -import android.system.Os; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionPlan; import android.text.TextUtils; @@ -214,6 +214,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // This is current path but may be changed soon. private static final String UID_COUNTERSET_MAP_PATH = "/sys/fs/bpf/map_netd_uid_counterset_map"; + private static final String COOKIE_TAG_MAP_PATH = + "/sys/fs/bpf/map_netd_cookie_tag_map"; + private static final String APP_UID_STATS_MAP_PATH = + "/sys/fs/bpf/map_netd_app_uid_stats_map"; + private static final String STATS_MAP_A_PATH = + "/sys/fs/bpf/map_netd_stats_map_A"; + private static final String STATS_MAP_B_PATH = + "/sys/fs/bpf/map_netd_stats_map_B"; private final Context mContext; private final NetworkStatsFactory mStatsFactory; @@ -341,6 +349,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ private SparseIntArray mActiveUidCounterSet = new SparseIntArray(); private final IBpfMap mUidCounterSetMap; + private final IBpfMap mCookieTagMap; + private final IBpfMap mStatsMapA; + private final IBpfMap mStatsMapB; + private final IBpfMap mAppUidStatsMap; /** Data layer operation counters for splicing into other structures. */ private NetworkStats mUidOperations = new NetworkStats(0L, 10); @@ -474,6 +486,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler); mInterfaceMapUpdater.start(); mUidCounterSetMap = mDeps.getUidCounterSetMap(); + mCookieTagMap = mDeps.getCookieTagMap(); + mStatsMapA = mDeps.getStatsMapA(); + mStatsMapB = mDeps.getStatsMapB(); + mAppUidStatsMap = mDeps.getAppUidStatsMap(); } /** @@ -547,8 +563,48 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - public TagStatsDeleter getTagStatsDeleter() { - return NetworkStatsService::nativeDeleteTagData; + /** Gets the cookie tag map */ + public IBpfMap getCookieTagMap() { + try { + return new BpfMap(COOKIE_TAG_MAP_PATH, + BpfMap.BPF_F_RDWR, CookieTagMapKey.class, CookieTagMapValue.class); + } catch (ErrnoException e) { + Log.wtf(TAG, "Cannot create cookie tag map: " + e); + return null; + } + } + + /** Gets stats map A */ + public IBpfMap getStatsMapA() { + try { + return new BpfMap(STATS_MAP_A_PATH, + BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class); + } catch (ErrnoException e) { + Log.wtf(TAG, "Cannot create stats map A: " + e); + return null; + } + } + + /** Gets stats map B */ + public IBpfMap getStatsMapB() { + try { + return new BpfMap(STATS_MAP_B_PATH, + BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class); + } catch (ErrnoException e) { + Log.wtf(TAG, "Cannot create stats map B: " + e); + return null; + } + } + + /** Gets the uid stats map */ + public IBpfMap getAppUidStatsMap() { + try { + return new BpfMap(APP_UID_STATS_MAP_PATH, + BpfMap.BPF_F_RDWR, UidStatsMapKey.class, StatsMapValue.class); + } catch (ErrnoException e) { + Log.wtf(TAG, "Cannot create app uid stats map: " + e); + return null; + } } } @@ -1790,6 +1846,63 @@ public class NetworkStatsService extends INetworkStatsService.Stub { currentTime); } + // deleteKernelTagData can ignore ENOENT; otherwise we should log an error + private void logErrorIfNotErrNoent(final ErrnoException e, final String msg) { + if (e.errno != ENOENT) Log.e(TAG, msg, e); + } + + private void deleteStatsMapTagData( + IBpfMap statsMap, int uid) { + try { + statsMap.forEach((key, value) -> { + if (key.uid == uid) { + try { + statsMap.deleteEntry(key); + } catch (ErrnoException e) { + logErrorIfNotErrNoent(e, "Failed to delete data(uid = " + key.uid + ")"); + } + } + }); + } catch (ErrnoException e) { + Log.e(TAG, "FAILED to delete tag data from stats map", e); + } + } + + /** + * Deletes uid tag data from CookieTagMap, StatsMapA, StatsMapB, and UidStatsMap + * @param uid + */ + private void deleteKernelTagData(int uid) { + try { + mCookieTagMap.forEach((key, value) -> { + if (value.uid == uid) { + try { + mCookieTagMap.deleteEntry(key); + } catch (ErrnoException e) { + logErrorIfNotErrNoent(e, "Failed to delete data(cookie = " + key + ")"); + } + } + }); + } catch (ErrnoException e) { + Log.e(TAG, "Failed to delete tag data from cookie tag map", e); + } + + deleteStatsMapTagData(mStatsMapA, uid); + deleteStatsMapTagData(mStatsMapB, uid); + + try { + mUidCounterSetMap.deleteEntry(new U32(uid)); + } catch (ErrnoException e) { + logErrorIfNotErrNoent(e, "Failed to delete tag data from uid counter set map"); + } + + try { + mAppUidStatsMap.deleteEntry(new UidStatsMapKey(uid)); + } catch (ErrnoException e) { + logErrorIfNotErrNoent(e, "Failed to delete tag data from app uid stats map"); + } + } + /** * Clean up {@link #mUidRecorder} after UID is removed. */ @@ -1805,10 +1918,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Clear kernel stats associated with UID for (int uid : uids) { - final int ret = mDeps.getTagStatsDeleter().deleteTagData(uid); - if (ret < 0) { - Log.w(TAG, "problem clearing counters for uid " + uid + ": " + Os.strerror(-ret)); - } + deleteKernelTagData(uid); } } @@ -2387,12 +2497,4 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static native long nativeGetTotalStat(int type); private static native long nativeGetIfaceStat(String iface, int type); private static native long nativeGetUidStat(int uid, int type); - - // TODO: use BpfNetMaps to delete tag data and remove this. - @VisibleForTesting - interface TagStatsDeleter { - int deleteTagData(int uid); - } - - private static native int nativeDeleteTagData(int uid); } diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp index f8a81682bd..39cbaf716f 100644 --- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp +++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp @@ -102,15 +102,10 @@ static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) { } } -static int deleteTagData(JNIEnv* /* env */, jclass /* clazz */, jint uid) { - return qtaguid_deleteTagData(0, uid); -} - static const JNINativeMethod gMethods[] = { {"nativeGetTotalStat", "(I)J", (void*)getTotalStat}, {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat}, {"nativeGetUidStat", "(II)J", (void*)getUidStat}, - {"nativeDeleteTagData", "(I)I", (void*)deleteTagData}, }; int register_android_server_net_NetworkStatsService(JNIEnv* env) { From 11170dd9ef00ec57b85772494be1dd1c75b24f1a Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Sun, 30 Jan 2022 11:27:16 +0000 Subject: [PATCH 828/881] Expose EthernetManager state and control APIs. This CL exposes EthernetManager APIs that settings and other system components can use to modify and monitor Ethernet state. The new APIs are similar to the existing @hide methods but pass on more information and meet API guidelines: 1. Add an InterfaceStateListener interface, and addInterfaceStateListener and removeInterfaceStateListener methods that meet API guidelines (e.g., take Executor, take SAM parameter last, etc.) This new listener passes interface state (absent, up, down), role (client or server) and IP configuration. 2. Implement the legacy Listener type as a subinterface of the new interface. Hopefully existing callers should be able to use it unchanged. 3. Expose setIncludeTestInterfaces as module-lib api instead of TestApi, since modules cannot expose TestApi methods. Bug: 210586283 Test: m Test: atest EthernetServiceTests Test: atest EthernetTetheringTest Change-Id: I88240a546ab51d128ed83775499f2bcabab74db0 Merged-In: I88240a546ab51d128ed83775499f2bcabab74db0 --- .../src/android/net/EthernetManager.java | 158 ++++++++++++++++-- .../android/net/IEthernetServiceListener.aidl | 5 +- 2 files changed, 144 insertions(+), 19 deletions(-) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 1f67f6d654..1a955c4c57 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -16,14 +16,16 @@ package android.net; +import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; + import android.annotation.CallbackExecutor; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; -import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; @@ -33,13 +35,15 @@ import android.os.RemoteException; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BackgroundThread; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.BiConsumer; /** - * A class representing the IP configuration of the Ethernet network. + * A class that manages and configures Ethernet interfaces. * * @hide */ @@ -54,11 +58,13 @@ public class EthernetManager { private final IEthernetServiceListener.Stub mServiceListener = new IEthernetServiceListener.Stub() { @Override - public void onAvailabilityChanged(String iface, boolean isAvailable) { + public void onInterfaceStateChanged(String iface, int state, int role, + IpConfiguration configuration) { synchronized (mListeners) { for (ListenerInfo li : mListeners) { li.executor.execute(() -> - li.listener.onAvailabilityChanged(iface, isAvailable)); + li.listener.onInterfaceStateChanged(iface, state, role, + configuration)); } } } @@ -68,19 +74,93 @@ public class EthernetManager { @NonNull public final Executor executor; @NonNull - public final Listener listener; + public final InterfaceStateListener listener; - private ListenerInfo(@NonNull Executor executor, @NonNull Listener listener) { + private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) { this.executor = executor; this.listener = listener; } } /** - * A listener interface to receive notification on changes in Ethernet. + * The interface is absent. * @hide */ - public interface Listener { + @SystemApi(client = MODULE_LIBRARIES) + public static final int STATE_ABSENT = 0; + + /** + * The interface is present but link is down. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int STATE_LINK_DOWN = 1; + + /** + * The interface is present and link is up. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int STATE_LINK_UP = 2; + + /** @hide */ + @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP}) + @Retention(RetentionPolicy.SOURCE) + public @interface InterfaceState {} + + /** + * The interface currently does not have any specific role. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int ROLE_NONE = 0; + + /** + * The interface is in client mode (e.g., connected to the Internet). + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int ROLE_CLIENT = 1; + + /** + * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices). + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int ROLE_SERVER = 2; + + /** @hide */ + @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER}) + @Retention(RetentionPolicy.SOURCE) + public @interface Role {} + + /** + * A listener that receives notifications about the state of Ethernet interfaces on the system. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public interface InterfaceStateListener { + /** + * Called when an Ethernet interface changes state. + * + * @param iface the name of the interface. + * @param state the current state of the interface, or {@link #STATE_ABSENT} if the + * interface was removed. + * @param role whether the interface is in the client mode or server mode. + * @param configuration the current IP configuration of the interface. + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state, + @Role int role, @Nullable IpConfiguration configuration); + } + + /** + * A listener interface to receive notification on changes in Ethernet. + * This has never been a supported API. Use {@link InterfaceStateListener} instead. + * @hide + */ + public interface Listener extends InterfaceStateListener { /** * Called when Ethernet port's availability is changed. * @param iface Ethernet interface name @@ -89,6 +169,13 @@ public class EthernetManager { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void onAvailabilityChanged(String iface, boolean isAvailable); + + /** Default implementation for backwards compatibility. Only calls the legacy listener. */ + default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state, + @Role int role, @Nullable IpConfiguration configuration) { + onAvailabilityChanged(iface, (state >= STATE_LINK_UP)); + } + } /** @@ -121,7 +208,7 @@ public class EthernetManager { * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void setConfiguration(String iface, IpConfiguration config) { + public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) { try { mService.setConfiguration(iface, config); } catch (RemoteException e) { @@ -155,9 +242,8 @@ public class EthernetManager { /** * Adds a listener. + * This has never been a supported API. Use {@link #addInterfaceStateListener} instead. * - * Consider using {@link #addListener(Listener, Executor)} instead: this method uses a default - * executor that may have higher latency than a provided executor. * @param listener A {@link Listener} to add. * @throws IllegalArgumentException If the listener is null. * @hide @@ -169,6 +255,8 @@ public class EthernetManager { /** * Adds a listener. + * This has never been a supported API. Use {@link #addInterfaceStateListener} instead. + * * @param listener A {@link Listener} to add. * @param executor Executor to run callbacks on. * @throws IllegalArgumentException If the listener or executor is null. @@ -176,6 +264,28 @@ public class EthernetManager { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public void addListener(@NonNull Listener listener, @NonNull Executor executor) { + addInterfaceStateListener(executor, listener); + } + + /** + * Listen to changes in the state of Ethernet interfaces. + * + * Adds a listener to receive notification for any state change of all existing Ethernet + * interfaces. + *

{@link Listener#onInterfaceStateChanged} will be triggered immediately for all + * existing interfaces upon adding a listener. The same method will be called on the + * listener every time any of the interface changes state. In particular, if an + * interface is removed, it will be called with state {@link #STATE_ABSENT}. + *

Use {@link #removeInterfaceStateListener} with the same object to stop listening. + * + * @param executor Executor to run callbacks on. + * @param listener A {@link Listener} to add. + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @SystemApi(client = MODULE_LIBRARIES) + public void addInterfaceStateListener(@NonNull Executor executor, + @NonNull InterfaceStateListener listener) { if (listener == null || executor == null) { throw new NullPointerException("listener and executor must not be null"); } @@ -206,15 +316,13 @@ public class EthernetManager { /** * Removes a listener. + * * @param listener A {@link Listener} to remove. - * @throws IllegalArgumentException If the listener is null. * @hide */ - @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public void removeListener(@NonNull Listener listener) { - if (listener == null) { - throw new IllegalArgumentException("listener must not be null"); - } + @SystemApi(client = MODULE_LIBRARIES) + public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) { + Objects.requireNonNull(listener); synchronized (mListeners) { mListeners.removeIf(l -> l.listener == listener); if (mListeners.isEmpty()) { @@ -227,13 +335,27 @@ public class EthernetManager { } } + /** + * Removes a listener. + * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead. + * @param listener A {@link Listener} to remove. + * @hide + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) + public void removeListener(@NonNull Listener listener) { + if (listener == null) { + throw new IllegalArgumentException("listener must not be null"); + } + removeInterfaceStateListener(listener); + } + /** * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface} * as Ethernet interfaces. The effects of this method apply to any test interfaces that are * already present on the system. * @hide */ - @TestApi + @SystemApi(client = MODULE_LIBRARIES) public void setIncludeTestInterfaces(boolean include) { try { mService.setIncludeTestInterfaces(include); diff --git a/framework-t/src/android/net/IEthernetServiceListener.aidl b/framework-t/src/android/net/IEthernetServiceListener.aidl index 782fa19d9d..6d2ba03f78 100644 --- a/framework-t/src/android/net/IEthernetServiceListener.aidl +++ b/framework-t/src/android/net/IEthernetServiceListener.aidl @@ -16,8 +16,11 @@ package android.net; +import android.net.IpConfiguration; + /** @hide */ oneway interface IEthernetServiceListener { - void onAvailabilityChanged(String iface, boolean isAvailable); + void onInterfaceStateChanged(String iface, int state, int role, + in IpConfiguration configuration); } From c54e4f397bef2adcd7e71d91760cb558d4bbd27b Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 11 Feb 2022 12:18:59 +0900 Subject: [PATCH 829/881] Fix grammar nit in comment. Test: None Change-Id: I60cb2478615efce13f1904092abe5c21bdf0dc9a --- framework-t/src/android/net/EthernetManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 1a955c4c57..72243f9e87 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -146,7 +146,7 @@ public class EthernetManager { * @param iface the name of the interface. * @param state the current state of the interface, or {@link #STATE_ABSENT} if the * interface was removed. - * @param role whether the interface is in the client mode or server mode. + * @param role whether the interface is in client mode or server mode. * @param configuration the current IP configuration of the interface. * @hide */ From 01a87ca336f5a47c462fdbba696106c9e8d5a97e Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Mon, 17 Jan 2022 17:37:19 +0000 Subject: [PATCH 830/881] [MS62.1] Start NetworkStatsService from the module NetworkStatsService is going to be moved into Connectivity mainlne module and it will be not visible to SystemServiceResistry after migration done. Thus: 1. Register service in NetworkStatsServiceInitialalizer, a separate initializer is needed because the service needs to be created before NetworkPolicyManagerService's initialization. 2. Call SystemReady at PHASE_ACTIVITY_MANAGER_READY phase where it needs to be ready before StatsPullAtomService pulls at PHASE_THIRD_PARTY_APPS_CAN_START. 3. Register manager in ConnectivityFrameworkInitializerTiramisu instead of SystemServiceRegistery. Test: atest FrameworksNetTests CtsNetTestCases NetworkUsageStatsTest Bug: 204830222 (cherry-picked from ag/16688794) Change-Id: I95020d816ed613ce3480a0720a5b71dcdc7fab72 Merged-In: I95020d816ed613ce3480a0720a5b71dcdc7fab72 --- .../net/ConnectivityFrameworkInitializerTiramisu.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java index 577ac54666..9bffbfb27a 100644 --- a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java +++ b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java @@ -18,6 +18,7 @@ package android.net; import android.annotation.SystemApi; import android.app.SystemServiceRegistry; +import android.app.usage.NetworkStatsManager; import android.content.Context; import android.net.nsd.INsdManager; import android.net.nsd.NsdManager; @@ -57,5 +58,15 @@ public final class ConnectivityFrameworkInitializerTiramisu { return new IpSecManager(context, service); } ); + + SystemServiceRegistry.registerContextAwareService( + Context.NETWORK_STATS_SERVICE, + NetworkStatsManager.class, + (context, serviceBinder) -> { + INetworkStatsService service = + INetworkStatsService.Stub.asInterface(serviceBinder); + return new NetworkStatsManager(context, service); + } + ); } } From 63627bce56e929cd515714741622a30c1a94ba71 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 26 Jan 2022 09:00:41 +0000 Subject: [PATCH 831/881] [MS54.1] Move NetworkStats to updatable sources This CL builds NetworkStats related code with the connectivity module instead of platform. This includes: 1. Add netstats.proto to the module. 2. Add lib dependencies for all callers. 3. Include several source files in platform and add jarjar rule to it. Modify callers accordingly. Test: TH Bug: 197717846 Change-Id: I244693aebe1782d9e67502638ff8145c51462e1e Merged-In: I244693aebe1782d9e67502638ff8145c51462e1e --- framework-t/Sources.bp | 4 +--- .../src/android/net/NetworkIdentity.java | 10 ++++----- .../src/android/net/NetworkIdentitySet.java | 2 +- .../android/net/NetworkStatsCollection.java | 14 ++++++------ .../src/android/net/NetworkStatsHistory.java | 17 +++++++------- service-t/Sources.bp | 2 +- .../server/net/NetworkStatsRecorder.java | 6 +++-- .../server/net/NetworkStatsService.java | 22 ++++++++++++------- .../net/NetworkStatsSubscriptionsMonitor.java | 3 +++ 9 files changed, 45 insertions(+), 35 deletions(-) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 6329565ca5..b30e54d20b 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -158,7 +158,6 @@ filegroup { name: "framework-connectivity-tiramisu-sources", srcs: [ ":framework-connectivity-ethernet-sources", - ":framework-connectivity-netstats-sources", ], visibility: ["//frameworks/base"], } @@ -167,6 +166,7 @@ filegroup { name: "framework-connectivity-tiramisu-updatable-sources", srcs: [ ":framework-connectivity-ipsec-sources", + ":framework-connectivity-netstats-sources", ":framework-connectivity-nsd-sources", ":framework-connectivity-tiramisu-internal-sources", ], @@ -202,7 +202,5 @@ cc_library_shared { stl: "none", apex_available: [ "com.android.tethering", - // TODO: remove when ConnectivityT moves to APEX. - "//apex_available:platform", ], } diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 56faa52e82..4ebaf2b8cd 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -184,14 +184,14 @@ public class NetworkIdentity { public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); - proto.write(NetworkIdentityProto.TYPE, mType); + proto.write(NetworkIdentityProto.TYPE_FIELD_NUMBER, mType); // TODO: dump mRatType as well. - proto.write(NetworkIdentityProto.ROAMING, mRoaming); - proto.write(NetworkIdentityProto.METERED, mMetered); - proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork); - proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged); + proto.write(NetworkIdentityProto.ROAMING_FIELD_NUMBER, mRoaming); + proto.write(NetworkIdentityProto.METERED_FIELD_NUMBER, mMetered); + proto.write(NetworkIdentityProto.DEFAULT_NETWORK_FIELD_NUMBER, mDefaultNetwork); + proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK_FIELD_NUMBER, mOemManaged); proto.end(start); } diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java index dfa347f6f1..2236d70c35 100644 --- a/framework-t/src/android/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -212,7 +212,7 @@ public class NetworkIdentitySet extends HashSet { final long start = proto.start(tag); for (NetworkIdentity ident : this) { - ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES); + ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES_FIELD_NUMBER); } proto.end(start); diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 735c44d5c8..67d48f0000 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -732,19 +732,19 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W final long start = proto.start(tag); for (Key key : getSortedKeys()) { - final long startStats = proto.start(NetworkStatsCollectionProto.STATS); + final long startStats = proto.start(NetworkStatsCollectionProto.STATS_FIELD_NUMBER); // Key - final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY); - key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY); - proto.write(NetworkStatsCollectionKeyProto.UID, key.uid); - proto.write(NetworkStatsCollectionKeyProto.SET, key.set); - proto.write(NetworkStatsCollectionKeyProto.TAG, key.tag); + final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY_FIELD_NUMBER); + key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY_FIELD_NUMBER); + proto.write(NetworkStatsCollectionKeyProto.UID_FIELD_NUMBER, key.uid); + proto.write(NetworkStatsCollectionKeyProto.SET_FIELD_NUMBER, key.set); + proto.write(NetworkStatsCollectionKeyProto.TAG_FIELD_NUMBER, key.tag); proto.end(startKey); // Value final NetworkStatsHistory history = mStats.get(key); - history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY); + history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY_FIELD_NUMBER); proto.end(startStats); } diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java index 78c137073a..822a16e0bb 100644 --- a/framework-t/src/android/net/NetworkStatsHistory.java +++ b/framework-t/src/android/net/NetworkStatsHistory.java @@ -915,17 +915,18 @@ public final class NetworkStatsHistory implements Parcelable { public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); - proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration); + proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS_FIELD_NUMBER, bucketDuration); for (int i = 0; i < bucketCount; i++) { - final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS); + final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS_FIELD_NUMBER); - proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS, bucketStart[i]); - dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i); + proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS_FIELD_NUMBER, + bucketStart[i]); + dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES_FIELD_NUMBER, rxBytes, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS_FIELD_NUMBER, rxPackets, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES_FIELD_NUMBER, txBytes, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS_FIELD_NUMBER, txPackets, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS_FIELD_NUMBER, operations, i); proto.end(startBucket); } diff --git a/service-t/Sources.bp b/service-t/Sources.bp index c3049dabef..502c56a7fb 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -88,7 +88,6 @@ filegroup { name: "services.connectivity-tiramisu-sources", srcs: [ ":services.connectivity-ethernet-sources", - ":services.connectivity-netstats-sources", ], path: "src", visibility: ["//frameworks/base/services/core"], @@ -98,6 +97,7 @@ filegroup { name: "services.connectivity-tiramisu-updatable-sources", srcs: [ ":services.connectivity-ipsec-sources", + ":services.connectivity-netstats-sources", ":services.connectivity-nsd-sources", ], path: "src", diff --git a/service-t/src/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java index c371f0859a..a006cd5975 100644 --- a/service-t/src/com/android/server/net/NetworkStatsRecorder.java +++ b/service-t/src/com/android/server/net/NetworkStatsRecorder.java @@ -471,9 +471,11 @@ public class NetworkStatsRecorder { public void dumpDebugLocked(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); if (mPending != null) { - proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES, mPending.getTotalBytes()); + proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES_FIELD_NUMBER, + mPending.getTotalBytes()); } - getOrLoadCompleteLocked().dumpDebug(proto, NetworkStatsRecorderProto.COMPLETE_HISTORY); + getOrLoadCompleteLocked().dumpDebug(proto, + NetworkStatsRecorderProto.COMPLETE_HISTORY_FIELD_NUMBER); proto.end(start); } diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index eeb56d05e7..c441c81602 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -63,6 +63,7 @@ import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.usage.NetworkStatsManager; @@ -103,6 +104,7 @@ import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; +import android.os.Build; import android.os.DropBoxManager; import android.os.Environment; import android.os.Handler; @@ -169,6 +171,7 @@ import java.util.concurrent.TimeUnit; * Collect and persist detailed network statistics, and provide this data to * other system services. */ +@TargetApi(Build.VERSION_CODES.TIRAMISU) public class NetworkStatsService extends INetworkStatsService.Stub { static final String TAG = "NetworkStats"; static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); @@ -2114,12 +2117,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // TODO Right now it writes all history. Should it limit to the "since-boot" log? - dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces); - dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces); - mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS); - mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS); - mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS); - mUidTagRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS); + dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES_FIELD_NUMBER, + mActiveIfaces); + dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES_FIELD_NUMBER, + mActiveUidIfaces); + mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS_FIELD_NUMBER); + mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS_FIELD_NUMBER); + mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS_FIELD_NUMBER); + mUidTagRecorder.dumpDebugLocked(proto, + NetworkStatsServiceDumpProto.UID_TAG_STATS_FIELD_NUMBER); proto.flush(); } @@ -2129,8 +2135,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { for (int i = 0; i < ifaces.size(); i++) { final long start = proto.start(tag); - proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i)); - ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES); + proto.write(NetworkInterfaceProto.INTERFACE_FIELD_NUMBER, ifaces.keyAt(i)); + ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES_FIELD_NUMBER); proto.end(start); } diff --git a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java index 5bba0b17aa..65ccd20072 100644 --- a/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java +++ b/service-t/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -23,7 +23,9 @@ import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NS import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; import android.annotation.NonNull; +import android.annotation.TargetApi; import android.content.Context; +import android.os.Build; import android.telephony.SubscriptionManager; import android.telephony.TelephonyCallback; import android.telephony.TelephonyDisplayInfo; @@ -43,6 +45,7 @@ import java.util.concurrent.Executor; /** * Helper class that watches for events that are triggered per subscription. */ +@TargetApi(Build.VERSION_CODES.TIRAMISU) public class NetworkStatsSubscriptionsMonitor extends SubscriptionManager.OnSubscriptionsChangedListener { From 63d42a25bb0f234afe8d596170cbf7eda601e1bc Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 2 Feb 2022 13:22:57 +0900 Subject: [PATCH 832/881] Move networkstats JNI to connectivity module Reorganize networkstats JNI so it can be included in the connectivity module. Bug: 197717846 Test: m Change-Id: I815ea379f3d9915041c80ac5e743ce62e05f4cf8 Merged-In: I815ea379f3d9915041c80ac5e743ce62e05f4cf8 --- framework-t/Sources.bp | 5 ++-- service-t/Sources.bp | 24 +++++++++++++++++++ ...android_server_net_NetworkStatsFactory.cpp | 0 ...android_server_net_NetworkStatsService.cpp | 0 .../server/net/NetworkStatsFactory.java | 4 ++++ .../server/net/NetworkStatsService.java | 4 ++++ 6 files changed, 34 insertions(+), 3 deletions(-) rename {services/core => service-t}/jni/com_android_server_net_NetworkStatsFactory.cpp (100%) rename {services/core => service-t}/jni/com_android_server_net_NetworkStatsService.cpp (100%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index b30e54d20b..66527802a0 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -194,10 +194,9 @@ cc_library_shared { "jni/onload.cpp", ], shared_libs: [ + "libandroid", "liblog", - ], - static_libs: [ - "libnativehelper_compat_libc++", + "libnativehelper", ], stl: "none", apex_available: [ diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 502c56a7fb..5100e7c5b9 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -40,6 +40,30 @@ filegroup { ], } +// For test code only. +filegroup { + name: "lib_networkStatsFactory_native", + srcs: [ + "jni/com_android_server_net_NetworkStatsFactory.cpp", + ], + path: "jni", + visibility: [ + "//packages/modules/Connectivity:__subpackages__", + ], +} + +filegroup { + name: "services.connectivity-netstats-jni-sources", + srcs: [ + "jni/com_android_server_net_NetworkStatsFactory.cpp", + "jni/com_android_server_net_NetworkStatsService.cpp", + ], + path: "jni", + visibility: [ + "//packages/modules/Connectivity:__subpackages__", + ], +} + // Nsd related libraries. filegroup { diff --git a/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp b/service-t/jni/com_android_server_net_NetworkStatsFactory.cpp similarity index 100% rename from services/core/jni/com_android_server_net_NetworkStatsFactory.cpp rename to service-t/jni/com_android_server_net_NetworkStatsFactory.cpp diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/service-t/jni/com_android_server_net_NetworkStatsService.cpp similarity index 100% rename from services/core/jni/com_android_server_net_NetworkStatsService.cpp rename to service-t/jni/com_android_server_net_NetworkStatsService.cpp diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java index 668d1cba92..151c90dd41 100644 --- a/service-t/src/com/android/server/net/NetworkStatsFactory.java +++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java @@ -54,6 +54,10 @@ import java.util.concurrent.ConcurrentHashMap; * @hide */ public class NetworkStatsFactory { + static { + System.loadLibrary("service-connectivity"); + } + private static final String TAG = "NetworkStatsFactory"; private static final boolean USE_NATIVE_PARSING = true; diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index c441c81602..3e4687f9d2 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -173,6 +173,10 @@ import java.util.concurrent.TimeUnit; */ @TargetApi(Build.VERSION_CODES.TIRAMISU) public class NetworkStatsService extends INetworkStatsService.Stub { + static { + System.loadLibrary("service-connectivity"); + } + static final String TAG = "NetworkStats"; static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE); From c99a128f510cdbb2ccf44187313f356bfef5a476 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Thu, 3 Feb 2022 11:34:52 +0900 Subject: [PATCH 833/881] Add setPollForce to module API The API was test API in S, but this is not supported in module API surfaces. Make it module API instead. Bug: 197717846 Test: Tests already using this API (cherry-picked from ag/16780943) Change-Id: I9d44b761572f94b08b269478c4a0c20c1171343c Merged-In: I9d44b761572f94b08b269478c4a0c20c1171343c --- .../src/android/app/usage/NetworkStatsManager.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 5ce7e59b38..0414bb79f8 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -27,7 +27,6 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; -import android.annotation.TestApi; import android.annotation.WorkerThread; import android.app.usage.NetworkStats.Bucket; import android.compat.annotation.UnsupportedAppUsage; @@ -192,9 +191,13 @@ public class NetworkStatsManager { } } - /** @hide */ + /** + * Set poll force flag to indicate that calling any subsequent query method will force a stats + * poll. + * @hide + */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @TestApi + @SystemApi(client = MODULE_LIBRARIES) public void setPollForce(boolean pollForce) { if (pollForce) { mFlags |= FLAG_POLL_FORCE; From fe5ed721bea0543525742b66f4d29f0d2d01d7f5 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 4 Feb 2022 03:05:59 +0900 Subject: [PATCH 834/881] Expose MATCH_PROXY as a module-lib API. It is used by clockwork. Test: m update-api (cherry-picked from ag/16786203) Change-Id: I5676f883141afca1511c425b7c36683a6c6bfb9f Merged-In: I5676f883141afca1511c425b7c36683a6c6bfb9f --- framework-t/src/android/net/NetworkTemplate.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/framework-t/src/android/net/NetworkTemplate.java b/framework-t/src/android/net/NetworkTemplate.java index 9b58b016bb..7b5afd7200 100644 --- a/framework-t/src/android/net/NetworkTemplate.java +++ b/framework-t/src/android/net/NetworkTemplate.java @@ -79,7 +79,8 @@ public final class NetworkTemplate implements Parcelable { MATCH_WIFI, MATCH_ETHERNET, MATCH_BLUETOOTH, - MATCH_CARRIER + MATCH_PROXY, + MATCH_CARRIER, }) public @interface TemplateMatchRule{} @@ -104,9 +105,8 @@ public final class NetworkTemplate implements Parcelable { /** Match rule to match bluetooth networks. */ public static final int MATCH_BLUETOOTH = 8; /** - * Match rule to match networks with {@link Connectivity#TYPE_PROXY} as the legacy network type. - * - * @hide + * Match rule to match networks with {@link ConnectivityManager#TYPE_PROXY} as the legacy + * network type. */ public static final int MATCH_PROXY = 9; /** From 2616b49c709b2e4aca5b20fb59f571b6fd987d03 Mon Sep 17 00:00:00 2001 From: markchien Date: Fri, 18 Feb 2022 12:48:02 +0800 Subject: [PATCH 835/881] Fix system_server crash while iterating CookieTagMap When uid is removed, NetworkStatsService will iterate CookieTagMap and delete the corresponded uid socketTag value. But not only NetworkStatsService would detete CookieTagMap entries. There are other threads may also delete CookieTagMap entries such as #unTagSocket in bpfHandler and desctroy socket listener in TrafficController. System server crash as NPE because the CookieTagMap entry it iterate just be removed by other threads at the same time. This is just a simple fix to prevent the crash. Will have follow up CL for formal fix. Bug: 220084230 Test: m Change-Id: I08cad87f537fb09499faf1ff5cfd443fcb8ce436 --- .../src/com/android/server/net/NetworkStatsService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index eeb56d05e7..b193623114 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1875,7 +1875,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void deleteKernelTagData(int uid) { try { mCookieTagMap.forEach((key, value) -> { - if (value.uid == uid) { + // If SkDestroyListener deletes the socket tag while this code is running, + // forEach will either restart iteration from the beginning or return null, + // depending on when the deletion happens. + // If it returns null, continue iteration to delete the data and in fact it would + // just iterate from first key because BpfMap#getNextKey would return first key + // if the current key is not exist. + if (value != null && value.uid == uid) { try { mCookieTagMap.deleteEntry(key); } catch (ErrnoException e) { From 07b13f5e3abac1a9560590115e916542ddd3911b Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Mon, 21 Feb 2022 16:24:45 +0100 Subject: [PATCH 836/881] Fix testIpClientIsNotStartedWhenLinkIsDown This test is breaking when requesting a network with an EthernetNetworkSpecifier after aosp/1795391 was submitted (which fixed another bug that hid this one). Test: atest EthernetNetworkFactoryTest Change-Id: I31f10f48cd03cdef29f21bbce790db68add071a8 --- .../server/ethernet/EthernetNetworkFactoryTest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 6cb13efecf..33831a56d5 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -31,6 +31,7 @@ import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -455,16 +456,21 @@ public class EthernetNetworkFactoryTest { mNetFactory.needNetworkFor(createDefaultRequest()); + verify(mDeps, never()).makeIpClient(any(), any(), any()); + + // BUG(b/191854824): requesting a network with a specifier (Android Auto use case) should + // not start an IpClient when the link is down, but fixing this may make matters worse by + // tiggering b/197548738. NetworkRequest specificNetRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) .setNetworkSpecifier(new EthernetNetworkSpecifier(TEST_IFACE)) .build(); mNetFactory.needNetworkFor(specificNetRequest); - - verify(mDeps, never()).makeIpClient(any(), any(), any()); + mNetFactory.releaseNetworkFor(specificNetRequest); mNetFactory.updateInterfaceLinkState(TEST_IFACE, true, NULL_LISTENER); - verify(mDeps).makeIpClient(any(), eq(TEST_IFACE), any()); + // TODO: change to once when b/191854824 is fixed. + verify(mDeps, times(2)).makeIpClient(any(), eq(TEST_IFACE), any()); } @Test From 95de2821c250044988e91fb8a4d9c5ecf54b3c4a Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Mon, 10 Jan 2022 14:39:39 +0100 Subject: [PATCH 837/881] Enable EthernetServiceTests in presubmit Test: run presubmit Bug: 213863997 Change-Id: I6736198539a37d538d5d53d64c16abe572bf3982 --- tests/ethernet/Android.bp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp index 93a8f6ca45..28b13c5243 100644 --- a/tests/ethernet/Android.bp +++ b/tests/ethernet/Android.bp @@ -40,4 +40,5 @@ android_test { "services.core", "services.net", ], + test_suites: ["general-tests"], } From 420d6e09c9e9e95cdb931e3e7d9c3fbcd72e82dc Mon Sep 17 00:00:00 2001 From: James Mattis Date: Thu, 17 Feb 2022 13:06:45 -0800 Subject: [PATCH 838/881] Updating Eth Update Request to use Builder Updating EthernetNetworkUpdateRequest to use a builder for creation and also changing to use IpConfiguration instead of StaticIpConfiguration. Bug: 220017952 Bug: 210487893 Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I78b002c12cf927c075671b75f0fe0d7878443b56 --- .../net/EthernetNetworkUpdateRequest.java | 70 +++++++++++++++++-- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java index e879e40247..a626971105 100644 --- a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java +++ b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java @@ -17,6 +17,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -27,13 +28,13 @@ import java.util.Objects; @SystemApi public final class EthernetNetworkUpdateRequest implements Parcelable { @NonNull - private final StaticIpConfiguration mIpConfig; + private final IpConfiguration mIpConfig; @NonNull private final NetworkCapabilities mNetworkCapabilities; @NonNull - public StaticIpConfiguration getIpConfig() { - return new StaticIpConfiguration(mIpConfig); + public IpConfiguration getIpConfiguration() { + return new IpConfiguration(mIpConfig); } @NonNull @@ -41,20 +42,75 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { return new NetworkCapabilities(mNetworkCapabilities); } - public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig, + private EthernetNetworkUpdateRequest(@NonNull final IpConfiguration ipConfig, @NonNull final NetworkCapabilities networkCapabilities) { Objects.requireNonNull(ipConfig); Objects.requireNonNull(networkCapabilities); - mIpConfig = new StaticIpConfiguration(ipConfig); + mIpConfig = new IpConfiguration(ipConfig); mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); } private EthernetNetworkUpdateRequest(@NonNull final Parcel source) { Objects.requireNonNull(source); - mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source); + mIpConfig = IpConfiguration.CREATOR.createFromParcel(source); mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source); } + /** + * Builder used to create {@link EthernetNetworkUpdateRequest} objects. + */ + public static final class Builder { + @Nullable + private IpConfiguration mBuilderIpConfig; + @Nullable + private NetworkCapabilities mBuilderNetworkCapabilities; + + public Builder(){} + + /** + * Constructor to populate the builder's values with an already built + * {@link EthernetNetworkUpdateRequest}. + * @param request the {@link EthernetNetworkUpdateRequest} to populate with. + */ + public Builder(@NonNull final EthernetNetworkUpdateRequest request) { + Objects.requireNonNull(request); + mBuilderIpConfig = new IpConfiguration(request.mIpConfig); + mBuilderNetworkCapabilities = new NetworkCapabilities(request.mNetworkCapabilities); + } + + /** + * Set the {@link IpConfiguration} to be used with the {@code Builder}. + * @param ipConfig the {@link IpConfiguration} to set. + * @return The builder to facilitate chaining. + */ + @NonNull + public Builder setIpConfiguration(@NonNull final IpConfiguration ipConfig) { + Objects.requireNonNull(ipConfig); + mBuilderIpConfig = new IpConfiguration(ipConfig); + return this; + } + + /** + * Set the {@link NetworkCapabilities} to be used with the {@code Builder}. + * @param nc the {@link NetworkCapabilities} to set. + * @return The builder to facilitate chaining. + */ + @NonNull + public Builder setNetworkCapabilities(@NonNull final NetworkCapabilities nc) { + Objects.requireNonNull(nc); + mBuilderNetworkCapabilities = new NetworkCapabilities(nc); + return this; + } + + /** + * Build {@link EthernetNetworkUpdateRequest} return the current update request. + */ + @NonNull + public EthernetNetworkUpdateRequest build() { + return new EthernetNetworkUpdateRequest(mBuilderIpConfig, mBuilderNetworkCapabilities); + } + } + @Override public String toString() { return "EthernetNetworkUpdateRequest{" @@ -68,7 +124,7 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { if (o == null || getClass() != o.getClass()) return false; EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o; - return Objects.equals(that.getIpConfig(), mIpConfig) + return Objects.equals(that.getIpConfiguration(), mIpConfig) && Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities); } From 744ace6b288c966066dacb1f8bbd8fa8159e3d69 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Thu, 17 Feb 2022 13:08:20 -0800 Subject: [PATCH 839/881] Using a builder for eth requests Updating ethernet classes to use a builder when creating an EthernetNetworkUpdateRequest and also changing to use IpConfiguration instead of StaticIpConfiguration for the UpdateConfiguration API. Bug: 220017952 Bug: 210487893 Bug: 210485380 Test: atest EthernetServiceTests Change-Id: I2647115bf867dfaa3f3dadf00e3c875aa7e8d88f --- .../server/ethernet/EthernetServiceImpl.java | 2 +- .../server/ethernet/EthernetTracker.java | 18 +++++++----------- .../ethernet/EthernetServiceImplTest.java | 9 +++++---- .../server/ethernet/EthernetTrackerTest.java | 11 +++++++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index c1c6d3a60b..fed500f367 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -239,7 +239,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { // TODO: validate that iface is listed in overlay config_ethernet_interfaces mTracker.updateConfiguration( - iface, request.getIpConfig(), request.getNetworkCapabilities(), listener); + iface, request.getIpConfiguration(), request.getNetworkCapabilities(), listener); } @Override diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 2571fe66fe..794b5d1b90 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -229,18 +229,18 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void updateConfiguration(@NonNull final String iface, - @NonNull final StaticIpConfiguration staticIpConfig, + @NonNull final IpConfiguration ipConfig, @NonNull final NetworkCapabilities capabilities, @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities - + ", staticIpConfig: " + staticIpConfig); + + ", ipConfig: " + ipConfig); } - final IpConfiguration ipConfig = createIpConfiguration(staticIpConfig); - writeIpConfiguration(iface, ipConfig); + final IpConfiguration localIpConfig = new IpConfiguration(ipConfig); + writeIpConfiguration(iface, localIpConfig); mNetworkCapabilities.put(iface, capabilities); mHandler.post(() -> { - mFactory.updateInterface(iface, ipConfig, capabilities, listener); + mFactory.updateInterface(iface, localIpConfig, capabilities, listener); broadcastInterfaceStateChange(iface); }); } @@ -715,13 +715,9 @@ public class EthernetTracker { return createIpConfiguration(staticIpConfigBuilder.build()); } - static IpConfiguration createIpConfiguration( + private static IpConfiguration createIpConfiguration( @NonNull final StaticIpConfiguration staticIpConfig) { - final IpConfiguration ret = new IpConfiguration(); - ret.setIpAssignment(IpAssignment.STATIC); - ret.setProxySettings(ProxySettings.NONE); - ret.setStaticIpConfiguration(staticIpConfig); - return ret; + return new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build(); } private IpConfiguration getOrCreateIpConfiguration(String iface) { diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 0ac28c43dd..28297537ea 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -32,7 +32,6 @@ import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; import android.net.NetworkCapabilities; -import android.net.StaticIpConfiguration; import android.os.Handler; import androidx.test.filters.SmallTest; @@ -49,8 +48,10 @@ import org.mockito.MockitoAnnotations; public class EthernetServiceImplTest { private static final String TEST_IFACE = "test123"; private static final EthernetNetworkUpdateRequest UPDATE_REQUEST = - new EthernetNetworkUpdateRequest( - new StaticIpConfiguration(), new NetworkCapabilities.Builder().build()); + new EthernetNetworkUpdateRequest.Builder() + .setIpConfiguration(new IpConfiguration()) + .setNetworkCapabilities(new NetworkCapabilities.Builder().build()) + .build(); private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @@ -214,7 +215,7 @@ public class EthernetServiceImplTest { mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); verify(mEthernetTracker).updateConfiguration( eq(TEST_IFACE), - eq(UPDATE_REQUEST.getIpConfig()), + eq(UPDATE_REQUEST.getIpConfiguration()), eq(UPDATE_REQUEST.getNetworkCapabilities()), eq(NULL_LISTENER)); } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index 14f34d0dab..e1a1a8e7e9 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -324,15 +324,18 @@ public class EthernetTrackerTest { @Test public void testUpdateConfiguration() { final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build(); - final StaticIpConfiguration staticIpConfig = new StaticIpConfiguration(); + final LinkAddress linkAddr = new LinkAddress("192.0.2.2/25"); + final StaticIpConfiguration staticIpConfig = + new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build(); + final IpConfiguration ipConfig = + new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build(); final IEthernetNetworkManagementListener listener = null; - tracker.updateConfiguration(TEST_IFACE, staticIpConfig, capabilities, listener); + tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener); waitForIdle(); verify(mFactory).updateInterface( - eq(TEST_IFACE), eq(EthernetTracker.createIpConfiguration(staticIpConfig)), - eq(capabilities), eq(listener)); + eq(TEST_IFACE), eq(ipConfig), eq(capabilities), eq(listener)); } @Test From 5c3fa07cc137845d26753635c208422663ff651e Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 9 Feb 2022 20:37:26 +0800 Subject: [PATCH 840/881] [DU03-4]Add NETWORK_STACK Permission check for NetworkStatsService API 1. getUidStatsForTransport API Bug: 210066922 Test: atest BatteryStatsImplTest WifiPowerCalculatorTest MobileRadioPowerCalculatorTest NetworkStatsServiceTest (cherry-picked from ag/16816095) Change-Id: I022c34b5af87fe3ff6857ea264bac2f7098eaed4 Merged-In: I022c34b5af87fe3ff6857ea264bac2f7098eaed4 --- .../src/android/app/usage/NetworkStatsManager.java | 8 ++++++-- .../src/com/android/server/net/NetworkStatsService.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 0414bb79f8..a8baa8e488 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -699,7 +699,9 @@ public class NetworkStatsManager { * @hide */ @SystemApi - @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) @NonNull public android.net.NetworkStats getMobileUidStats() { try { return mService.getUidStatsForTransport(TRANSPORT_CELLULAR); @@ -723,7 +725,9 @@ public class NetworkStatsManager { * @hide */ @SystemApi - @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}) @NonNull public android.net.NetworkStats getWifiUidStats() { try { return mService.getUidStatsForTransport(TRANSPORT_WIFI); diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 1579f1e171..0b5a85fa4b 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1123,7 +1123,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public NetworkStats getUidStatsForTransport(int transport) { - enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + PermissionUtils.enforceNetworkStackPermission(mContext); try { final String[] relevantIfaces = transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces; From 5f93cdff5a97cc1a14fde6a4e2542a5b6f4b025d Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 28 Jan 2022 22:02:06 +0800 Subject: [PATCH 841/881] [MS68.3] Address comments at aosp/1958144 Test: atest TrafficStatsTest NetworkUsageStatsTest FrameworksNetTests Bug: 204830222 (cherry-picked from ag/16813003) Change-Id: I5a54b44294021d64d8506eeb570db0db8544472a Merged-In: I5a54b44294021d64d8506eeb570db0db8544472a --- .../app/usage/NetworkStatsManager.java | 8 ++++++-- .../server/net/NetworkStatsObservers.java | 20 ++++++++++++------- .../server/net/NetworkStatsService.java | 2 +- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index 0414bb79f8..221a848a59 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -740,8 +740,9 @@ public class NetworkStatsManager { * {@link #unregisterUsageCallback} is called. * * @param template Template used to match networks. See {@link NetworkTemplate}. - * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower - * than 2MiB will be clamped for non-privileged callers. + * @param thresholdBytes Threshold in bytes to be notified on. Provided values lower than 2MiB + * will be clamped for callers except callers with the NETWORK_STACK + * permission. * @param executor The executor on which callback will be invoked. The provided {@link Executor} * must run callback sequentially, otherwise the order of callbacks cannot be * guaranteed. @@ -750,6 +751,9 @@ public class NetworkStatsManager { * @hide */ @SystemApi(client = MODULE_LIBRARIES) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK}, conditional = true) public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes, @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) { Objects.requireNonNull(template, "NetworkTemplate cannot be null"); diff --git a/service-t/src/com/android/server/net/NetworkStatsObservers.java b/service-t/src/com/android/server/net/NetworkStatsObservers.java index 19536247b2..fdfc893f57 100644 --- a/service-t/src/com/android/server/net/NetworkStatsObservers.java +++ b/service-t/src/com/android/server/net/NetworkStatsObservers.java @@ -19,8 +19,11 @@ package com.android.server.net; import static android.app.usage.NetworkStatsManager.MIN_THRESHOLD_BYTES; import android.app.usage.NetworkStatsManager; +import android.content.Context; +import android.content.pm.PackageManager; import android.net.DataUsageRequest; import android.net.NetworkIdentitySet; +import android.net.NetworkStack; import android.net.NetworkStats; import android.net.NetworkStatsAccess; import android.net.NetworkStatsCollection; @@ -74,9 +77,9 @@ class NetworkStatsObservers { * * @return the normalized request wrapped within {@link RequestInfo}. */ - public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback, - int callingUid, @NetworkStatsAccess.Level int accessLevel) { - DataUsageRequest request = buildRequest(inputRequest, callingUid); + public DataUsageRequest register(Context context, DataUsageRequest inputRequest, + IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { + DataUsageRequest request = buildRequest(context, inputRequest, callingUid); RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid, accessLevel); @@ -194,10 +197,13 @@ class NetworkStatsObservers { } } - private DataUsageRequest buildRequest(DataUsageRequest request, int callingUid) { - // For non-system uid, cap the minimum threshold to a safe default to avoid too - // many callbacks. - long thresholdInBytes = (callingUid == Process.SYSTEM_UID ? request.thresholdInBytes + private DataUsageRequest buildRequest(Context context, DataUsageRequest request, + int callingUid) { + // For non-NETWORK_STACK permission uid, cap the minimum threshold to a safe default to + // avoid too many callbacks. + final long thresholdInBytes = (context.checkPermission( + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, Process.myPid(), callingUid) + == PackageManager.PERMISSION_GRANTED ? request.thresholdInBytes : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes)); if (thresholdInBytes > request.thresholdInBytes) { Log.w(TAG, "Threshold was too low for " + request diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 1579f1e171..775a47d2e0 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1285,7 +1285,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { DataUsageRequest normalizedRequest; final long token = Binder.clearCallingIdentity(); try { - normalizedRequest = mStatsObservers.register( + normalizedRequest = mStatsObservers.register(mContext, request, callback, callingUid, accessLevel); } finally { Binder.restoreCallingIdentity(token); From 2bdae7d6e462d3026defeb7fd6f9c6eac96d6473 Mon Sep 17 00:00:00 2001 From: lifr Date: Mon, 1 Nov 2021 18:50:54 +0800 Subject: [PATCH 842/881] [SUBID01-0]Grow NetworkIdentity to include a new mSubId field In the previous design of NSS and NPMS, those only had IMSI to identify the cell network. Now the telephony has created the "subId" handle, which is the preferred mechanism for identifying subscribers. This commit adds NetworkStats support for subscriberId as a part of the network identity key Bug: 80526261 Test: atest NetworkTemplateTest NetworkStatsCollectionTest NetworkStatsServiceTest NetworkIdentityTest NetworkStatsDataMigrationUtilsTest (cherry-picked from ag/16825721) Change-Id: Ie1fe81006555dbcca4b62457fa6c319f04b4576d Merged-In: Ie1fe81006555dbcca4b62457fa6c319f04b4576d --- .../src/android/net/NetworkIdentity.java | 39 ++++++++++++++++--- .../src/android/net/NetworkIdentitySet.java | 14 ++++++- .../src/android/net/NetworkStateSnapshot.java | 21 +++++++++- .../server/net/NetworkStatsService.java | 13 +++++-- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 4ebaf2b8cd..a48f94b66d 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -20,6 +20,7 @@ import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkTemplate.NETWORK_TYPE_ALL; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import android.annotation.IntDef; import android.annotation.NonNull; @@ -86,6 +87,7 @@ public class NetworkIdentity { final int mType; final int mRatType; + final int mSubId; final String mSubscriberId; final String mWifiNetworkKey; final boolean mRoaming; @@ -96,7 +98,7 @@ public class NetworkIdentity { /** @hide */ public NetworkIdentity( int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey, - boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged) { + boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged, int subId) { mType = type; mRatType = ratType; mSubscriberId = subscriberId; @@ -105,12 +107,13 @@ public class NetworkIdentity { mMetered = metered; mDefaultNetwork = defaultNetwork; mOemManaged = oemManaged; + mSubId = subId; } @Override public int hashCode() { return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered, - mDefaultNetwork, mOemManaged); + mDefaultNetwork, mOemManaged, mSubId); } @Override @@ -122,7 +125,8 @@ public class NetworkIdentity { && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey) && mMetered == ident.mMetered && mDefaultNetwork == ident.mDefaultNetwork - && mOemManaged == ident.mOemManaged; + && mOemManaged == ident.mOemManaged + && mSubId == ident.mSubId; } return false; } @@ -150,6 +154,7 @@ public class NetworkIdentity { builder.append(", metered=").append(mMetered); builder.append(", defaultNetwork=").append(mDefaultNetwork); builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged)); + builder.append(", subId=").append(mSubId); return builder.append("}").toString(); } @@ -256,6 +261,11 @@ public class NetworkIdentity { return mOemManaged; } + /** Get the SubId of this instance. */ + public int getSubId() { + return mSubId; + } + /** * Assemble a {@link NetworkIdentity} from the passed arguments. * @@ -276,7 +286,8 @@ public class NetworkIdentity { public static NetworkIdentity buildNetworkIdentity(Context context, @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) { final NetworkIdentity.Builder builder = new NetworkIdentity.Builder() - .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork); + .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork) + .setSubId(snapshot.getSubId()); if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) { builder.setRatType(ratType); } @@ -325,6 +336,9 @@ public class NetworkIdentity { if (res == 0) { res = Integer.compare(left.mOemManaged, right.mOemManaged); } + if (res == 0) { + res = Integer.compare(left.mSubId, right.mSubId); + } return res; } @@ -345,6 +359,7 @@ public class NetworkIdentity { private boolean mMetered; private boolean mDefaultNetwork; private int mOemManaged; + private int mSubId; /** * Creates a new Builder. @@ -359,6 +374,7 @@ public class NetworkIdentity { mMetered = false; mDefaultNetwork = false; mOemManaged = NetworkTemplate.OEM_MANAGED_NO; + mSubId = INVALID_SUBSCRIPTION_ID; } /** @@ -537,6 +553,19 @@ public class NetworkIdentity { return this; } + /** + * Set the Subscription Id. + * + * @param subId the Subscription Id of the network. Or INVALID_SUBSCRIPTION_ID if not + * applicable. + * @return this builder. + */ + @NonNull + public Builder setSubId(int subId) { + mSubId = subId; + return this; + } + private void ensureValidParameters() { // Assert non-mobile network cannot have a ratType. if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) { @@ -559,7 +588,7 @@ public class NetworkIdentity { public NetworkIdentity build() { ensureValidParameters(); return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey, - mRoaming, mMetered, mDefaultNetwork, mOemManaged); + mRoaming, mMetered, mDefaultNetwork, mOemManaged, mSubId); } } } diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java index 2236d70c35..56461babfe 100644 --- a/framework-t/src/android/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -17,6 +17,7 @@ package android.net; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import android.annotation.NonNull; import android.service.NetworkIdentitySetProto; @@ -42,6 +43,7 @@ public class NetworkIdentitySet extends HashSet { private static final int VERSION_ADD_METERED = 4; private static final int VERSION_ADD_DEFAULT_NETWORK = 5; private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6; + private static final int VERSION_ADD_SUB_ID = 7; /** * Construct a {@link NetworkIdentitySet} object. @@ -103,8 +105,15 @@ public class NetworkIdentitySet extends HashSet { oemNetCapabilities = NetworkIdentity.OEM_NONE; } + final int subId; + if (version >= VERSION_ADD_SUB_ID) { + subId = in.readInt(); + } else { + subId = INVALID_SUBSCRIPTION_ID; + } + add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered, - defaultNetwork, oemNetCapabilities)); + defaultNetwork, oemNetCapabilities, subId)); } } @@ -113,7 +122,7 @@ public class NetworkIdentitySet extends HashSet { * @hide */ public void writeToStream(DataOutput out) throws IOException { - out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK); + out.writeInt(VERSION_ADD_SUB_ID); out.writeInt(size()); for (NetworkIdentity ident : this) { out.writeInt(ident.getType()); @@ -124,6 +133,7 @@ public class NetworkIdentitySet extends HashSet { out.writeBoolean(ident.isMetered()); out.writeBoolean(ident.isDefaultNetwork()); out.writeInt(ident.getOemManaged()); + out.writeInt(ident.getSubId()); } } diff --git a/framework-t/src/android/net/NetworkStateSnapshot.java b/framework-t/src/android/net/NetworkStateSnapshot.java index 3915634392..d3f785a8f9 100644 --- a/framework-t/src/android/net/NetworkStateSnapshot.java +++ b/framework-t/src/android/net/NetworkStateSnapshot.java @@ -17,6 +17,8 @@ package android.net; import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import android.annotation.NonNull; import android.annotation.Nullable; @@ -98,12 +100,29 @@ public final class NetworkStateSnapshot implements Parcelable { return mLinkProperties; } - /** Get the Subscriber Id of the network associated with this snapshot. */ + /** + * Get the Subscriber Id of the network associated with this snapshot. + * @deprecated Please use #getSubId, which doesn't return personally identifiable + * information. + */ + @Deprecated @Nullable public String getSubscriberId() { return mSubscriberId; } + /** Get the subId of the network associated with this snapshot. */ + public int getSubId() { + if (mNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) { + final NetworkSpecifier spec = mNetworkCapabilities.getNetworkSpecifier(); + if (spec instanceof TelephonyNetworkSpecifier) { + return ((TelephonyNetworkSpecifier) spec).getSubscriptionId(); + } + } + return INVALID_SUBSCRIPTION_ID; + } + + /** * Get the legacy type of the network associated with this snapshot. * @return the legacy network type. See {@code ConnectivityManager#TYPE_*}. diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 1579f1e171..ccca3daf7d 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1540,10 +1540,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) { // Copy the identify from IMS one but mark it as metered. - NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), - ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(), - ident.isRoaming(), true /* metered */, - true /* onDefaultNetwork */, ident.getOemManaged()); + NetworkIdentity vtIdent = new NetworkIdentity.Builder() + .setType(ident.getType()) + .setRatType(ident.getRatType()) + .setSubscriberId(ident.getSubscriberId()) + .setWifiNetworkKey(ident.getWifiNetworkKey()) + .setRoaming(ident.isRoaming()).setMetered(true) + .setDefaultNetwork(true) + .setOemManaged(ident.getOemManaged()) + .setSubId(ident.getSubId()).build(); final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot); findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent); findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent); From 5f835f735c5da1445ba5b7db1c543ea73d84b0a3 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Mon, 28 Feb 2022 14:08:12 -0800 Subject: [PATCH 843/881] Ethernet validate if iface is tracked on handler Removing synchronous validation of whether a particular interface is tracked or not and instead relying on asynchronous validation and callbacks. An interface can be in the midst of being provisioned and checking if it is tracked sychronously before provisioning is complete will erroneously throw an error for a call that would have been successful when executed on the ethernet handler thread. Bug: 210487893 Bug: 210485380 Test: atest EthernetServiceTests Change-Id: Ib70312a240cab412a54ca7f598893aa9b1e108fd --- .../ethernet/EthernetNetworkFactory.java | 26 ++++++++++--------- .../server/ethernet/EthernetServiceImpl.java | 13 +++------- .../ethernet/EthernetNetworkFactoryTest.java | 14 ++++++++++ .../ethernet/EthernetServiceImplTest.java | 24 ----------------- 4 files changed, 31 insertions(+), 46 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index f266386024..8ce27a64b1 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -220,20 +220,17 @@ public class EthernetNetworkFactory extends NetworkFactory { @NonNull final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, @Nullable final IEthernetNetworkManagementListener listener) { - enforceInterfaceIsTracked(ifaceName); + if (!hasInterface(ifaceName)) { + maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); + return; + } + final NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName); iface.updateInterface(ipConfig, capabilities, listener); mTrackingInterfaces.put(ifaceName, iface); updateCapabilityFilter(); } - private void enforceInterfaceIsTracked(@NonNull final String ifaceName) { - if (!hasInterface(ifaceName)) { - throw new UnsupportedOperationException( - "Interface with name " + ifaceName + " is not being tracked."); - } - } - private static NetworkCapabilities mixInCapabilities(NetworkCapabilities nc, NetworkCapabilities addedNc) { final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(nc); @@ -272,10 +269,8 @@ public class EthernetNetworkFactory extends NetworkFactory { @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up, @Nullable final IEthernetNetworkManagementListener listener) { - if (!mTrackingInterfaces.containsKey(ifaceName)) { - maybeSendNetworkManagementCallback(listener, null, - new EthernetNetworkManagementException( - ifaceName + " can't be updated as it is not available.")); + if (!hasInterface(ifaceName)) { + maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return false; } @@ -287,6 +282,13 @@ public class EthernetNetworkFactory extends NetworkFactory { return iface.updateLinkState(up, listener); } + private void maybeSendNetworkManagementCallbackForUntracked( + String ifaceName, IEthernetNetworkManagementListener listener) { + maybeSendNetworkManagementCallback(listener, null, + new EthernetNetworkManagementException( + ifaceName + " can't be updated as it is not available.")); + } + @VisibleForTesting protected boolean hasInterface(String ifaceName) { return mTrackingInterfaces.containsKey(ifaceName); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index fed500f367..f80f6a05b8 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -66,12 +66,6 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { methodName + " is only available on automotive devices."); } - private void enforceInterfaceIsTracked(final @NonNull String iface) { - if(!mTracker.isTrackingInterface(iface)) { - throw new UnsupportedOperationException("The given iface is not currently tracked."); - } - } - private boolean checkUseRestrictedNetworksPermission() { return PermissionUtils.checkAnyPermissionOf(mContext, android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS); @@ -220,13 +214,12 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { */ private void validateNetworkManagementState(@NonNull final String iface, final @NonNull String methodName) { + Objects.requireNonNull(iface, "Pass a non-null iface."); + Objects.requireNonNull(methodName, "Pass a non-null methodName."); + enforceAutomotiveDevice(methodName); enforceNetworkManagementPermission(); logIfEthernetNotStarted(); - - Objects.requireNonNull(iface, "Pass a non-null iface."); - Objects.requireNonNull(methodName, "Pass a non-null methodName."); - enforceInterfaceIsTracked(iface); } @Override diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 33831a56d5..61425bf171 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -763,4 +763,18 @@ public class EthernetNetworkFactoryTest { eq(capabilities), any(), any(), any(), any()); verifyRestart(ipConfiguration); } + + @Test + public void testUpdateInterfaceForNonExistingInterface() throws Exception { + initEthernetNetworkFactory(); + // No interface exists due to not calling createAndVerifyProvisionedInterface(...). + final NetworkCapabilities capabilities = createDefaultFilterCaps(); + final IpConfiguration ipConfiguration = createStaticIpConfig(); + final TestNetworkManagementListener listener = new TestNetworkManagementListener(); + + mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); + + verifyNoStopOrStart(); + assertFailedListener(listener, "can't be updated as it is not available"); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 28297537ea..e74a5a366c 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -156,30 +156,6 @@ public class EthernetServiceImplTest { }); } - @Test - public void testUpdateConfigurationRejectsWithUntrackedIface() { - shouldTrackIface(TEST_IFACE, false); - assertThrows(UnsupportedOperationException.class, () -> { - mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); - }); - } - - @Test - public void testConnectNetworkRejectsWithUntrackedIface() { - shouldTrackIface(TEST_IFACE, false); - assertThrows(UnsupportedOperationException.class, () -> { - mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER); - }); - } - - @Test - public void testDisconnectNetworkRejectsWithUntrackedIface() { - shouldTrackIface(TEST_IFACE, false); - assertThrows(UnsupportedOperationException.class, () -> { - mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); - }); - } - private void denyManageEthPermission() { doThrow(new SecurityException("")).when(mContext) .enforceCallingOrSelfPermission( From 1a8a58449a1d26995d279224f8ab424cb5bcc3c5 Mon Sep 17 00:00:00 2001 From: markchien Date: Tue, 1 Mar 2022 15:16:11 +0800 Subject: [PATCH 844/881] Remove ConnectivityManager swapActiveStatsMap API swapActiveStatsMap is temporary added for the NetworkStatsFactory to call BpfNetMaps#swapActiveStatsMap in tethering mainline module. Now NetworkStatsFactory already be mainlined, calling BpfNetMaps#swapActiveStatsMap directly. Bug: 218494448 Test: atest ConnectivityCoverageTests atest FrameworksNetTests Change-Id: I25618020c078c7de3f0036c48d06d7816a431f62 --- .../server/net/NetworkStatsFactory.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsFactory.java b/service-t/src/com/android/server/net/NetworkStatsFactory.java index 151c90dd41..3b93f1a190 100644 --- a/service-t/src/com/android/server/net/NetworkStatsFactory.java +++ b/service-t/src/com/android/server/net/NetworkStatsFactory.java @@ -25,9 +25,9 @@ import static android.net.NetworkStats.UID_ALL; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.net.ConnectivityManager; import android.net.NetworkStats; import android.net.UnderlyingNetworkInfo; +import android.os.ServiceSpecificException; import android.os.StrictMode; import android.os.SystemClock; @@ -35,6 +35,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ProcFileReader; import com.android.net.module.util.CollectionUtils; +import com.android.server.BpfNetMaps; import libcore.io.IoUtils; @@ -74,6 +75,8 @@ public class NetworkStatsFactory { private final Context mContext; + private final BpfNetMaps mBpfNetMaps; + /** * Guards persistent data access in this class * @@ -170,6 +173,7 @@ public class NetworkStatsFactory { mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); mUseBpfStats = useBpfStats; + mBpfNetMaps = new BpfNetMaps(); synchronized (mPersistentDataLock) { mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1); mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1); @@ -297,12 +301,14 @@ public class NetworkStatsFactory { } @GuardedBy("mPersistentDataLock") - private void requestSwapActiveStatsMapLocked() { - // Do a active map stats swap. When the binder call successfully returns, - // the system server should be able to safely read and clean the inactive map - // without race problem. - final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class); - cm.swapActiveStatsMap(); + private void requestSwapActiveStatsMapLocked() throws IOException { + try { + // Do a active map stats swap. Once the swap completes, this code + // can read and clean the inactive map without races. + mBpfNetMaps.swapActiveStatsMap(); + } catch (ServiceSpecificException e) { + throw new IOException(e); + } } /** @@ -328,11 +334,7 @@ public class NetworkStatsFactory { final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0 /* initialSize */); if (mUseBpfStats) { - try { - requestSwapActiveStatsMapLocked(); - } catch (RuntimeException e) { - throw new IOException(e); - } + requestSwapActiveStatsMapLocked(); // Stats are always read from the inactive map, so they must be read after the // swap if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), UID_ALL, From fd5dcd2dd9f50c373c3d3d5218b28d6014adeb84 Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 7 Mar 2022 16:15:50 +0800 Subject: [PATCH 845/881] [DU09-2]Modify the NetworkStatsCollection Builder API 1. Adding the bucketDuration with unit as bucketDurationmillis 2. make the Key class be final 3. The Key set parameter be marked with an IntDef Bug: 220153505 Test: atest NetworkStatsCollectionTest Change-Id: Iab32b8fc129b77d6786c2f1f2339e515f2eb55f7 --- .../android/net/NetworkStatsCollection.java | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 67d48f0000..1ddc78bb4d 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -36,6 +36,7 @@ import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRation import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.net.NetworkStats.State; import android.net.NetworkStatsHistory.Entry; import android.os.Binder; import android.service.NetworkStatsCollectionKeyProto; @@ -102,7 +103,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private ArrayMap mStats = new ArrayMap<>(); - private final long mBucketDuration; + private final long mBucketDurationMillis; private long mStartMillis; private long mEndMillis; @@ -115,8 +116,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * @param bucketDuration duration of the buckets in this object, in milliseconds. * @hide */ - public NetworkStatsCollection(long bucketDuration) { - mBucketDuration = bucketDuration; + public NetworkStatsCollection(long bucketDurationMillis) { + mBucketDurationMillis = bucketDurationMillis; reset(); } @@ -148,7 +149,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W if (mStartMillis == Long.MAX_VALUE) { return Long.MAX_VALUE; } else { - return mStartMillis + mBucketDuration; + return mStartMillis + mBucketDurationMillis; } } @@ -184,10 +185,10 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W || time == SubscriptionPlan.TIME_UNKNOWN) { return time; } else { - final long mod = time % mBucketDuration; + final long mod = time % mBucketDurationMillis; if (mod > 0) { time -= mod; - time += mBucketDuration; + time += mBucketDurationMillis; } return time; } @@ -200,7 +201,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W || time == SubscriptionPlan.TIME_UNKNOWN) { return time; } else { - final long mod = time % mBucketDuration; + final long mod = time % mBucketDurationMillis; if (mod > 0) { time -= mod; } @@ -247,10 +248,10 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W // 180 days of history should be enough for anyone; if we end up needing // more, we'll dynamically grow the history object. final int bucketEstimate = (int) NetworkStatsUtils.constrain( - ((end - start) / mBucketDuration), 0, - (180 * DateUtils.DAY_IN_MILLIS) / mBucketDuration); + ((end - start) / mBucketDurationMillis), 0, + (180 * DateUtils.DAY_IN_MILLIS) / mBucketDurationMillis); final NetworkStatsHistory combined = new NetworkStatsHistory( - mBucketDuration, bucketEstimate, fields); + mBucketDurationMillis, bucketEstimate, fields); // shortcut when we know stats will be empty if (start == end) return combined; @@ -343,7 +344,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W // Finally we can slice data as originally requested final NetworkStatsHistory sliced = new NetworkStatsHistory( - mBucketDuration, bucketEstimate, fields); + mBucketDurationMillis, bucketEstimate, fields); sliced.recordHistory(combined, start, end); return sliced; } else { @@ -458,9 +459,9 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W // update when no existing, or when bucket duration changed NetworkStatsHistory updated = null; if (existing == null) { - updated = new NetworkStatsHistory(mBucketDuration, 10); - } else if (existing.getBucketDuration() != mBucketDuration) { - updated = new NetworkStatsHistory(existing, mBucketDuration); + updated = new NetworkStatsHistory(mBucketDurationMillis, 10); + } else if (existing.getBucketDuration() != mBucketDurationMillis) { + updated = new NetworkStatsHistory(existing, mBucketDurationMillis); } if (updated != null) { @@ -702,7 +703,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W private int estimateBuckets() { return (int) (Math.min(mEndMillis - mStartMillis, WEEK_IN_MILLIS * 5) - / mBucketDuration); + / mBucketDurationMillis); } private ArrayList getSortedKeys() { @@ -828,7 +829,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * Builder class for {@link NetworkStatsCollection}. */ public static final class Builder { - private final long mBucketDuration; + private final long mBucketDurationMillis; private final ArrayMap mEntries = new ArrayMap<>(); /** @@ -836,8 +837,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * * @param bucketDuration Duration of the buckets of the object, in milliseconds. */ - public Builder(long bucketDuration) { - mBucketDuration = bucketDuration; + public Builder(long bucketDurationMillis) { + mBucketDurationMillis = bucketDurationMillis; } /** @@ -855,7 +856,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W final List historyEntries = history.getEntries(); final NetworkStatsHistory.Builder historyBuilder = - new NetworkStatsHistory.Builder(mBucketDuration, historyEntries.size()); + new NetworkStatsHistory.Builder(mBucketDurationMillis, historyEntries.size()); for (Entry entry : historyEntries) { historyBuilder.addEntry(entry); } @@ -871,7 +872,8 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W */ @NonNull public NetworkStatsCollection build() { - final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration); + final NetworkStatsCollection collection = + new NetworkStatsCollection(mBucketDurationMillis); for (int i = 0; i < mEntries.size(); i++) { collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i)); } @@ -883,7 +885,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * the identifier that associate with the {@link NetworkStatsHistory} object to identify * a certain record in the {@link NetworkStatsCollection} object. */ - public static class Key { + public static final class Key { /** @hide */ public final NetworkIdentitySet ident; /** @hide */ @@ -903,7 +905,7 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W * @param set Set of the record, see {@code NetworkStats#SET_*}. * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}. */ - public Key(@NonNull Set ident, int uid, int set, int tag) { + public Key(@NonNull Set ident, int uid, @State int set, int tag) { this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag); } From 85b2dc0020fe0cedbcfa79045945b027702162e4 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 14 Feb 2022 21:26:44 +0800 Subject: [PATCH 846/881] Fix proto invalid write type While dumpProtoLocked is called, InvalidProtocolBufferException occurred because types are mismatched between platform side and module side. netstats.proto was moved into connectivity module, both the platform(incident.proto) and the module uses protoc-gen-javastream to generate the Java classes from it. It should be fine since platform includes the source of the proto, and jarjar the generated classess in the module to avoid conflict with platform. Bug: 218566849 Test: adb shell incident 3001 adb shell dumpsys netstats --proto atest CtsIncidentHostTestCases:IncidentdTest#testIncidentReportDumpAuto Change-Id: I4654350a59dc1ca1a925785ad37f34aa7b481235 Merged-In: I4654350a59dc1ca1a925785ad37f34aa7b481235 --- framework-t/src/android/net/NetworkIdentity.java | 10 +++++----- .../src/android/net/NetworkIdentitySet.java | 2 +- .../src/android/net/NetworkStatsCollection.java | 14 +++++++------- .../src/android/net/NetworkStatsHistory.java | 16 ++++++++-------- .../android/server/net/NetworkStatsRecorder.java | 4 ++-- .../android/server/net/NetworkStatsService.java | 16 ++++++++-------- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/framework-t/src/android/net/NetworkIdentity.java b/framework-t/src/android/net/NetworkIdentity.java index 4ebaf2b8cd..56faa52e82 100644 --- a/framework-t/src/android/net/NetworkIdentity.java +++ b/framework-t/src/android/net/NetworkIdentity.java @@ -184,14 +184,14 @@ public class NetworkIdentity { public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); - proto.write(NetworkIdentityProto.TYPE_FIELD_NUMBER, mType); + proto.write(NetworkIdentityProto.TYPE, mType); // TODO: dump mRatType as well. - proto.write(NetworkIdentityProto.ROAMING_FIELD_NUMBER, mRoaming); - proto.write(NetworkIdentityProto.METERED_FIELD_NUMBER, mMetered); - proto.write(NetworkIdentityProto.DEFAULT_NETWORK_FIELD_NUMBER, mDefaultNetwork); - proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK_FIELD_NUMBER, mOemManaged); + proto.write(NetworkIdentityProto.ROAMING, mRoaming); + proto.write(NetworkIdentityProto.METERED, mMetered); + proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork); + proto.write(NetworkIdentityProto.OEM_MANAGED_NETWORK, mOemManaged); proto.end(start); } diff --git a/framework-t/src/android/net/NetworkIdentitySet.java b/framework-t/src/android/net/NetworkIdentitySet.java index 2236d70c35..dfa347f6f1 100644 --- a/framework-t/src/android/net/NetworkIdentitySet.java +++ b/framework-t/src/android/net/NetworkIdentitySet.java @@ -212,7 +212,7 @@ public class NetworkIdentitySet extends HashSet { final long start = proto.start(tag); for (NetworkIdentity ident : this) { - ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES_FIELD_NUMBER); + ident.dumpDebug(proto, NetworkIdentitySetProto.IDENTITIES); } proto.end(start); diff --git a/framework-t/src/android/net/NetworkStatsCollection.java b/framework-t/src/android/net/NetworkStatsCollection.java index 67d48f0000..735c44d5c8 100644 --- a/framework-t/src/android/net/NetworkStatsCollection.java +++ b/framework-t/src/android/net/NetworkStatsCollection.java @@ -732,19 +732,19 @@ public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.W final long start = proto.start(tag); for (Key key : getSortedKeys()) { - final long startStats = proto.start(NetworkStatsCollectionProto.STATS_FIELD_NUMBER); + final long startStats = proto.start(NetworkStatsCollectionProto.STATS); // Key - final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY_FIELD_NUMBER); - key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY_FIELD_NUMBER); - proto.write(NetworkStatsCollectionKeyProto.UID_FIELD_NUMBER, key.uid); - proto.write(NetworkStatsCollectionKeyProto.SET_FIELD_NUMBER, key.set); - proto.write(NetworkStatsCollectionKeyProto.TAG_FIELD_NUMBER, key.tag); + final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY); + key.ident.dumpDebug(proto, NetworkStatsCollectionKeyProto.IDENTITY); + proto.write(NetworkStatsCollectionKeyProto.UID, key.uid); + proto.write(NetworkStatsCollectionKeyProto.SET, key.set); + proto.write(NetworkStatsCollectionKeyProto.TAG, key.tag); proto.end(startKey); // Value final NetworkStatsHistory history = mStats.get(key); - history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY_FIELD_NUMBER); + history.dumpDebug(proto, NetworkStatsCollectionStatsProto.HISTORY); proto.end(startStats); } diff --git a/framework-t/src/android/net/NetworkStatsHistory.java b/framework-t/src/android/net/NetworkStatsHistory.java index 822a16e0bb..301fef9441 100644 --- a/framework-t/src/android/net/NetworkStatsHistory.java +++ b/framework-t/src/android/net/NetworkStatsHistory.java @@ -915,18 +915,18 @@ public final class NetworkStatsHistory implements Parcelable { public void dumpDebug(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); - proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS_FIELD_NUMBER, bucketDuration); + proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration); for (int i = 0; i < bucketCount; i++) { - final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS_FIELD_NUMBER); + final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS); - proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS_FIELD_NUMBER, + proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS, bucketStart[i]); - dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES_FIELD_NUMBER, rxBytes, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS_FIELD_NUMBER, rxPackets, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES_FIELD_NUMBER, txBytes, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS_FIELD_NUMBER, txPackets, i); - dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS_FIELD_NUMBER, operations, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i); + dumpDebug(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i); proto.end(startBucket); } diff --git a/service-t/src/com/android/server/net/NetworkStatsRecorder.java b/service-t/src/com/android/server/net/NetworkStatsRecorder.java index a006cd5975..f62765d074 100644 --- a/service-t/src/com/android/server/net/NetworkStatsRecorder.java +++ b/service-t/src/com/android/server/net/NetworkStatsRecorder.java @@ -471,11 +471,11 @@ public class NetworkStatsRecorder { public void dumpDebugLocked(ProtoOutputStream proto, long tag) { final long start = proto.start(tag); if (mPending != null) { - proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES_FIELD_NUMBER, + proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES, mPending.getTotalBytes()); } getOrLoadCompleteLocked().dumpDebug(proto, - NetworkStatsRecorderProto.COMPLETE_HISTORY_FIELD_NUMBER); + NetworkStatsRecorderProto.COMPLETE_HISTORY); proto.end(start); } diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index 1579f1e171..1f63c3a822 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -2127,15 +2127,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // TODO Right now it writes all history. Should it limit to the "since-boot" log? - dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES_FIELD_NUMBER, + dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces); - dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES_FIELD_NUMBER, + dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces); - mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS_FIELD_NUMBER); - mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS_FIELD_NUMBER); - mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS_FIELD_NUMBER); + mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS); + mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS); + mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS); mUidTagRecorder.dumpDebugLocked(proto, - NetworkStatsServiceDumpProto.UID_TAG_STATS_FIELD_NUMBER); + NetworkStatsServiceDumpProto.UID_TAG_STATS); proto.flush(); } @@ -2145,8 +2145,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { for (int i = 0; i < ifaces.size(); i++) { final long start = proto.start(tag); - proto.write(NetworkInterfaceProto.INTERFACE_FIELD_NUMBER, ifaces.keyAt(i)); - ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES_FIELD_NUMBER); + proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i)); + ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES); proto.end(start); } From e46a330632048a363ae05dfca5bd3f8203935064 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Sat, 26 Feb 2022 22:16:46 -0800 Subject: [PATCH 847/881] Eth Management APIs to Support TEST Interfaces Updating Ethernet Network Management APIs to allow support for test interfaces when the caller has the MANAGE_TEST_NETWORKS permission, test interfaces are being tracked in ethernet and if updating a network's capabilities, they include the TEST transport. Bug: 210487893 Test: atest EthernetServiceTests atest CtsNetTestCasesLatestSdk :android.net.cts.EthernetManagerTest Change-Id: I0e0bc9632d9b3d5d61f23e74150586f42c0b5bd2 --- .../server/ethernet/EthernetServiceImpl.java | 34 ++++++- .../server/ethernet/EthernetTracker.java | 14 +++ .../ethernet/EthernetServiceImplTest.java | 92 +++++++++++++++++++ .../server/ethernet/EthernetTrackerTest.java | 41 ++++++++- 4 files changed, 176 insertions(+), 5 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index f80f6a05b8..7f77e5e633 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -16,6 +16,8 @@ package com.android.server.ethernet; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -26,6 +28,7 @@ import android.net.IEthernetNetworkManagementListener; import android.net.ITetheredInterfaceCallback; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; +import android.net.NetworkCapabilities; import android.os.Binder; import android.os.Handler; import android.os.RemoteException; @@ -206,6 +209,12 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { "EthernetServiceImpl"); } + private void enforceManageTestNetworksPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_TEST_NETWORKS, + "EthernetServiceImpl"); + } + /** * Validate the state of ethernet for APIs tied to network management. * @@ -217,18 +226,35 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Objects.requireNonNull(iface, "Pass a non-null iface."); Objects.requireNonNull(methodName, "Pass a non-null methodName."); - enforceAutomotiveDevice(methodName); - enforceNetworkManagementPermission(); + // Only bypass the permission/device checks if this is a valid test interface. + if (mTracker.isValidTestInterface(iface)) { + enforceManageTestNetworksPermission(); + Log.i(TAG, "Ethernet network management API used with test interface " + iface); + } else { + enforceAutomotiveDevice(methodName); + enforceNetworkManagementPermission(); + } logIfEthernetNotStarted(); } + private void validateTestCapabilities(@NonNull final NetworkCapabilities nc) { + if (nc.hasTransport(TRANSPORT_TEST)) { + return; + } + throw new IllegalArgumentException( + "Updates to test interfaces must have NetworkCapabilities.TRANSPORT_TEST."); + } + @Override public void updateConfiguration(@NonNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, @Nullable final IEthernetNetworkManagementListener listener) { - Log.i(TAG, "updateConfiguration called with: iface=" + iface - + ", request=" + request + ", listener=" + listener); validateNetworkManagementState(iface, "updateConfiguration()"); + if (mTracker.isValidTestInterface(iface)) { + validateTestCapabilities(request.getNetworkCapabilities()); + // TODO: use NetworkCapabilities#restrictCapabilitiesForTestNetwork when available on a + // local NetworkCapabilities copy to pass to mTracker.updateConfiguration. + } // TODO: validate that iface is listed in overlay config_ethernet_interfaces mTracker.updateConfiguration( diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 794b5d1b90..9070a7e090 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -86,6 +86,9 @@ public class EthernetTracker { * if setIncludeTestInterfaces is true, any test interfaces. */ private String mIfaceMatch; + /** + * Track test interfaces if true, don't track otherwise. + */ private boolean mIncludeTestInterfaces = false; /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */ @@ -738,6 +741,17 @@ public class EthernetTracker { Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'"); } + /** + * Validate if a given interface is valid for testing. + * + * @param iface the name of the interface to validate. + * @return {@code true} if test interfaces are enabled and the given {@code iface} has a test + * interface prefix, {@code false} otherwise. + */ + public boolean isValidTestInterface(@NonNull final String iface) { + return mIncludeTestInterfaces && iface.matches(TEST_IFACE_REGEXP); + } + private void postAndWaitForRunnable(Runnable r) { final ConditionVariable cv = new ConditionVariable(); if (mHandler.post(() -> { diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index e74a5a366c..012f07aca1 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -16,6 +16,8 @@ package com.android.server.ethernet; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; + import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.anyString; @@ -23,6 +25,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.Manifest; import android.annotation.NonNull; @@ -162,6 +165,12 @@ public class EthernetServiceImplTest { eq(Manifest.permission.MANAGE_ETHERNET_NETWORKS), anyString()); } + private void denyManageTestNetworksPermission() { + doThrow(new SecurityException("")).when(mContext) + .enforceCallingOrSelfPermission( + eq(Manifest.permission.MANAGE_TEST_NETWORKS), anyString()); + } + @Test public void testUpdateConfigurationRejectsWithoutManageEthPermission() { denyManageEthPermission(); @@ -186,6 +195,37 @@ public class EthernetServiceImplTest { }); } + private void enableTestInterface() { + when(mEthernetTracker.isValidTestInterface(eq(TEST_IFACE))).thenReturn(true); + } + + @Test + public void testUpdateConfigurationRejectsTestRequestWithoutTestPermission() { + enableTestInterface(); + denyManageTestNetworksPermission(); + assertThrows(SecurityException.class, () -> { + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); + }); + } + + @Test + public void testConnectNetworkRejectsTestRequestWithoutTestPermission() { + enableTestInterface(); + denyManageTestNetworksPermission(); + assertThrows(SecurityException.class, () -> { + mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER); + }); + } + + @Test + public void testDisconnectNetworkRejectsTestRequestWithoutTestPermission() { + enableTestInterface(); + denyManageTestNetworksPermission(); + assertThrows(SecurityException.class, () -> { + mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); + }); + } + @Test public void testUpdateConfiguration() { mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); @@ -206,4 +246,56 @@ public class EthernetServiceImplTest { mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER)); } + + @Test + public void testUpdateConfigurationRejectsInvalidTestRequest() { + enableTestInterface(); + assertThrows(IllegalArgumentException.class, () -> { + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); + }); + } + + private EthernetNetworkUpdateRequest createTestNetworkUpdateRequest() { + final NetworkCapabilities nc = new NetworkCapabilities + .Builder(UPDATE_REQUEST.getNetworkCapabilities()) + .addTransportType(TRANSPORT_TEST).build(); + + return new EthernetNetworkUpdateRequest + .Builder(UPDATE_REQUEST) + .setNetworkCapabilities(nc).build(); + } + + @Test + public void testUpdateConfigurationForTestRequestDoesNotRequireAutoOrEthernetPermission() { + enableTestInterface(); + toggleAutomotiveFeature(false); + denyManageEthPermission(); + final EthernetNetworkUpdateRequest request = createTestNetworkUpdateRequest(); + + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER); + verify(mEthernetTracker).updateConfiguration( + eq(TEST_IFACE), + eq(request.getIpConfiguration()), + eq(request.getNetworkCapabilities()), eq(NULL_LISTENER)); + } + + @Test + public void testConnectNetworkForTestRequestDoesNotRequireAutoOrNetPermission() { + enableTestInterface(); + toggleAutomotiveFeature(false); + denyManageEthPermission(); + + mEthernetServiceImpl.connectNetwork(TEST_IFACE, NULL_LISTENER); + verify(mEthernetTracker).connectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER)); + } + + @Test + public void testDisconnectNetworkForTestRequestDoesNotRequireAutoOrNetPermission() { + enableTestInterface(); + toggleAutomotiveFeature(false); + denyManageEthPermission(); + + mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); + verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER)); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index e1a1a8e7e9..d86cc0f60d 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -16,8 +16,12 @@ package com.android.server.ethernet; +import static android.net.TestNetworkManager.TEST_TAP_PREFIX; + import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -39,6 +43,7 @@ import android.net.LinkAddress; import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; import android.os.HandlerThread; +import android.os.RemoteException; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -71,10 +76,11 @@ public class EthernetTrackerTest { @Mock Resources mResources; @Before - public void setUp() { + public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); initMockResources(); when(mFactory.updateInterfaceLinkState(anyString(), anyBoolean(), any())).thenReturn(false); + when(mNetd.interfaceGetList()).thenReturn(new String[0]); mHandlerThread = new HandlerThread(THREAD_NAME); mHandlerThread.start(); tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd); @@ -355,4 +361,37 @@ public class EthernetTrackerTest { verify(mFactory).updateInterfaceLinkState(eq(TEST_IFACE), eq(false /* up */), eq(NULL_LISTENER)); } + + @Test + public void testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded() { + final String validIfaceName = TEST_TAP_PREFIX + "123"; + tracker.setIncludeTestInterfaces(false); + waitForIdle(); + + final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName); + + assertFalse(isValidTestInterface); + } + + @Test + public void testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid() { + final String invalidIfaceName = "123" + TEST_TAP_PREFIX; + tracker.setIncludeTestInterfaces(true); + waitForIdle(); + + final boolean isValidTestInterface = tracker.isValidTestInterface(invalidIfaceName); + + assertFalse(isValidTestInterface); + } + + @Test + public void testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName() { + final String validIfaceName = TEST_TAP_PREFIX + "123"; + tracker.setIncludeTestInterfaces(true); + waitForIdle(); + + final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName); + + assertTrue(isValidTestInterface); + } } From 27b3e863d5565eec8dbef606e51c90e7d9e330b5 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Thu, 3 Mar 2022 16:19:04 -0800 Subject: [PATCH 848/881] Allowing for null net caps in updateConfiguration Marking NetworkCapabilities as nullable in updateConfiguration and updating where needed to support this. This will allow callers of the ethernet network management updateConfiguration API to use it primarily for setting an ethernet network's IP configuration. Bug: 222565654 Bug: 220017952 Bug: 210485380 Test: atest EthernetServiceTests Change-Id: Ifd908639a00470e599fe1a15487cc6383a56b2f5 --- .../server/ethernet/EthernetNetworkFactory.java | 4 +++- .../android/server/ethernet/EthernetServiceImpl.java | 4 ++-- .../com/android/server/ethernet/EthernetTracker.java | 6 ++++-- .../server/ethernet/EthernetServiceImplTest.java | 12 ++++++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 8ce27a64b1..875fc102c0 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -485,7 +485,9 @@ public class EthernetNetworkFactory extends NetworkFactory { } mIpConfig = ipConfig; - setCapabilities(capabilities); + if (null != capabilities) { + setCapabilities(capabilities); + } // Send an abort callback if a request is filed before the previous one has completed. maybeSendNetworkManagementCallbackForAbort(); // TODO: Update this logic to only do a restart if required. Although a restart may diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 7f77e5e633..9987b3e00c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -237,8 +237,8 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { logIfEthernetNotStarted(); } - private void validateTestCapabilities(@NonNull final NetworkCapabilities nc) { - if (nc.hasTransport(TRANSPORT_TEST)) { + private void validateTestCapabilities(@Nullable final NetworkCapabilities nc) { + if (null != nc && nc.hasTransport(TRANSPORT_TEST)) { return; } throw new IllegalArgumentException( diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 9070a7e090..ea241e1d3f 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -233,7 +233,7 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void updateConfiguration(@NonNull final String iface, @NonNull final IpConfiguration ipConfig, - @NonNull final NetworkCapabilities capabilities, + @Nullable final NetworkCapabilities capabilities, @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities @@ -241,7 +241,9 @@ public class EthernetTracker { } final IpConfiguration localIpConfig = new IpConfiguration(ipConfig); writeIpConfiguration(iface, localIpConfig); - mNetworkCapabilities.put(iface, capabilities); + if (null != capabilities) { + mNetworkCapabilities.put(iface, capabilities); + } mHandler.post(() -> { mFactory.updateInterface(iface, localIpConfig, capabilities, listener); broadcastInterfaceStateChange(iface); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 012f07aca1..e814c84f5b 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -247,6 +247,18 @@ public class EthernetServiceImplTest { verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER)); } + @Test + public void testUpdateConfigurationRejectsTestRequestWithNullCapabilities() { + enableTestInterface(); + final EthernetNetworkUpdateRequest request = + new EthernetNetworkUpdateRequest + .Builder() + .setIpConfiguration(new IpConfiguration()).build(); + assertThrows(IllegalArgumentException.class, () -> { + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER); + }); + } + @Test public void testUpdateConfigurationRejectsInvalidTestRequest() { enableTestInterface(); From 02730cf4214d339ceeb3ae0315b104d78047d738 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Fri, 4 Feb 2022 13:14:13 +0100 Subject: [PATCH 849/881] Fix log message when failing to open bpf maps s/create/open/ Test: TH Change-Id: I7fd1b280ab15aaa0757cfb3afcc20bf377a3bcef --- .../com/android/server/net/NetworkStatsService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index ef6f39a5c0..f8355817bf 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -565,7 +565,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return new BpfMap(UID_COUNTERSET_MAP_PATH, BpfMap.BPF_F_RDWR, U32.class, U8.class); } catch (ErrnoException e) { - Log.wtf(TAG, "Cannot create uid counter set map: " + e); + Log.wtf(TAG, "Cannot open uid counter set map: " + e); return null; } } @@ -576,7 +576,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return new BpfMap(COOKIE_TAG_MAP_PATH, BpfMap.BPF_F_RDWR, CookieTagMapKey.class, CookieTagMapValue.class); } catch (ErrnoException e) { - Log.wtf(TAG, "Cannot create cookie tag map: " + e); + Log.wtf(TAG, "Cannot open cookie tag map: " + e); return null; } } @@ -587,7 +587,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return new BpfMap(STATS_MAP_A_PATH, BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class); } catch (ErrnoException e) { - Log.wtf(TAG, "Cannot create stats map A: " + e); + Log.wtf(TAG, "Cannot open stats map A: " + e); return null; } } @@ -598,7 +598,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return new BpfMap(STATS_MAP_B_PATH, BpfMap.BPF_F_RDWR, StatsMapKey.class, StatsMapValue.class); } catch (ErrnoException e) { - Log.wtf(TAG, "Cannot create stats map B: " + e); + Log.wtf(TAG, "Cannot open stats map B: " + e); return null; } } @@ -609,7 +609,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return new BpfMap(APP_UID_STATS_MAP_PATH, BpfMap.BPF_F_RDWR, UidStatsMapKey.class, StatsMapValue.class); } catch (ErrnoException e) { - Log.wtf(TAG, "Cannot create app uid stats map: " + e); + Log.wtf(TAG, "Cannot open app uid stats map: " + e); return null; } } From db3007caca61beb9fb1c06c5a03bb4baea9728f1 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Thu, 3 Mar 2022 16:07:11 -0800 Subject: [PATCH 850/881] Allowing for null net caps in updateConfiguration Marking NetworkCapabilities as nullable in updateConfiguration and updating where needed to support this. This will allow callers of the ethernet network management updateConfiguration API to use it primarily for setting an ethernet network's IP configuration. Bug: 222565654 Bug: 220017952 Bug: 210485380 Test: atest EthernetNetworkUpdateRequestTest Change-Id: I1f80e950acbd078a6b3378e1fa5f1e4173112e79 --- .../net/EthernetNetworkUpdateRequest.java | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java index a626971105..43f4c40f2d 100644 --- a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java +++ b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java @@ -24,36 +24,52 @@ import android.os.Parcelable; import java.util.Objects; -/** @hide */ +/** + * Represents a request to update an existing Ethernet interface. + * + * @see EthernetManager#updateConfiguration + * + * @hide + */ @SystemApi public final class EthernetNetworkUpdateRequest implements Parcelable { @NonNull private final IpConfiguration mIpConfig; - @NonNull + @Nullable private final NetworkCapabilities mNetworkCapabilities; + /** + * @return the new {@link IpConfiguration}. + */ @NonNull public IpConfiguration getIpConfiguration() { return new IpConfiguration(mIpConfig); } - @NonNull + /** + * Setting the {@link NetworkCapabilities} is optional in {@link EthernetNetworkUpdateRequest}. + * When set to null, the existing NetworkCapabilities are not updated. + * + * @return the new {@link NetworkCapabilities} or null. + */ + @Nullable public NetworkCapabilities getNetworkCapabilities() { - return new NetworkCapabilities(mNetworkCapabilities); + return mNetworkCapabilities == null ? null : new NetworkCapabilities(mNetworkCapabilities); } private EthernetNetworkUpdateRequest(@NonNull final IpConfiguration ipConfig, - @NonNull final NetworkCapabilities networkCapabilities) { + @Nullable final NetworkCapabilities networkCapabilities) { Objects.requireNonNull(ipConfig); - Objects.requireNonNull(networkCapabilities); - mIpConfig = new IpConfiguration(ipConfig); - mNetworkCapabilities = new NetworkCapabilities(networkCapabilities); + mIpConfig = ipConfig; + mNetworkCapabilities = networkCapabilities; } private EthernetNetworkUpdateRequest(@NonNull final Parcel source) { Objects.requireNonNull(source); - mIpConfig = IpConfiguration.CREATOR.createFromParcel(source); - mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source); + mIpConfig = source.readParcelable(IpConfiguration.class.getClassLoader(), + IpConfiguration.class); + mNetworkCapabilities = source.readParcelable(NetworkCapabilities.class.getClassLoader(), + NetworkCapabilities.class); } /** @@ -75,7 +91,8 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { public Builder(@NonNull final EthernetNetworkUpdateRequest request) { Objects.requireNonNull(request); mBuilderIpConfig = new IpConfiguration(request.mIpConfig); - mBuilderNetworkCapabilities = new NetworkCapabilities(request.mNetworkCapabilities); + mBuilderNetworkCapabilities = null == request.mNetworkCapabilities + ? null : new NetworkCapabilities(request.mNetworkCapabilities); } /** @@ -85,7 +102,6 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { */ @NonNull public Builder setIpConfiguration(@NonNull final IpConfiguration ipConfig) { - Objects.requireNonNull(ipConfig); mBuilderIpConfig = new IpConfiguration(ipConfig); return this; } @@ -96,9 +112,8 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { * @return The builder to facilitate chaining. */ @NonNull - public Builder setNetworkCapabilities(@NonNull final NetworkCapabilities nc) { - Objects.requireNonNull(nc); - mBuilderNetworkCapabilities = new NetworkCapabilities(nc); + public Builder setNetworkCapabilities(@Nullable final NetworkCapabilities nc) { + mBuilderNetworkCapabilities = nc == null ? null : new NetworkCapabilities(nc); return this; } @@ -135,8 +150,8 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - mIpConfig.writeToParcel(dest, flags); - mNetworkCapabilities.writeToParcel(dest, flags); + dest.writeParcelable(mIpConfig, flags); + dest.writeParcelable(mNetworkCapabilities, flags); } @Override From faa9fe86b665e90d388e1339e27dac43143ee7d5 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Tue, 8 Mar 2022 17:07:50 +0100 Subject: [PATCH 851/881] Remove restriction that limits updateConfiguration API to Auto Test: TH Change-Id: Ibd1b6493778b98fc765e6eebdfe8f9c1fef29a73 --- framework-t/src/android/net/EthernetManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 72243f9e87..eba51c1148 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -511,7 +511,6 @@ public class EthernetManager { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) - @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) public void updateConfiguration( @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, From f6cc4ca78f605173fb8c36815782cba35ea6410b Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Tue, 8 Mar 2022 13:10:18 +0100 Subject: [PATCH 852/881] Allow all device types to call updateConfiguration Usage of this API should not be limited to Automotive devices as TvSettings also needs to update the IpConfiguration. Test: TH Change-Id: I838a0a8684e9f944801718a4d688666de45f42fb --- .../server/ethernet/EthernetServiceImpl.java | 67 +++++++++++-------- .../ethernet/EthernetServiceImplTest.java | 26 +++++-- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 9987b3e00c..782ee0fad4 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -215,45 +215,34 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { "EthernetServiceImpl"); } - /** - * Validate the state of ethernet for APIs tied to network management. - * - * @param iface the ethernet interface name to operate on. - * @param methodName the name of the calling method. - */ - private void validateNetworkManagementState(@NonNull final String iface, - final @NonNull String methodName) { - Objects.requireNonNull(iface, "Pass a non-null iface."); - Objects.requireNonNull(methodName, "Pass a non-null methodName."); - - // Only bypass the permission/device checks if this is a valid test interface. - if (mTracker.isValidTestInterface(iface)) { - enforceManageTestNetworksPermission(); - Log.i(TAG, "Ethernet network management API used with test interface " + iface); - } else { - enforceAutomotiveDevice(methodName); - enforceNetworkManagementPermission(); - } - logIfEthernetNotStarted(); - } - private void validateTestCapabilities(@Nullable final NetworkCapabilities nc) { - if (null != nc && nc.hasTransport(TRANSPORT_TEST)) { - return; + // For test capabilities, only null or capabilities that include TRANSPORT_TEST are allowed. + if (nc != null && !nc.hasTransport(TRANSPORT_TEST)) { + throw new IllegalArgumentException( + "Updates to test interfaces must have NetworkCapabilities.TRANSPORT_TEST."); } - throw new IllegalArgumentException( - "Updates to test interfaces must have NetworkCapabilities.TRANSPORT_TEST."); } @Override public void updateConfiguration(@NonNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, @Nullable final IEthernetNetworkManagementListener listener) { - validateNetworkManagementState(iface, "updateConfiguration()"); + Objects.requireNonNull(iface); + Objects.requireNonNull(request); + // TODO: rename to throwIfEthernetNotStarted. + logIfEthernetNotStarted(); + if (mTracker.isValidTestInterface(iface)) { + enforceManageTestNetworksPermission(); validateTestCapabilities(request.getNetworkCapabilities()); // TODO: use NetworkCapabilities#restrictCapabilitiesForTestNetwork when available on a // local NetworkCapabilities copy to pass to mTracker.updateConfiguration. + } else { + enforceNetworkManagementPermission(); + if (request.getNetworkCapabilities() != null) { + // only automotive devices are allowed to set the NetworkCapabilities using this API + enforceAutomotiveDevice("updateConfiguration() with non-null capabilities"); + } } // TODO: validate that iface is listed in overlay config_ethernet_interfaces @@ -265,7 +254,17 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { public void connectNetwork(@NonNull final String iface, @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); - validateNetworkManagementState(iface, "connectNetwork()"); + Objects.requireNonNull(iface); + logIfEthernetNotStarted(); + + if (mTracker.isValidTestInterface(iface)) { + enforceManageTestNetworksPermission(); + } else { + // only automotive devices are allowed to use this API. + enforceNetworkManagementPermission(); + enforceAutomotiveDevice("connectNetwork()"); + } + mTracker.connectNetwork(iface, listener); } @@ -273,7 +272,17 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { public void disconnectNetwork(@NonNull final String iface, @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); - validateNetworkManagementState(iface, "disconnectNetwork()"); + Objects.requireNonNull(iface); + logIfEthernetNotStarted(); + + if (mTracker.isValidTestInterface(iface)) { + enforceManageTestNetworksPermission(); + } else { + // only automotive devices are allowed to use this API. + enforceNetworkManagementPermission(); + enforceAutomotiveDevice("disconnectNetwork()"); + } + mTracker.disconnectNetwork(iface, listener); } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index e814c84f5b..175a97d070 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.verify; @@ -55,6 +56,10 @@ public class EthernetServiceImplTest { .setIpConfiguration(new IpConfiguration()) .setNetworkCapabilities(new NetworkCapabilities.Builder().build()) .build(); + private static final EthernetNetworkUpdateRequest UPDATE_REQUEST_WITHOUT_CAPABILITIES = + new EthernetNetworkUpdateRequest.Builder() + .setIpConfiguration(new IpConfiguration()) + .build(); private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @@ -136,13 +141,23 @@ public class EthernetServiceImplTest { } @Test - public void testUpdateConfigurationRejectsWithoutAutomotiveFeature() { + public void testUpdateConfigurationWithCapabilitiesRejectsWithoutAutomotiveFeature() { toggleAutomotiveFeature(false); assertThrows(UnsupportedOperationException.class, () -> { mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST, NULL_LISTENER); }); } + @Test + public void testUpdateConfigurationWithCapabilitiesWithAutomotiveFeature() { + toggleAutomotiveFeature(false); + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST_WITHOUT_CAPABILITIES, + NULL_LISTENER); + verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE), + eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getIpConfiguration()), + eq(UPDATE_REQUEST_WITHOUT_CAPABILITIES.getNetworkCapabilities()), isNull()); + } + @Test public void testConnectNetworkRejectsWithoutAutomotiveFeature() { toggleAutomotiveFeature(false); @@ -248,15 +263,16 @@ public class EthernetServiceImplTest { } @Test - public void testUpdateConfigurationRejectsTestRequestWithNullCapabilities() { + public void testUpdateConfigurationAcceptsTestRequestWithNullCapabilities() { enableTestInterface(); final EthernetNetworkUpdateRequest request = new EthernetNetworkUpdateRequest .Builder() .setIpConfiguration(new IpConfiguration()).build(); - assertThrows(IllegalArgumentException.class, () -> { - mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER); - }); + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, request, NULL_LISTENER); + verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE), + eq(request.getIpConfiguration()), + eq(request.getNetworkCapabilities()), isNull()); } @Test From 038c80551e9f970d8c7c51beacf6079b165c2f2a Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 9 Mar 2022 13:58:28 +0100 Subject: [PATCH 853/881] Rename logIfEthernetNotStarted to throwIfEthernetNotStarted The functions does not log but throws an exception instead. Changing the name to reflect that. Test: TH Change-Id: I6207aababaccc9bc553f7f731e3b8a1d26eb16a1 --- .../android/server/ethernet/EthernetServiceImpl.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 782ee0fad4..89ac6e4816 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -80,7 +80,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mStarted.set(true); } - private void logIfEthernetNotStarted() { + private void throwIfEthernetNotStarted() { if (!mStarted.get()) { throw new IllegalStateException("System isn't ready to change ethernet configurations"); } @@ -111,7 +111,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { */ @Override public void setConfiguration(String iface, IpConfiguration config) { - logIfEthernetNotStarted(); + throwIfEthernetNotStarted(); PermissionUtils.enforceNetworkStackPermission(mContext); if (mTracker.isRestrictedInterface(iface)) { @@ -229,8 +229,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Nullable final IEthernetNetworkManagementListener listener) { Objects.requireNonNull(iface); Objects.requireNonNull(request); - // TODO: rename to throwIfEthernetNotStarted. - logIfEthernetNotStarted(); + throwIfEthernetNotStarted(); if (mTracker.isValidTestInterface(iface)) { enforceManageTestNetworksPermission(); @@ -255,7 +254,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); - logIfEthernetNotStarted(); + throwIfEthernetNotStarted(); if (mTracker.isValidTestInterface(iface)) { enforceManageTestNetworksPermission(); @@ -273,7 +272,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); - logIfEthernetNotStarted(); + throwIfEthernetNotStarted(); if (mTracker.isValidTestInterface(iface)) { enforceManageTestNetworksPermission(); From a4e8e77e24a4921c271231e5a33ed37c48264b41 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 9 Mar 2022 21:37:14 +0100 Subject: [PATCH 854/881] Clean up permission validation in EthernetServiceImpl Test: atest EthernetServiceImplTest Change-Id: I0ca54e09dd98cab348fc855e8a0bf70a703fffed --- .../server/ethernet/EthernetServiceImpl.java | 53 +++++++++---------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 89ac6e4816..50b46845be 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -215,14 +215,31 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { "EthernetServiceImpl"); } - private void validateTestCapabilities(@Nullable final NetworkCapabilities nc) { - // For test capabilities, only null or capabilities that include TRANSPORT_TEST are allowed. + private void maybeValidateTestCapabilities(final String iface, + @Nullable final NetworkCapabilities nc) { + if (!mTracker.isValidTestInterface(iface)) { + return; + } + // For test interfaces, only null or capabilities that include TRANSPORT_TEST are + // allowed. if (nc != null && !nc.hasTransport(TRANSPORT_TEST)) { throw new IllegalArgumentException( "Updates to test interfaces must have NetworkCapabilities.TRANSPORT_TEST."); } } + private void enforceAdminPermission(final String iface, boolean enforceAutomotive, + final String logMessage) { + if (mTracker.isValidTestInterface(iface)) { + enforceManageTestNetworksPermission(); + } else { + enforceNetworkManagementPermission(); + if (enforceAutomotive) { + enforceAutomotiveDevice(logMessage); + } + } + } + @Override public void updateConfiguration(@NonNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, @@ -231,19 +248,11 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Objects.requireNonNull(request); throwIfEthernetNotStarted(); - if (mTracker.isValidTestInterface(iface)) { - enforceManageTestNetworksPermission(); - validateTestCapabilities(request.getNetworkCapabilities()); - // TODO: use NetworkCapabilities#restrictCapabilitiesForTestNetwork when available on a - // local NetworkCapabilities copy to pass to mTracker.updateConfiguration. - } else { - enforceNetworkManagementPermission(); - if (request.getNetworkCapabilities() != null) { - // only automotive devices are allowed to set the NetworkCapabilities using this API - enforceAutomotiveDevice("updateConfiguration() with non-null capabilities"); - } - } // TODO: validate that iface is listed in overlay config_ethernet_interfaces + // only automotive devices are allowed to set the NetworkCapabilities using this API + enforceAdminPermission(iface, request.getNetworkCapabilities() != null, + "updateConfiguration() with non-null capabilities"); + maybeValidateTestCapabilities(iface, request.getNetworkCapabilities()); mTracker.updateConfiguration( iface, request.getIpConfiguration(), request.getNetworkCapabilities(), listener); @@ -256,13 +265,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Objects.requireNonNull(iface); throwIfEthernetNotStarted(); - if (mTracker.isValidTestInterface(iface)) { - enforceManageTestNetworksPermission(); - } else { - // only automotive devices are allowed to use this API. - enforceNetworkManagementPermission(); - enforceAutomotiveDevice("connectNetwork()"); - } + enforceAdminPermission(iface, true, "connectNetwork()"); mTracker.connectNetwork(iface, listener); } @@ -274,13 +277,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { Objects.requireNonNull(iface); throwIfEthernetNotStarted(); - if (mTracker.isValidTestInterface(iface)) { - enforceManageTestNetworksPermission(); - } else { - // only automotive devices are allowed to use this API. - enforceNetworkManagementPermission(); - enforceAutomotiveDevice("disconnectNetwork()"); - } + enforceAdminPermission(iface, true, "connectNetwork()"); mTracker.disconnectNetwork(iface, listener); } From e6c13a7dd01313c44d9418716a58227708bdfd52 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 10 Mar 2022 17:44:49 +0800 Subject: [PATCH 855/881] Rename setUidForeground to noteUidForeground This patch addresses API review about the naming of NetworkStatsManager#setUidForeground and it would be more appropriate to rename it to noteUidForeground. Bug: 222291301 Test: atest FrameworksNetTests Change-Id: I952762872850889609c9808aa6e3cdfc04317806 --- framework-t/src/android/app/usage/NetworkStatsManager.java | 4 ++-- framework-t/src/android/net/INetworkStatsService.aidl | 2 +- service-t/src/com/android/server/net/NetworkStatsService.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework-t/src/android/app/usage/NetworkStatsManager.java b/framework-t/src/android/app/usage/NetworkStatsManager.java index ca080ce4c6..bf518b2d5a 100644 --- a/framework-t/src/android/app/usage/NetworkStatsManager.java +++ b/framework-t/src/android/app/usage/NetworkStatsManager.java @@ -1061,9 +1061,9 @@ public class NetworkStatsManager { @RequiresPermission(anyOf = { NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) - public void setUidForeground(int uid, boolean uidForeground) { + public void noteUidForeground(int uid, boolean uidForeground) { try { - mService.setUidForeground(uid, uidForeground); + mService.noteUidForeground(uid, uidForeground); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/framework-t/src/android/net/INetworkStatsService.aidl b/framework-t/src/android/net/INetworkStatsService.aidl index efe626d3c9..c86f7fd089 100644 --- a/framework-t/src/android/net/INetworkStatsService.aidl +++ b/framework-t/src/android/net/INetworkStatsService.aidl @@ -91,7 +91,7 @@ interface INetworkStatsService { in INetworkStatsProvider provider); /** Mark given UID as being in foreground for stats purposes. */ - void setUidForeground(int uid, boolean uidForeground); + void noteUidForeground(int uid, boolean uidForeground); /** Advise persistence threshold; may be overridden internally. */ void advisePersistThreshold(long thresholdBytes); diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index ef6f39a5c0..72eff87c16 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -1194,7 +1194,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @VisibleForTesting - public void setUidForeground(int uid, boolean uidForeground) { + public void noteUidForeground(int uid, boolean uidForeground) { PermissionUtils.enforceNetworkStackPermission(mContext); synchronized (mStatsLock) { final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT; From d695111dc9bb0879b00b776b1a084c8ef79344c1 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 11 Mar 2022 01:09:34 +0800 Subject: [PATCH 856/881] Let docs tool to list the newly-visible IntDef values Some *_ALL constants are exposed in T and they should be mentioned in documentation. Because there are already defined InDef values for this kind of constants. Thus, remove the list in the javadoc and leave these up to the doc tool to list the InDef values. Bug: 222291452 Test: m doc-comment-check-docs Change-Id: Ibbaee5389a85bb3d696a518deea0897845553bfa --- framework-t/src/android/net/NetworkStats.java | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/framework-t/src/android/net/NetworkStats.java b/framework-t/src/android/net/NetworkStats.java index f681ba1c38..06f2a621bc 100644 --- a/framework-t/src/android/net/NetworkStats.java +++ b/framework-t/src/android/net/NetworkStats.java @@ -327,16 +327,11 @@ public final class NetworkStats implements Parcelable, Iterable Date: Mon, 24 Jan 2022 03:54:55 +0000 Subject: [PATCH 857/881] Build ethernet service into service-connectivity-tiramisu-pre-jarjar. Along with ethernet service is going to be moved into Connectivity module, this CL contains the corresponding changes as below: 1. deprecate the etherent-service lib and create a new filegroup: When the ethernet mainline code migration completes, ethernet-service lib won't be kept any more, instead the ethernet service should be started from ConnectivityServiceInitializer. So deprecate the current ethernet-service lib and cleanup the usages on other places later. Create a new filegroup which includes all ethernet service code, that will be built into service-connectivity-tiramisu-pre-jarjar. 2. Move the implementation of starting ethernet service: ConnectivityServiceInitializer should take responsibility to start ethernet service and EthernetTracker on boot phase. Move this code to ConnectivityServiceInitializer and remove the current onStart and onBootPhase implemenation. 3. Move below ethernet service related config resources: - config_ethernet_tcp_buffers - config_ethernet_interfaces - config_ethernet_iface_regex Move the definition of these resource from frameworks/base/core to p/m/Connectivity/service/ServiceConnectivityResources, and import the ServiceConnectivityResources lib to adapt the ethernet update. 4. Update the EthernetServiceTests dependencies and refactor the code which uses ConnectivityResources instead of internal Resource to make the tests pass. Bug: 210586283 Test: m Test: atest FrameworksNetTests atest EthernetServiceTests Change-Id: I0bbecfb64f720213ee2b02417bc8357ccf4725b6 Merged-In: I0bbecfb64f720213ee2b02417bc8357ccf4725b6 --- .../ethernet/EthernetNetworkFactory.java | 29 ++++++++- .../server/ethernet/EthernetService.java | 38 +++-------- .../server/ethernet/EthernetTracker.java | 64 +++++++++++++++++-- tests/ethernet/Android.bp | 13 +++- .../ethernet/EthernetNetworkFactoryTest.java | 5 +- .../server/ethernet/EthernetTrackerTest.java | 13 ++-- 6 files changed, 116 insertions(+), 46 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 875fc102c0..ce0d77c18e 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -19,7 +19,9 @@ package com.android.server.ethernet; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.content.res.Resources; import android.net.ConnectivityManager; +import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.EthernetNetworkSpecifier; import android.net.IEthernetNetworkManagementListener; @@ -49,6 +51,7 @@ import android.util.AndroidRuntimeException; import android.util.Log; import android.util.SparseArray; +import com.android.connectivity.resources.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IndentingPrintWriter; import com.android.net.module.util.InterfaceParams; @@ -69,6 +72,8 @@ public class EthernetNetworkFactory extends NetworkFactory { private final static int NETWORK_SCORE = 70; private static final String NETWORK_TYPE = "Ethernet"; + private static final String LEGACY_TCP_BUFFER_SIZES = + "524288,1048576,3145728,524288,1048576,2097152"; private final ConcurrentHashMap mTrackingInterfaces = new ConcurrentHashMap<>(); @@ -94,6 +99,27 @@ public class EthernetNetworkFactory extends NetworkFactory { public InterfaceParams getNetworkInterfaceByName(String name) { return InterfaceParams.getByName(name); } + + // TODO: remove legacy resource fallback after migrating its overlays. + private String getPlatformTcpBufferSizes(Context context) { + final Resources r = context.getResources(); + final int resId = r.getIdentifier("config_ethernet_tcp_buffers", "string", + context.getPackageName()); + return r.getString(resId); + } + + public String getTcpBufferSizesFromResource(Context context) { + final String tcpBufferSizes; + final String platformTcpBufferSizes = getPlatformTcpBufferSizes(context); + if (!LEGACY_TCP_BUFFER_SIZES.equals(platformTcpBufferSizes)) { + // Platform resource is not the historical default: use the overlay. + tcpBufferSizes = platformTcpBufferSizes; + } else { + final ConnectivityResources resources = new ConnectivityResources(context); + tcpBufferSizes = resources.get().getString(R.string.config_ethernet_tcp_buffers); + } + return tcpBufferSizes; + } } public static class ConfigurationException extends AndroidRuntimeException { @@ -518,8 +544,7 @@ public class EthernetNetworkFactory extends NetworkFactory { mIpClientCallback.awaitIpClientStart(); if (sTcpBufferSizes == null) { - sTcpBufferSizes = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_tcp_buffers); + sTcpBufferSizes = mDeps.getTcpBufferSizesFromResource(mContext); } provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes); } diff --git a/service-t/src/com/android/server/ethernet/EthernetService.java b/service-t/src/com/android/server/ethernet/EthernetService.java index e6fee9e7bc..d405fd59fb 100644 --- a/service-t/src/com/android/server/ethernet/EthernetService.java +++ b/service-t/src/com/android/server/ethernet/EthernetService.java @@ -21,45 +21,27 @@ import android.net.INetd; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; -import android.util.Log; -import com.android.server.SystemService; import java.util.Objects; -public final class EthernetService extends SystemService { - +// TODO: consider renaming EthernetServiceImpl to EthernetService and deleting this file. +public final class EthernetService { private static final String TAG = "EthernetService"; private static final String THREAD_NAME = "EthernetServiceThread"; - private final EthernetServiceImpl mImpl; - public EthernetService(Context context) { - super(context); - final HandlerThread handlerThread = new HandlerThread(THREAD_NAME); - handlerThread.start(); - final Handler handler = handlerThread.getThreadHandler(); - final EthernetNetworkFactory factory = new EthernetNetworkFactory(handler, context); - mImpl = new EthernetServiceImpl( - context, handler, - new EthernetTracker(context, handler, factory, getNetd(context))); - } - - private INetd getNetd(Context context) { + private static INetd getNetd(Context context) { final INetd netd = INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)); Objects.requireNonNull(netd, "could not get netd instance"); return netd; } - @Override - public void onStart() { - Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE); - publishBinderService(Context.ETHERNET_SERVICE, mImpl); - } - - @Override - public void onBootPhase(int phase) { - if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { - mImpl.start(); - } + public static EthernetServiceImpl create(Context context) { + final HandlerThread handlerThread = new HandlerThread(THREAD_NAME); + handlerThread.start(); + final Handler handler = new Handler(handlerThread.getLooper()); + final EthernetNetworkFactory factory = new EthernetNetworkFactory(handler, context); + return new EthernetServiceImpl(context, handler, + new EthernetTracker(context, handler, factory, getNetd(context))); } } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index ea241e1d3f..1b696a4587 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -23,6 +23,8 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility.PACK import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.content.res.Resources; +import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.IEthernetServiceListener; import android.net.IEthernetNetworkManagementListener; @@ -80,6 +82,7 @@ public class EthernetTracker { private static final boolean DBG = EthernetNetworkFactory.DBG; private static final String TEST_IFACE_REGEXP = TEST_TAP_PREFIX + "\\d+"; + private static final String LEGACY_IFACE_REGEXP = "eth\\d"; /** * Interface names we track. This is a product-dependent regular expression, plus, @@ -102,6 +105,7 @@ public class EthernetTracker { private final Handler mHandler; private final EthernetNetworkFactory mFactory; private final EthernetConfigStore mConfigStore; + private final Dependencies mDeps; private final RemoteCallbackList mListeners = new RemoteCallbackList<>(); @@ -123,19 +127,72 @@ public class EthernetTracker { } } + public static class Dependencies { + // TODO: remove legacy resource fallback after migrating its overlays. + private String getPlatformRegexResource(Context context) { + final Resources r = context.getResources(); + final int resId = + r.getIdentifier("config_ethernet_iface_regex", "string", context.getPackageName()); + return r.getString(resId); + } + + // TODO: remove legacy resource fallback after migrating its overlays. + private String[] getPlatformInterfaceConfigs(Context context) { + final Resources r = context.getResources(); + final int resId = r.getIdentifier("config_ethernet_interfaces", "array", + context.getPackageName()); + return r.getStringArray(resId); + } + + public String getInterfaceRegexFromResource(Context context) { + final String platformRegex = getPlatformRegexResource(context); + final String match; + if (!LEGACY_IFACE_REGEXP.equals(platformRegex)) { + // Platform resource is not the historical default: use the overlay + match = platformRegex; + } else { + final ConnectivityResources resources = new ConnectivityResources(context); + match = resources.get().getString( + com.android.connectivity.resources.R.string.config_ethernet_iface_regex); + } + return match; + } + + public String[] getInterfaceConfigFromResource(Context context) { + final String[] platformInterfaceConfigs = getPlatformInterfaceConfigs(context); + final String[] interfaceConfigs; + if (platformInterfaceConfigs.length != 0) { + // Platform resource is not the historical default: use the overlay + interfaceConfigs = platformInterfaceConfigs; + } else { + final ConnectivityResources resources = new ConnectivityResources(context); + interfaceConfigs = resources.get().getStringArray( + com.android.connectivity.resources.R.array.config_ethernet_interfaces); + } + return interfaceConfigs; + } + } + EthernetTracker(@NonNull final Context context, @NonNull final Handler handler, @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd) { + this(context, handler, factory, netd, new Dependencies()); + } + + @VisibleForTesting + EthernetTracker(@NonNull final Context context, @NonNull final Handler handler, + @NonNull final EthernetNetworkFactory factory, @NonNull final INetd netd, + @NonNull final Dependencies deps) { mContext = context; mHandler = handler; mFactory = factory; mNetd = netd; + mDeps = deps; // Interface match regex. updateIfaceMatchRegexp(); // Read default Ethernet interface configuration from resources - final String[] interfaceConfigs = context.getResources().getStringArray( - com.android.internal.R.array.config_ethernet_interfaces); + final String[] interfaceConfigs = mDeps.getInterfaceConfigFromResource(context); for (String strConfig : interfaceConfigs) { parseEthernetConfig(strConfig); } @@ -735,8 +792,7 @@ public class EthernetTracker { } private void updateIfaceMatchRegexp() { - final String match = mContext.getResources().getString( - com.android.internal.R.string.config_ethernet_iface_regex); + final String match = mDeps.getInterfaceRegexFromResource(mContext); mIfaceMatch = mIncludeTestInterfaces ? "(" + match + "|" + TEST_IFACE_REGEXP + ")" : match; diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp index 28b13c5243..6cfebdcc83 100644 --- a/tests/ethernet/Android.bp +++ b/tests/ethernet/Android.bp @@ -17,10 +17,17 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +// TODO: merge the tests into service-connectivity tests after +// ethernet service migration completes. So far just import the +// ethernet service source to fix the dependencies. android_test { name: "EthernetServiceTests", - srcs: ["java/**/*.java"], + srcs: [ + ":ethernet-service-updatable-sources", + ":services.connectivity-ethernet-sources", + "java/**/*.java", + ], certificate: "platform", platform_apis: true, @@ -29,11 +36,13 @@ android_test { "android.test.runner", "android.test.base", "android.test.mock", + "framework-connectivity.impl", + "framework-connectivity-t.impl", + "ServiceConnectivityResources", ], static_libs: [ "androidx.test.rules", - "ethernet-service", "frameworks-base-testutils", "mockito-target-minus-junit4", "net-tests-utils", diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 61425bf171..501324a2fe 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -63,7 +63,7 @@ import android.util.Pair; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.R; +import com.android.connectivity.resources.R; import com.android.net.module.util.InterfaceParams; import com.android.testutils.DevSdkIgnoreRule; @@ -174,8 +174,7 @@ public class EthernetNetworkFactoryTest { } private void setupContext() { - when(mContext.getResources()).thenReturn(mResources); - when(mResources.getString(R.string.config_ethernet_tcp_buffers)).thenReturn(""); + when(mDeps.getTcpBufferSizesFromResource(eq(mContext))).thenReturn(""); } @After diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index d86cc0f60d..ef70d94391 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -27,7 +27,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -48,7 +47,7 @@ import android.os.RemoteException; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.R; +import com.android.connectivity.resources.R; import com.android.testutils.HandlerUtils; import org.junit.After; @@ -73,7 +72,7 @@ public class EthernetTrackerTest { @Mock private Context mContext; @Mock private EthernetNetworkFactory mFactory; @Mock private INetd mNetd; - @Mock Resources mResources; + @Mock private EthernetTracker.Dependencies mDeps; @Before public void setUp() throws RemoteException { @@ -83,7 +82,8 @@ public class EthernetTrackerTest { when(mNetd.interfaceGetList()).thenReturn(new String[0]); mHandlerThread = new HandlerThread(THREAD_NAME); mHandlerThread.start(); - tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd); + tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd, + mDeps); } @After @@ -92,9 +92,8 @@ public class EthernetTrackerTest { } private void initMockResources() { - doReturn("").when(mResources).getString(R.string.config_ethernet_iface_regex); - doReturn(new String[0]).when(mResources).getStringArray(R.array.config_ethernet_interfaces); - doReturn(mResources).when(mContext).getResources(); + when(mDeps.getInterfaceRegexFromResource(eq(mContext))).thenReturn(""); + when(mDeps.getInterfaceConfigFromResource(eq(mContext))).thenReturn(new String[0]); } private void waitForIdle() { From 3574a866168571842178956ff3cf597c63b3d084 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Tue, 28 Dec 2021 09:16:09 +0000 Subject: [PATCH 858/881] Split out the ethernet API surface and use framework-connectivity-t Ethernet framework and service source code is going to be moved to Connectivity mainline module, this CL contains below corresponding changes to adapt the migration in f/b side: 1. Split out ethernet module-lib APIs to Connectivity module. Add the ethernet resource filegroup to tiramisu-updatable-sources filegroup as well, build them together. Also update the module-lib and system api txt to reflect the APIs change. Remove the hidden APIs which are moved to Connectivity module. This removal fixes the api inconsistent issue with Tethering/apex/hidden/. 2. Remove EthernetService from SystemServer which will be registered from ConnectivityServiceInitializer. 3. Replace the BackgroundThread class(imported from f/b/core/java) with the one in the modules-utils-backgroundthread lib, which is visible to Connectivity module. Bug: 210586283 Test: m Test: atest FrameworksNetTests EthernetServiceTests Change-Id: I3e13cb9c0e348333af295c2537d459aa6700ff17 Merged-In: I1956848d3248cc56e9841d221e5e4c160bed65a4 --- framework-t/Sources.bp | 6 +++--- ...nectivityFrameworkInitializerTiramisu.java | 14 ++++++++++++-- .../src/android/net/EthernetManager.java | 2 +- service-t/Sources.bp | 8 ++++---- .../android/server/net/IpConfigStoreTest.java | 19 +++++++++---------- 5 files changed, 29 insertions(+), 20 deletions(-) rename {services/tests/servicestests/src => tests/unit/java}/com/android/server/net/IpConfigStoreTest.java (92%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 66527802a0..217a1f67c3 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -154,17 +154,17 @@ filegroup { ], } +// TODO: remove this empty filegroup. filegroup { name: "framework-connectivity-tiramisu-sources", - srcs: [ - ":framework-connectivity-ethernet-sources", - ], + srcs: [], visibility: ["//frameworks/base"], } filegroup { name: "framework-connectivity-tiramisu-updatable-sources", srcs: [ + ":framework-connectivity-ethernet-sources", ":framework-connectivity-ipsec-sources", ":framework-connectivity-netstats-sources", ":framework-connectivity-nsd-sources", diff --git a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java index 9bffbfb27a..61b34d0bcf 100644 --- a/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java +++ b/framework-t/src/android/net/ConnectivityFrameworkInitializerTiramisu.java @@ -34,8 +34,9 @@ public final class ConnectivityFrameworkInitializerTiramisu { private ConnectivityFrameworkInitializerTiramisu() {} /** - * Called by {@link SystemServiceRegistry}'s static initializer and registers nsd services to - * {@link Context}, so that {@link Context#getSystemService} can return them. + * Called by {@link SystemServiceRegistry}'s static initializer and registers NetworkStats, nsd, + * ipsec and ethernet services to {@link Context}, so that {@link Context#getSystemService} can + * return them. * * @throws IllegalStateException if this is called anywhere besides * {@link SystemServiceRegistry}. @@ -68,5 +69,14 @@ public final class ConnectivityFrameworkInitializerTiramisu { return new NetworkStatsManager(context, service); } ); + + SystemServiceRegistry.registerContextAwareService( + Context.ETHERNET_SERVICE, + EthernetManager.class, + (context, serviceBinder) -> { + IEthernetManager service = IEthernetManager.Stub.asInterface(serviceBinder); + return new EthernetManager(context, service); + } + ); } } diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index eba51c1148..793f28d5aa 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -33,7 +33,7 @@ import android.os.Build; import android.os.RemoteException; import com.android.internal.annotations.GuardedBy; -import com.android.internal.os.BackgroundThread; +import com.android.modules.utils.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 5100e7c5b9..4b799c599b 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -102,17 +102,16 @@ filegroup { ], path: "src", visibility: [ - "//frameworks/opt/net/ethernet", + "//frameworks/opt/net/ethernet/tests", ], } // Connectivity-T common libraries. +// TODO: remove this empty filegroup. filegroup { name: "services.connectivity-tiramisu-sources", - srcs: [ - ":services.connectivity-ethernet-sources", - ], + srcs: [], path: "src", visibility: ["//frameworks/base/services/core"], } @@ -120,6 +119,7 @@ filegroup { filegroup { name: "services.connectivity-tiramisu-updatable-sources", srcs: [ + ":services.connectivity-ethernet-sources", ":services.connectivity-ipsec-sources", ":services.connectivity-netstats-sources", ":services.connectivity-nsd-sources", diff --git a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java similarity index 92% rename from services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java rename to tests/unit/java/com/android/server/net/IpConfigStoreTest.java index 2f771260ac..ad0be5862c 100644 --- a/services/tests/servicestests/src/com/android/server/net/IpConfigStoreTest.java +++ b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java @@ -48,10 +48,16 @@ import java.util.Arrays; */ @RunWith(AndroidJUnit4.class) public class IpConfigStoreTest { + private static final int KEY_CONFIG = 17; + private static final String IFACE_1 = "eth0"; + private static final String IFACE_2 = "eth1"; + private static final String IP_ADDR_1 = "192.168.1.10/24"; + private static final String IP_ADDR_2 = "192.168.1.20/24"; + private static final String DNS_IP_ADDR_1 = "1.2.3.4"; + private static final String DNS_IP_ADDR_2 = "5.6.7.8"; @Test public void backwardCompatibility2to3() throws IOException { - final int KEY_CONFIG = 17; ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); DataOutputStream outputStream = new DataOutputStream(byteStream); @@ -73,13 +79,6 @@ public class IpConfigStoreTest { @Test public void staticIpMultiNetworks() throws Exception { - final String IFACE_1 = "eth0"; - final String IFACE_2 = "eth1"; - final String IP_ADDR_1 = "192.168.1.10/24"; - final String IP_ADDR_2 = "192.168.1.20/24"; - final String DNS_IP_ADDR_1 = "1.2.3.4"; - final String DNS_IP_ADDR_2 = "5.6.7.8"; - final ArrayList dnsServers = new ArrayList<>(); dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_1)); dnsServers.add(InetAddresses.parseNumericAddress(DNS_IP_ADDR_2)); @@ -144,11 +143,11 @@ public class IpConfigStoreTest { /** Synchronously writes into given byte steam */ private static class MockedDelayedDiskWrite extends DelayedDiskWrite { - final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream(); @Override public void write(String filePath, Writer w) { - DataOutputStream outputStream = new DataOutputStream(byteStream); + DataOutputStream outputStream = new DataOutputStream(mByteStream); try { w.onWriteCalled(outputStream); From d9c8223109928407b67d1f8cc5f216bae4004471 Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 8 Mar 2022 18:05:14 -0800 Subject: [PATCH 859/881] Cleaning EthernetNetworkFactoryTest Unprovisioned Clearing up the EthernetNetworkFactoryTest unprovisioned helped method a bit to accomplish the same thing with fewer lines of code and not rely on the ref count to stop an interface. Bug: 197548738 Test: atest EthernetServiceTests Change-Id: I0fb80b569b6f59ee82fbd528ffad044278ab80c8 --- .../ethernet/EthernetNetworkFactoryTest.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 61425bf171..28fcf3e80e 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -280,19 +280,13 @@ public class EthernetNetworkFactoryTest { // creates an unprovisioned interface private void createUnprovisionedInterface(String iface) throws Exception { - // the only way to create an unprovisioned interface is by calling needNetworkFor - // followed by releaseNetworkFor which will stop the NetworkAgent and IpClient. When - // EthernetNetworkFactory#updateInterfaceLinkState(iface, true) is called, the interface - // is automatically provisioned even if nobody has ever called needNetworkFor + // To create an unprovisioned interface, provision and then "stop" it, i.e. stop its + // NetworkAgent and IpClient. One way this can be done is by provisioning an interface and + // then calling onNetworkUnwanted. createAndVerifyProvisionedInterface(iface); - // Interface is already provisioned, so startProvisioning / register should not be called - // again - mNetFactory.needNetworkFor(createDefaultRequest()); - verify(mIpClient, never()).startProvisioning(any()); - verify(mNetworkAgent, never()).register(); - - mNetFactory.releaseNetworkFor(createDefaultRequest()); + mNetworkAgent.getCallbacks().onNetworkUnwanted(); + mLooper.dispatchAll(); verifyStop(); clearInvocations(mIpClient); From 6e429bec00507a82aadfdc2490797e21b3a3b520 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 4 Mar 2022 15:03:36 +0800 Subject: [PATCH 860/881] [DU04-2]Appropriate changes to the NetworkPolicyManager API Divide the NetworkPolicyManager API notifyStatsProviderWarningOrLimitReached into the following two APIs: 1. notifyStatsProviderWarningReached() 2. notifyStatsProviderLimitReached() Bug: 216474563 Test: atest NetworkStatsServiceTest NetworkPolicyManagerTest NetworkPolicyManagerServiceTest OffloadControllerTest Change-Id: Ic413eb532b5e24d4a7e2afabdcf643ab6607b1ed --- .../provider/INetworkStatsProviderCallback.aidl | 3 ++- .../net/netstats/provider/NetworkStatsProvider.java | 6 +++--- .../com/android/server/net/NetworkStatsService.java | 13 ++++++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl b/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl index 7eaa01e262..01ff02dfc5 100644 --- a/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl +++ b/framework-t/src/android/net/netstats/provider/INetworkStatsProviderCallback.aidl @@ -26,6 +26,7 @@ import android.net.NetworkStats; oneway interface INetworkStatsProviderCallback { void notifyStatsUpdated(int token, in NetworkStats ifaceStats, in NetworkStats uidStats); void notifyAlertReached(); - void notifyWarningOrLimitReached(); + void notifyWarningReached(); + void notifyLimitReached(); void unregister(); } diff --git a/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java b/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java index 23fc06927e..d37a53dbf1 100644 --- a/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java +++ b/framework-t/src/android/net/netstats/provider/NetworkStatsProvider.java @@ -152,19 +152,19 @@ public abstract class NetworkStatsProvider { try { // Reuse the code path to notify warning reached with limit reached // since framework handles them in the same way. - getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); + getProviderCallbackBinderOrThrow().notifyWarningReached(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } } /** - * Notify system that the quota set by {@link #onSetLimit} or limit set by + * Notify system that the limit set by {@link #onSetLimit} or limit set by * {@link #onSetWarningAndLimit} has been reached. */ public void notifyLimitReached() { try { - getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached(); + getProviderCallbackBinderOrThrow().notifyLimitReached(); } catch (RemoteException e) { e.rethrowAsRuntimeException(); } diff --git a/service-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java index f8355817bf..e8827d8032 100644 --- a/service-t/src/com/android/server/net/NetworkStatsService.java +++ b/service-t/src/com/android/server/net/NetworkStatsService.java @@ -2393,10 +2393,17 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void notifyWarningOrLimitReached() { - Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); + public void notifyWarningReached() { + Log.d(TAG, mTag + ": notifyWarningReached"); BinderUtils.withCleanCallingIdentity(() -> - mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached()); + mNetworkPolicyManager.notifyStatsProviderWarningReached()); + } + + @Override + public void notifyLimitReached() { + Log.d(TAG, mTag + ": notifyLimitReached"); + BinderUtils.withCleanCallingIdentity(() -> + mNetworkPolicyManager.notifyStatsProviderLimitReached()); } @Override From 9b58f89dc87d2f836671a3376f9687c21fcabd7a Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Mon, 14 Mar 2022 17:30:18 +0100 Subject: [PATCH 861/881] Add support for Nullable IpConfiguration Test: atest EthernetServiceTests Change-Id: I6b415ffb2f5825a9dffda1366b60c1e0d26f4e64 --- .../ethernet/EthernetNetworkFactory.java | 11 +++++---- .../server/ethernet/EthernetTracker.java | 11 ++++++--- .../ethernet/EthernetNetworkFactoryTest.java | 24 +++++++++++++++++++ .../ethernet/EthernetServiceImplTest.java | 13 ++++++++++ 4 files changed, 52 insertions(+), 7 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index ce0d77c18e..ef3abbaec0 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -233,7 +233,8 @@ public class EthernetNetworkFactory extends NetworkFactory { * Update a network's configuration and restart it if necessary. * * @param ifaceName the interface name of the network to be updated. - * @param ipConfig the desired {@link IpConfiguration} for the given network. + * @param ipConfig the desired {@link IpConfiguration} for the given network or null. If + * {@code null} is passed, the existing IpConfiguration is not updated. * @param capabilities the desired {@link NetworkCapabilities} for the given network. If * {@code null} is passed, then the network's current * {@link NetworkCapabilities} will be used in support of existing APIs as @@ -243,7 +244,7 @@ public class EthernetNetworkFactory extends NetworkFactory { */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected void updateInterface(@NonNull final String ifaceName, - @NonNull final IpConfiguration ipConfig, + @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, @Nullable final IEthernetNetworkManagementListener listener) { if (!hasInterface(ifaceName)) { @@ -499,7 +500,7 @@ public class EthernetNetworkFactory extends NetworkFactory { mLegacyType = getLegacyType(mCapabilities); } - void updateInterface(@NonNull final IpConfiguration ipConfig, + void updateInterface(@Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { @@ -510,7 +511,9 @@ public class EthernetNetworkFactory extends NetworkFactory { ); } - mIpConfig = ipConfig; + if (null != ipConfig){ + mIpConfig = ipConfig; + } if (null != capabilities) { setCapabilities(capabilities); } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 1b696a4587..074c81bcb0 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -289,15 +289,20 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void updateConfiguration(@NonNull final String iface, - @NonNull final IpConfiguration ipConfig, + @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities + ", ipConfig: " + ipConfig); } - final IpConfiguration localIpConfig = new IpConfiguration(ipConfig); - writeIpConfiguration(iface, localIpConfig); + + final IpConfiguration localIpConfig = ipConfig == null + ? null : new IpConfiguration(ipConfig); + if (ipConfig != null) { + writeIpConfiguration(iface, localIpConfig); + } + if (null != capabilities) { mNetworkCapabilities.put(iface, capabilities); } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 501324a2fe..726833f8ee 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -776,4 +776,28 @@ public class EthernetNetworkFactoryTest { verifyNoStopOrStart(); assertFailedListener(listener, "can't be updated as it is not available"); } + + @Test + public void testUpdateInterfaceWithNullIpConfiguration() throws Exception { + initEthernetNetworkFactory(); + createAndVerifyProvisionedInterface(TEST_IFACE); + + final IpConfiguration initialIpConfig = createStaticIpConfig(); + mNetFactory.updateInterface(TEST_IFACE, initialIpConfig, null /*capabilities*/, + null /*listener*/); + triggerOnProvisioningSuccess(); + verifyRestart(initialIpConfig); + + // TODO: have verifyXyz functions clear invocations. + clearInvocations(mDeps); + clearInvocations(mIpClient); + clearInvocations(mNetworkAgent); + + + // verify that sending a null ipConfig does not update the current ipConfig. + mNetFactory.updateInterface(TEST_IFACE, null /*ipConfig*/, null /*capabilities*/, + null /*listener*/); + triggerOnProvisioningSuccess(); + verifyRestart(initialIpConfig); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 175a97d070..2131f7fcdb 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -60,6 +60,10 @@ public class EthernetServiceImplTest { new EthernetNetworkUpdateRequest.Builder() .setIpConfiguration(new IpConfiguration()) .build(); + private static final EthernetNetworkUpdateRequest UPDATE_REQUEST_WITHOUT_IP_CONFIG = + new EthernetNetworkUpdateRequest.Builder() + .setNetworkCapabilities(new NetworkCapabilities.Builder().build()) + .build(); private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @@ -275,6 +279,15 @@ public class EthernetServiceImplTest { eq(request.getNetworkCapabilities()), isNull()); } + @Test + public void testUpdateConfigurationAcceptsRequestWithNullIpConfiguration() { + mEthernetServiceImpl.updateConfiguration(TEST_IFACE, UPDATE_REQUEST_WITHOUT_IP_CONFIG, + NULL_LISTENER); + verify(mEthernetTracker).updateConfiguration(eq(TEST_IFACE), + eq(UPDATE_REQUEST_WITHOUT_IP_CONFIG.getIpConfiguration()), + eq(UPDATE_REQUEST_WITHOUT_IP_CONFIG.getNetworkCapabilities()), isNull()); + } + @Test public void testUpdateConfigurationRejectsInvalidTestRequest() { enableTestInterface(); From 72155988527c6b95e8e6cb9f259c541b02a06703 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Mon, 14 Mar 2022 18:58:07 +0100 Subject: [PATCH 862/881] Add Nullable IpConfiguration to ethernet update request This is not currently used by anyone, but will allow us to only update NetworkCapabilities in the future. This could be useful for testing. Test: atest EthernetServiceTests Bug: 220017952 Change-Id: I9697399bad2bfe66c6f328064be75f4dfa10af81 --- .../net/EthernetNetworkUpdateRequest.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java index 43f4c40f2d..1691942c36 100644 --- a/framework-t/src/android/net/EthernetNetworkUpdateRequest.java +++ b/framework-t/src/android/net/EthernetNetworkUpdateRequest.java @@ -33,17 +33,20 @@ import java.util.Objects; */ @SystemApi public final class EthernetNetworkUpdateRequest implements Parcelable { - @NonNull + @Nullable private final IpConfiguration mIpConfig; @Nullable private final NetworkCapabilities mNetworkCapabilities; /** - * @return the new {@link IpConfiguration}. + * Setting the {@link IpConfiguration} is optional in {@link EthernetNetworkUpdateRequest}. + * When set to null, the existing IpConfiguration is not updated. + * + * @return the new {@link IpConfiguration} or null. */ - @NonNull + @Nullable public IpConfiguration getIpConfiguration() { - return new IpConfiguration(mIpConfig); + return mIpConfig == null ? null : new IpConfiguration(mIpConfig); } /** @@ -57,9 +60,8 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { return mNetworkCapabilities == null ? null : new NetworkCapabilities(mNetworkCapabilities); } - private EthernetNetworkUpdateRequest(@NonNull final IpConfiguration ipConfig, + private EthernetNetworkUpdateRequest(@Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities networkCapabilities) { - Objects.requireNonNull(ipConfig); mIpConfig = ipConfig; mNetworkCapabilities = networkCapabilities; } @@ -90,7 +92,8 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { */ public Builder(@NonNull final EthernetNetworkUpdateRequest request) { Objects.requireNonNull(request); - mBuilderIpConfig = new IpConfiguration(request.mIpConfig); + mBuilderIpConfig = null == request.mIpConfig + ? null : new IpConfiguration(request.mIpConfig); mBuilderNetworkCapabilities = null == request.mNetworkCapabilities ? null : new NetworkCapabilities(request.mNetworkCapabilities); } @@ -101,8 +104,8 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { * @return The builder to facilitate chaining. */ @NonNull - public Builder setIpConfiguration(@NonNull final IpConfiguration ipConfig) { - mBuilderIpConfig = new IpConfiguration(ipConfig); + public Builder setIpConfiguration(@Nullable final IpConfiguration ipConfig) { + mBuilderIpConfig = ipConfig == null ? null : new IpConfiguration(ipConfig); return this; } @@ -119,9 +122,16 @@ public final class EthernetNetworkUpdateRequest implements Parcelable { /** * Build {@link EthernetNetworkUpdateRequest} return the current update request. + * + * @throws IllegalStateException when both mBuilderNetworkCapabilities and mBuilderIpConfig + * are null. */ @NonNull public EthernetNetworkUpdateRequest build() { + if (mBuilderIpConfig == null && mBuilderNetworkCapabilities == null) { + throw new IllegalStateException( + "Cannot construct an empty EthernetNetworkUpdateRequest"); + } return new EthernetNetworkUpdateRequest(mBuilderIpConfig, mBuilderNetworkCapabilities); } } From 77a3a8408b04496241e8695d4afd88c057bc8826 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 16 Mar 2022 11:31:06 +0100 Subject: [PATCH 863/881] Change Ethernet API to use OutcomeReceiver This change addresses API review feedback. In addition, it changes the returned result from Network to the interface name. The current API returning a Network object is racy and cannot be implemented correctly. Users should instead use the ConnectivityManager#requestNetwork() API to get hold of the Network for a given interface. Bug: 220017952 Test: TH Change-Id: I7c46545a47034be409071c2ec007d9e1480c6ed0 --- framework-t/Sources.bp | 2 +- .../src/android/net/EthernetManager.java | 102 ++++++++++-------- .../src/android/net/IEthernetManager.aidl | 9 +- ... => INetworkInterfaceOutcomeReceiver.aidl} | 6 +- 4 files changed, 66 insertions(+), 53 deletions(-) rename framework-t/src/android/net/{IEthernetNetworkManagementListener.aidl => INetworkInterfaceOutcomeReceiver.aidl} (80%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 217a1f67c3..bc27852857 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -131,8 +131,8 @@ filegroup { "src/android/net/EthernetNetworkUpdateRequest.java", "src/android/net/EthernetNetworkUpdateRequest.aidl", "src/android/net/IEthernetManager.aidl", - "src/android/net/IEthernetNetworkManagementListener.aidl", "src/android/net/IEthernetServiceListener.aidl", + "src/android/net/INetworkInterfaceOutcomeReceiver.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 793f28d5aa..4f61dbf38b 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -30,6 +30,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; +import android.os.OutcomeReceiver; import android.os.RemoteException; import com.android.internal.annotations.GuardedBy; @@ -40,7 +41,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; -import java.util.function.BiConsumer; /** * A class that manages and configures Ethernet interfaces. @@ -443,41 +443,45 @@ public class EthernetManager { return new TetheredInterfaceRequest(mService, cbInternal); } - private static final class InternalNetworkManagementListener - extends IEthernetNetworkManagementListener.Stub { + private static final class NetworkInterfaceOutcomeReceiver + extends INetworkInterfaceOutcomeReceiver.Stub { @NonNull private final Executor mExecutor; @NonNull - private final BiConsumer mListener; + private final OutcomeReceiver mCallback; - InternalNetworkManagementListener( + NetworkInterfaceOutcomeReceiver( @NonNull final Executor executor, - @NonNull final BiConsumer listener) { + @NonNull final OutcomeReceiver + callback) { Objects.requireNonNull(executor, "Pass a non-null executor"); - Objects.requireNonNull(listener, "Pass a non-null listener"); + Objects.requireNonNull(callback, "Pass a non-null callback"); mExecutor = executor; - mListener = listener; + mCallback = callback; } @Override - public void onComplete( - @Nullable final Network network, - @Nullable final EthernetNetworkManagementException e) { - mExecutor.execute(() -> mListener.accept(network, e)); + public void onResult(@NonNull String iface) { + mExecutor.execute(() -> mCallback.onResult(iface)); + } + + @Override + public void onError(@NonNull EthernetNetworkManagementException e) { + mExecutor.execute(() -> mCallback.onError(e)); } } - private InternalNetworkManagementListener getInternalNetworkManagementListener( + private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver( @Nullable final Executor executor, - @Nullable final BiConsumer listener) { - if (null != listener) { - Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); + @Nullable final OutcomeReceiver callback) { + if (null != callback) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback"); } - final InternalNetworkManagementListener proxy; - if (null == listener) { + final NetworkInterfaceOutcomeReceiver proxy; + if (null == callback) { proxy = null; } else { - proxy = new InternalNetworkManagementListener(executor, listener); + proxy = new NetworkInterfaceOutcomeReceiver(executor, callback); } return proxy; } @@ -492,14 +496,17 @@ public class EthernetManager { * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities} * object for this network to put inside the {@code request}. * - * If non-null, the listener will be called exactly once after this is called, unless - * a synchronous exception was thrown. + * This function accepts an {@link OutcomeReceiver} that is called once the operation has + * finished execution. * * @param iface the name of the interface to act upon. * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device or on an @@ -515,11 +522,11 @@ public class EthernetManager { @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); Objects.requireNonNull(request, "request must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.updateConfiguration(iface, request, proxy); } catch (RemoteException e) { @@ -530,15 +537,17 @@ public class EthernetManager { /** * Set an ethernet network's link state up. * - * When the link is successfully turned up, the listener will be called with the resulting - * network. If any error or unexpected condition happens while the system tries to turn the - * interface up, the listener will be called with an appropriate exception. - * The listener is guaranteed to be called exactly once for each call to this method, but this - * may take an unbounded amount of time depending on the actual network conditions. + * When the link is successfully turned up, the callback will be called with the network + * interface was torn down, if any. If any error or unexpected condition happens while the + * system tries to turn the interface down, the callback will be called with an appropriate + * exception. The callback is guaranteed to be called exactly once for each call to this method. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -553,10 +562,10 @@ public class EthernetManager { public void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.connectNetwork(iface, proxy); } catch (RemoteException e) { @@ -567,14 +576,17 @@ public class EthernetManager { /** * Set an ethernet network's link state down. * - * When the link is successfully turned down, the listener will be called with the network that - * was torn down, if any. If any error or unexpected condition happens while the system tries to - * turn the interface down, the listener will be called with an appropriate exception. - * The listener is guaranteed to be called exactly once for each call to this method. + * When the link is successfully turned down, the callback will be called with the network + * interface was torn down, if any. If any error or unexpected condition happens while the + * system tries to turn the interface down, the callback will be called with an appropriate + * exception. The callback is guaranteed to be called exactly once for each call to this method. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -589,10 +601,10 @@ public class EthernetManager { public void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.disconnectNetwork(iface, proxy); } catch (RemoteException e) { diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index 544d02ba76..95ae907a3d 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -18,8 +18,9 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkManagementException; import android.net.EthernetNetworkUpdateRequest; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; /** @@ -39,7 +40,7 @@ interface IEthernetManager void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request, - in IEthernetNetworkManagementListener listener); - void connectNetwork(String iface, in IEthernetNetworkManagementListener listener); - void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener); + in INetworkInterfaceOutcomeReceiver listener); + void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); + void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); } diff --git a/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl b/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl similarity index 80% rename from framework-t/src/android/net/IEthernetNetworkManagementListener.aidl rename to framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl index 93edccfdaf..85795ead7a 100644 --- a/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl +++ b/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl @@ -17,9 +17,9 @@ package android.net; import android.net.EthernetNetworkManagementException; -import android.net.Network; /** @hide */ -oneway interface IEthernetNetworkManagementListener { - void onComplete(in Network network, in EthernetNetworkManagementException exception); +oneway interface INetworkInterfaceOutcomeReceiver { + void onResult(in String iface); + void onError(in EthernetNetworkManagementException e); } \ No newline at end of file From edba41c6bd8fe19f5d87ead89cfa43a677a0f99e Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 16 Mar 2022 10:49:18 +0100 Subject: [PATCH 864/881] Change network management listener to outcome receiver Adopts new API according to API review feedback. The outcome receiver can later be removed from most of the ethernet code; in a perfect world, a result can be generated and an exception captured directly from EthernetServiceImpl. This will greatly simplify the current implementation. Bug: 220017952 Test: atest EthernetServiceTests Change-Id: Id8fadfed9fcfd22f04f6d7c3460b5956e571e01f --- .../ethernet/EthernetNetworkFactory.java | 46 ++++++------ .../server/ethernet/EthernetServiceImpl.java | 8 +-- .../server/ethernet/EthernetTracker.java | 10 +-- .../ethernet/EthernetNetworkFactoryTest.java | 72 +++++++++---------- .../ethernet/EthernetServiceImplTest.java | 4 +- .../server/ethernet/EthernetTrackerTest.java | 6 +- 6 files changed, 71 insertions(+), 75 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index ef3abbaec0..4f153553d9 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -24,8 +24,8 @@ import android.net.ConnectivityManager; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.EthernetNetworkSpecifier; -import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -239,14 +239,14 @@ public class EthernetNetworkFactory extends NetworkFactory { * {@code null} is passed, then the network's current * {@link NetworkCapabilities} will be used in support of existing APIs as * the public API does not allow this. - * @param listener an optional {@link IEthernetNetworkManagementListener} to notify callers of + * @param listener an optional {@link INetworkInterfaceOutcomeReceiver} to notify callers of * completion. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected void updateInterface(@NonNull final String ifaceName, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return; @@ -295,7 +295,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return false; @@ -310,7 +310,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void maybeSendNetworkManagementCallbackForUntracked( - String ifaceName, IEthernetNetworkManagementListener listener) { + String ifaceName, INetworkInterfaceOutcomeReceiver listener) { maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( ifaceName + " can't be updated as it is not available.")); @@ -353,15 +353,19 @@ public class EthernetNetworkFactory extends NetworkFactory { } private static void maybeSendNetworkManagementCallback( - @Nullable final IEthernetNetworkManagementListener listener, - @Nullable final Network network, + @Nullable final INetworkInterfaceOutcomeReceiver listener, + @Nullable final String iface, @Nullable final EthernetNetworkManagementException e) { if (null == listener) { return; } try { - listener.onComplete(network, e); + if (iface != null) { + listener.onResult(iface); + } else { + listener.onError(e); + } } catch (RemoteException re) { Log.e(TAG, "Can't send onComplete for network management callback", re); } @@ -415,9 +419,9 @@ public class EthernetNetworkFactory extends NetworkFactory { private class EthernetIpClientCallback extends IpClientCallbacks { private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); - @Nullable IEthernetNetworkManagementListener mNetworkManagementListener; + @Nullable INetworkInterfaceOutcomeReceiver mNetworkManagementListener; - EthernetIpClientCallback(@Nullable final IEthernetNetworkManagementListener listener) { + EthernetIpClientCallback(@Nullable final INetworkInterfaceOutcomeReceiver listener) { mNetworkManagementListener = listener; } @@ -502,7 +506,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void updateInterface(@Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) { Log.d(TAG, "updateInterface, iface: " + name + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig @@ -533,7 +537,7 @@ public class EthernetNetworkFactory extends NetworkFactory { start(null); } - private void start(@Nullable final IEthernetNetworkManagementListener listener) { + private void start(@Nullable final INetworkInterfaceOutcomeReceiver listener) { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); return; @@ -553,7 +557,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStarted(@NonNull final LinkProperties linkProperties, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if(mIpClient == null) { // This call comes from a message posted on the handler thread, but the IpClient has // since been stopped such as may be the case if updateInterfaceLinkState() is @@ -593,10 +597,10 @@ public class EthernetNetworkFactory extends NetworkFactory { }); mNetworkAgent.register(); mNetworkAgent.markConnected(); - realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null); + realizeNetworkManagementCallback(name, null); } - void onIpLayerStopped(@Nullable final IEthernetNetworkManagementListener listener) { + void onIpLayerStopped(@Nullable final INetworkInterfaceOutcomeReceiver listener) { // This cannot happen due to provisioning timeout, because our timeout is 0. It can // happen due to errors while provisioning or on provisioning loss. if(mIpClient == null) { @@ -622,7 +626,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } // Must be called on the handler thread - private void realizeNetworkManagementCallback(@Nullable final Network network, + private void realizeNetworkManagementCallback(@Nullable final String iface, @Nullable final EthernetNetworkManagementException e) { ensureRunningOnEthernetHandlerThread(); if (null == mIpClientCallback) { @@ -630,7 +634,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } EthernetNetworkFactory.maybeSendNetworkManagementCallback( - mIpClientCallback.mNetworkManagementListener, network, e); + mIpClientCallback.mNetworkManagementListener, iface, e); // Only send a single callback per listener. mIpClientCallback.mNetworkManagementListener = null; } @@ -671,7 +675,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ boolean updateLinkState(final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (mLinkUp == up) { EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( @@ -681,13 +685,11 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkUp = up; if (!up) { // was up, goes down - // Save an instance of the current network to use with the callback before stop(). - final Network network = mNetworkAgent != null ? mNetworkAgent.getNetwork() : null; // Send an abort on a provisioning request callback if necessary before stopping. maybeSendNetworkManagementCallbackForAbort(); stop(); // If only setting the interface down, send a callback to signal completion. - EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, network, null); + EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null); } else { // was down, goes up stop(); start(listener); @@ -742,7 +744,7 @@ public class EthernetNetworkFactory extends NetworkFactory { restart(null); } - void restart(@Nullable final IEthernetNetworkManagementListener listener){ + void restart(@Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) Log.d(TAG, "reconnecting Ethernet"); stop(); start(listener); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 50b46845be..edda321494 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -24,7 +24,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; @@ -243,7 +243,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void updateConfiguration(@NonNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Objects.requireNonNull(iface); Objects.requireNonNull(request); throwIfEthernetNotStarted(); @@ -260,7 +260,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void connectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); @@ -272,7 +272,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void disconnectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 074c81bcb0..0a0e327f45 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -27,7 +27,7 @@ import android.content.res.Resources; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.INetd; import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfigurationParcel; @@ -291,7 +291,7 @@ public class EthernetTracker { protected void updateConfiguration(@NonNull final String iface, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities + ", ipConfig: " + ipConfig); @@ -314,13 +314,13 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void connectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { mHandler.post(() -> updateInterfaceState(iface, true, listener)); } @VisibleForTesting(visibility = PACKAGE) protected void disconnectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { mHandler.post(() -> updateInterfaceState(iface, false, listener)); } @@ -505,7 +505,7 @@ public class EthernetTracker { } private void updateInterfaceState(@NonNull final String iface, final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { final int mode = getInterfaceMode(iface); final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) && mFactory.updateInterfaceLinkState(iface, up, listener); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 726833f8ee..5d23aaf0da 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -41,8 +41,8 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; -import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -85,7 +85,7 @@ import java.util.concurrent.TimeUnit; public class EthernetNetworkFactoryTest { private static final int TIMEOUT_MS = 2_000; private static final String TEST_IFACE = "test123"; - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private static final String IP_ADDR = "192.0.2.2/25"; private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); private static final String HW_ADDR = "01:02:03:04:05:06"; @@ -322,7 +322,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verify(mIpClient).shutdown(); - assertSuccessfulListener(listener, null); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -336,7 +336,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verifyStop(); - assertSuccessfulListener(listener, mMockNetwork); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -353,7 +353,7 @@ public class EthernetNetworkFactoryTest { verify(mDeps, never()).makeIpClient(any(), any(), any()); verify(mDeps, never()) .makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); - assertSuccessfulListener(listener, null); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -367,7 +367,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - assertFailedListener(listener, "can't be updated as it is not available"); + listener.expectOnErrorWithMessage("can't be updated as it is not available"); } @Test @@ -381,7 +381,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - assertFailedListener(listener, "No changes"); + listener.expectOnErrorWithMessage("No changes"); } @Test @@ -638,18 +638,31 @@ public class EthernetNetworkFactoryTest { } private static final class TestNetworkManagementListener - implements IEthernetNetworkManagementListener { - private final CompletableFuture> mDone - = new CompletableFuture<>(); + implements INetworkInterfaceOutcomeReceiver { + private final CompletableFuture mResult = new CompletableFuture<>(); + private final CompletableFuture mError = + new CompletableFuture<>(); @Override - public void onComplete(final Network network, - final EthernetNetworkManagementException exception) { - mDone.complete(new Pair<>(network, exception)); + public void onResult(@NonNull String iface) { + mResult.complete(iface); } - Pair expectOnComplete() throws Exception { - return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + @Override + public void onError(@NonNull EthernetNetworkManagementException exception) { + mError.complete(exception); + } + + String expectOnResult() throws Exception { + return mResult.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + EthernetNetworkManagementException expectOnError() throws Exception { + return mError.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void expectOnErrorWithMessage(String msg) throws Exception { + assertTrue(expectOnError().getMessage().contains(msg)); } @Override @@ -669,7 +682,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - assertSuccessfulListener(listener, mMockNetwork); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available @@ -709,26 +722,7 @@ public class EthernetNetworkFactoryTest { triggerOnProvisioningSuccess(); }); - assertSuccessfulListener(successfulListener, mMockNetwork); - } - - private void assertSuccessfulListener( - @NonNull final TestNetworkManagementListener successfulListener, - @NonNull final Network expectedNetwork) throws Exception { - final Pair successfulResult = - successfulListener.expectOnComplete(); - assertEquals(expectedNetwork, successfulResult.first); - assertNull(successfulResult.second); - } - - private void assertFailedListener(@NonNull final TestNetworkManagementListener failedListener, - @NonNull final String errMsg) - throws Exception { - final Pair failedResult = - failedListener.expectOnComplete(); - assertNull(failedResult.first); - assertNotNull(failedResult.second); - assertTrue(failedResult.second.getMessage().contains(errMsg)); + assertEquals(successfulListener.expectOnResult(), TEST_IFACE); } private void verifyNetworkManagementCallIsAbortedWhenInterrupted( @@ -743,7 +737,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener); interruptingRunnable.run(); - assertFailedListener(failedListener, "aborted"); + failedListener.expectOnErrorWithMessage("aborted"); } @Test @@ -757,7 +751,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - listener.expectOnComplete(); + assertEquals(listener.expectOnResult(), TEST_IFACE); verify(mDeps).makeEthernetNetworkAgent(any(), any(), eq(capabilities), any(), any(), any(), any()); verifyRestart(ipConfiguration); @@ -774,7 +768,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); verifyNoStopOrStart(); - assertFailedListener(listener, "can't be updated as it is not available"); + listener.expectOnErrorWithMessage("can't be updated as it is not available"); } @Test diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 2131f7fcdb..e67c4c8b95 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -32,7 +32,7 @@ import android.Manifest; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; import android.net.NetworkCapabilities; @@ -64,7 +64,7 @@ public class EthernetServiceImplTest { new EthernetNetworkUpdateRequest.Builder() .setNetworkCapabilities(new NetworkCapabilities.Builder().build()) .build(); - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @Mock private Handler mHandler; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index ef70d94391..bab9643d23 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -33,7 +33,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.net.InetAddresses; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.INetd; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -66,7 +66,7 @@ public class EthernetTrackerTest { private static final String TEST_IFACE = "test123"; private static final int TIMEOUT_MS = 1_000; private static final String THREAD_NAME = "EthernetServiceThread"; - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private EthernetTracker tracker; private HandlerThread mHandlerThread; @Mock private Context mContext; @@ -334,7 +334,7 @@ public class EthernetTrackerTest { new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build(); final IpConfiguration ipConfig = new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build(); - final IEthernetNetworkManagementListener listener = null; + final INetworkInterfaceOutcomeReceiver listener = null; tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener); waitForIdle(); From dd88b843c90f281d0bb794e14182ba343a6ea6ff Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Thu, 17 Mar 2022 15:20:53 +0000 Subject: [PATCH 865/881] Revert "Change network management listener to outcome receiver" Revert submission 2028203-ethernet-outcomereceiver Reason for revert: BuildMonitor investigating b/225169800 Reverted Changes: I4c204a848:Change Ethernet API to use OutcomeReceiver I7c46545a4:Change Ethernet API to use OutcomeReceiver Id8fadfed9:Change network management listener to outcome rece... Change-Id: I45ba68452b9dccedf72b68fdea6e31c07b86546d --- .../ethernet/EthernetNetworkFactory.java | 46 ++++++------ .../server/ethernet/EthernetServiceImpl.java | 8 +-- .../server/ethernet/EthernetTracker.java | 10 +-- .../ethernet/EthernetNetworkFactoryTest.java | 72 ++++++++++--------- .../ethernet/EthernetServiceImplTest.java | 4 +- .../server/ethernet/EthernetTrackerTest.java | 6 +- 6 files changed, 75 insertions(+), 71 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 4f153553d9..ef3abbaec0 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -24,8 +24,8 @@ import android.net.ConnectivityManager; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.EthernetNetworkSpecifier; +import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; -import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -239,14 +239,14 @@ public class EthernetNetworkFactory extends NetworkFactory { * {@code null} is passed, then the network's current * {@link NetworkCapabilities} will be used in support of existing APIs as * the public API does not allow this. - * @param listener an optional {@link INetworkInterfaceOutcomeReceiver} to notify callers of + * @param listener an optional {@link IEthernetNetworkManagementListener} to notify callers of * completion. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected void updateInterface(@NonNull final String ifaceName, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return; @@ -295,7 +295,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return false; @@ -310,7 +310,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void maybeSendNetworkManagementCallbackForUntracked( - String ifaceName, INetworkInterfaceOutcomeReceiver listener) { + String ifaceName, IEthernetNetworkManagementListener listener) { maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( ifaceName + " can't be updated as it is not available.")); @@ -353,19 +353,15 @@ public class EthernetNetworkFactory extends NetworkFactory { } private static void maybeSendNetworkManagementCallback( - @Nullable final INetworkInterfaceOutcomeReceiver listener, - @Nullable final String iface, + @Nullable final IEthernetNetworkManagementListener listener, + @Nullable final Network network, @Nullable final EthernetNetworkManagementException e) { if (null == listener) { return; } try { - if (iface != null) { - listener.onResult(iface); - } else { - listener.onError(e); - } + listener.onComplete(network, e); } catch (RemoteException re) { Log.e(TAG, "Can't send onComplete for network management callback", re); } @@ -419,9 +415,9 @@ public class EthernetNetworkFactory extends NetworkFactory { private class EthernetIpClientCallback extends IpClientCallbacks { private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); - @Nullable INetworkInterfaceOutcomeReceiver mNetworkManagementListener; + @Nullable IEthernetNetworkManagementListener mNetworkManagementListener; - EthernetIpClientCallback(@Nullable final INetworkInterfaceOutcomeReceiver listener) { + EthernetIpClientCallback(@Nullable final IEthernetNetworkManagementListener listener) { mNetworkManagementListener = listener; } @@ -506,7 +502,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void updateInterface(@Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { Log.d(TAG, "updateInterface, iface: " + name + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig @@ -537,7 +533,7 @@ public class EthernetNetworkFactory extends NetworkFactory { start(null); } - private void start(@Nullable final INetworkInterfaceOutcomeReceiver listener) { + private void start(@Nullable final IEthernetNetworkManagementListener listener) { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); return; @@ -557,7 +553,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStarted(@NonNull final LinkProperties linkProperties, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if(mIpClient == null) { // This call comes from a message posted on the handler thread, but the IpClient has // since been stopped such as may be the case if updateInterfaceLinkState() is @@ -597,10 +593,10 @@ public class EthernetNetworkFactory extends NetworkFactory { }); mNetworkAgent.register(); mNetworkAgent.markConnected(); - realizeNetworkManagementCallback(name, null); + realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null); } - void onIpLayerStopped(@Nullable final INetworkInterfaceOutcomeReceiver listener) { + void onIpLayerStopped(@Nullable final IEthernetNetworkManagementListener listener) { // This cannot happen due to provisioning timeout, because our timeout is 0. It can // happen due to errors while provisioning or on provisioning loss. if(mIpClient == null) { @@ -626,7 +622,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } // Must be called on the handler thread - private void realizeNetworkManagementCallback(@Nullable final String iface, + private void realizeNetworkManagementCallback(@Nullable final Network network, @Nullable final EthernetNetworkManagementException e) { ensureRunningOnEthernetHandlerThread(); if (null == mIpClientCallback) { @@ -634,7 +630,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } EthernetNetworkFactory.maybeSendNetworkManagementCallback( - mIpClientCallback.mNetworkManagementListener, iface, e); + mIpClientCallback.mNetworkManagementListener, network, e); // Only send a single callback per listener. mIpClientCallback.mNetworkManagementListener = null; } @@ -675,7 +671,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ boolean updateLinkState(final boolean up, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (mLinkUp == up) { EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( @@ -685,11 +681,13 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkUp = up; if (!up) { // was up, goes down + // Save an instance of the current network to use with the callback before stop(). + final Network network = mNetworkAgent != null ? mNetworkAgent.getNetwork() : null; // Send an abort on a provisioning request callback if necessary before stopping. maybeSendNetworkManagementCallbackForAbort(); stop(); // If only setting the interface down, send a callback to signal completion. - EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null); + EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, network, null); } else { // was down, goes up stop(); start(listener); @@ -744,7 +742,7 @@ public class EthernetNetworkFactory extends NetworkFactory { restart(null); } - void restart(@Nullable final INetworkInterfaceOutcomeReceiver listener) { + void restart(@Nullable final IEthernetNetworkManagementListener listener){ if (DBG) Log.d(TAG, "reconnecting Ethernet"); stop(); start(listener); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index edda321494..50b46845be 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -24,7 +24,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; -import android.net.INetworkInterfaceOutcomeReceiver; +import android.net.IEthernetNetworkManagementListener; import android.net.ITetheredInterfaceCallback; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; @@ -243,7 +243,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void updateConfiguration(@NonNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { Objects.requireNonNull(iface); Objects.requireNonNull(request); throwIfEthernetNotStarted(); @@ -260,7 +260,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void connectNetwork(@NonNull final String iface, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); @@ -272,7 +272,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void disconnectNetwork(@NonNull final String iface, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 0a0e327f45..074c81bcb0 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -27,7 +27,7 @@ import android.content.res.Resources; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.IEthernetServiceListener; -import android.net.INetworkInterfaceOutcomeReceiver; +import android.net.IEthernetNetworkManagementListener; import android.net.INetd; import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfigurationParcel; @@ -291,7 +291,7 @@ public class EthernetTracker { protected void updateConfiguration(@NonNull final String iface, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities + ", ipConfig: " + ipConfig); @@ -314,13 +314,13 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void connectNetwork(@NonNull final String iface, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { mHandler.post(() -> updateInterfaceState(iface, true, listener)); } @VisibleForTesting(visibility = PACKAGE) protected void disconnectNetwork(@NonNull final String iface, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { mHandler.post(() -> updateInterfaceState(iface, false, listener)); } @@ -505,7 +505,7 @@ public class EthernetTracker { } private void updateInterfaceState(@NonNull final String iface, final boolean up, - @Nullable final INetworkInterfaceOutcomeReceiver listener) { + @Nullable final IEthernetNetworkManagementListener listener) { final int mode = getInterfaceMode(iface); final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) && mFactory.updateInterfaceLinkState(iface, up, listener); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 5d23aaf0da..726833f8ee 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -41,8 +41,8 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; +import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; -import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -85,7 +85,7 @@ import java.util.concurrent.TimeUnit; public class EthernetNetworkFactoryTest { private static final int TIMEOUT_MS = 2_000; private static final String TEST_IFACE = "test123"; - private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; + private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private static final String IP_ADDR = "192.0.2.2/25"; private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); private static final String HW_ADDR = "01:02:03:04:05:06"; @@ -322,7 +322,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verify(mIpClient).shutdown(); - assertEquals(listener.expectOnResult(), TEST_IFACE); + assertSuccessfulListener(listener, null); } @Test @@ -336,7 +336,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verifyStop(); - assertEquals(listener.expectOnResult(), TEST_IFACE); + assertSuccessfulListener(listener, mMockNetwork); } @Test @@ -353,7 +353,7 @@ public class EthernetNetworkFactoryTest { verify(mDeps, never()).makeIpClient(any(), any(), any()); verify(mDeps, never()) .makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); - assertEquals(listener.expectOnResult(), TEST_IFACE); + assertSuccessfulListener(listener, null); } @Test @@ -367,7 +367,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - listener.expectOnErrorWithMessage("can't be updated as it is not available"); + assertFailedListener(listener, "can't be updated as it is not available"); } @Test @@ -381,7 +381,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - listener.expectOnErrorWithMessage("No changes"); + assertFailedListener(listener, "No changes"); } @Test @@ -638,31 +638,18 @@ public class EthernetNetworkFactoryTest { } private static final class TestNetworkManagementListener - implements INetworkInterfaceOutcomeReceiver { - private final CompletableFuture mResult = new CompletableFuture<>(); - private final CompletableFuture mError = - new CompletableFuture<>(); + implements IEthernetNetworkManagementListener { + private final CompletableFuture> mDone + = new CompletableFuture<>(); @Override - public void onResult(@NonNull String iface) { - mResult.complete(iface); + public void onComplete(final Network network, + final EthernetNetworkManagementException exception) { + mDone.complete(new Pair<>(network, exception)); } - @Override - public void onError(@NonNull EthernetNetworkManagementException exception) { - mError.complete(exception); - } - - String expectOnResult() throws Exception { - return mResult.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - - EthernetNetworkManagementException expectOnError() throws Exception { - return mError.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - - void expectOnErrorWithMessage(String msg) throws Exception { - assertTrue(expectOnError().getMessage().contains(msg)); + Pair expectOnComplete() throws Exception { + return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); } @Override @@ -682,7 +669,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - assertEquals(listener.expectOnResult(), TEST_IFACE); + assertSuccessfulListener(listener, mMockNetwork); } @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available @@ -722,7 +709,26 @@ public class EthernetNetworkFactoryTest { triggerOnProvisioningSuccess(); }); - assertEquals(successfulListener.expectOnResult(), TEST_IFACE); + assertSuccessfulListener(successfulListener, mMockNetwork); + } + + private void assertSuccessfulListener( + @NonNull final TestNetworkManagementListener successfulListener, + @NonNull final Network expectedNetwork) throws Exception { + final Pair successfulResult = + successfulListener.expectOnComplete(); + assertEquals(expectedNetwork, successfulResult.first); + assertNull(successfulResult.second); + } + + private void assertFailedListener(@NonNull final TestNetworkManagementListener failedListener, + @NonNull final String errMsg) + throws Exception { + final Pair failedResult = + failedListener.expectOnComplete(); + assertNull(failedResult.first); + assertNotNull(failedResult.second); + assertTrue(failedResult.second.getMessage().contains(errMsg)); } private void verifyNetworkManagementCallIsAbortedWhenInterrupted( @@ -737,7 +743,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener); interruptingRunnable.run(); - failedListener.expectOnErrorWithMessage("aborted"); + assertFailedListener(failedListener, "aborted"); } @Test @@ -751,7 +757,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - assertEquals(listener.expectOnResult(), TEST_IFACE); + listener.expectOnComplete(); verify(mDeps).makeEthernetNetworkAgent(any(), any(), eq(capabilities), any(), any(), any(), any()); verifyRestart(ipConfiguration); @@ -768,7 +774,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); verifyNoStopOrStart(); - listener.expectOnErrorWithMessage("can't be updated as it is not available"); + assertFailedListener(listener, "can't be updated as it is not available"); } @Test diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index e67c4c8b95..2131f7fcdb 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -32,7 +32,7 @@ import android.Manifest; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; -import android.net.INetworkInterfaceOutcomeReceiver; +import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; import android.net.NetworkCapabilities; @@ -64,7 +64,7 @@ public class EthernetServiceImplTest { new EthernetNetworkUpdateRequest.Builder() .setNetworkCapabilities(new NetworkCapabilities.Builder().build()) .build(); - private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; + private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @Mock private Handler mHandler; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index bab9643d23..ef70d94391 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -33,7 +33,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.net.InetAddresses; -import android.net.INetworkInterfaceOutcomeReceiver; +import android.net.IEthernetNetworkManagementListener; import android.net.INetd; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -66,7 +66,7 @@ public class EthernetTrackerTest { private static final String TEST_IFACE = "test123"; private static final int TIMEOUT_MS = 1_000; private static final String THREAD_NAME = "EthernetServiceThread"; - private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; + private static final IEthernetNetworkManagementListener NULL_LISTENER = null; private EthernetTracker tracker; private HandlerThread mHandlerThread; @Mock private Context mContext; @@ -334,7 +334,7 @@ public class EthernetTrackerTest { new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build(); final IpConfiguration ipConfig = new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build(); - final INetworkInterfaceOutcomeReceiver listener = null; + final IEthernetNetworkManagementListener listener = null; tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener); waitForIdle(); From 7844d4151309dc8ab0f32512f5961077b59ba60e Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Thu, 17 Mar 2022 15:20:53 +0000 Subject: [PATCH 866/881] Revert "Change Ethernet API to use OutcomeReceiver" Revert "Change network management listener to outcome receiver" Revert submission 2028203-ethernet-outcomereceiver Reason for revert: BuildMonitor investigating b/225169800 Reverted Changes: I4c204a848:Change Ethernet API to use OutcomeReceiver I7c46545a4:Change Ethernet API to use OutcomeReceiver Id8fadfed9:Change network management listener to outcome rece... Change-Id: I45af594f7233ed89113f4cf7f977092271980672 --- framework-t/Sources.bp | 2 +- .../src/android/net/EthernetManager.java | 102 ++++++++---------- .../src/android/net/IEthernetManager.aidl | 9 +- ...> IEthernetNetworkManagementListener.aidl} | 6 +- 4 files changed, 53 insertions(+), 66 deletions(-) rename framework-t/src/android/net/{INetworkInterfaceOutcomeReceiver.aidl => IEthernetNetworkManagementListener.aidl} (80%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index bc27852857..217a1f67c3 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -131,8 +131,8 @@ filegroup { "src/android/net/EthernetNetworkUpdateRequest.java", "src/android/net/EthernetNetworkUpdateRequest.aidl", "src/android/net/IEthernetManager.aidl", + "src/android/net/IEthernetNetworkManagementListener.aidl", "src/android/net/IEthernetServiceListener.aidl", - "src/android/net/INetworkInterfaceOutcomeReceiver.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 4f61dbf38b..793f28d5aa 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -30,7 +30,6 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; -import android.os.OutcomeReceiver; import android.os.RemoteException; import com.android.internal.annotations.GuardedBy; @@ -41,6 +40,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.function.BiConsumer; /** * A class that manages and configures Ethernet interfaces. @@ -443,45 +443,41 @@ public class EthernetManager { return new TetheredInterfaceRequest(mService, cbInternal); } - private static final class NetworkInterfaceOutcomeReceiver - extends INetworkInterfaceOutcomeReceiver.Stub { + private static final class InternalNetworkManagementListener + extends IEthernetNetworkManagementListener.Stub { @NonNull private final Executor mExecutor; @NonNull - private final OutcomeReceiver mCallback; + private final BiConsumer mListener; - NetworkInterfaceOutcomeReceiver( + InternalNetworkManagementListener( @NonNull final Executor executor, - @NonNull final OutcomeReceiver - callback) { + @NonNull final BiConsumer listener) { Objects.requireNonNull(executor, "Pass a non-null executor"); - Objects.requireNonNull(callback, "Pass a non-null callback"); + Objects.requireNonNull(listener, "Pass a non-null listener"); mExecutor = executor; - mCallback = callback; + mListener = listener; } @Override - public void onResult(@NonNull String iface) { - mExecutor.execute(() -> mCallback.onResult(iface)); - } - - @Override - public void onError(@NonNull EthernetNetworkManagementException e) { - mExecutor.execute(() -> mCallback.onError(e)); + public void onComplete( + @Nullable final Network network, + @Nullable final EthernetNetworkManagementException e) { + mExecutor.execute(() -> mListener.accept(network, e)); } } - private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver( + private InternalNetworkManagementListener getInternalNetworkManagementListener( @Nullable final Executor executor, - @Nullable final OutcomeReceiver callback) { - if (null != callback) { - Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback"); + @Nullable final BiConsumer listener) { + if (null != listener) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); } - final NetworkInterfaceOutcomeReceiver proxy; - if (null == callback) { + final InternalNetworkManagementListener proxy; + if (null == listener) { proxy = null; } else { - proxy = new NetworkInterfaceOutcomeReceiver(executor, callback); + proxy = new InternalNetworkManagementListener(executor, listener); } return proxy; } @@ -496,17 +492,14 @@ public class EthernetManager { * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities} * object for this network to put inside the {@code request}. * - * This function accepts an {@link OutcomeReceiver} that is called once the operation has - * finished execution. + * If non-null, the listener will be called exactly once after this is called, unless + * a synchronous exception was thrown. * * @param iface the name of the interface to act upon. * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values. - * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. - * @param callback an optional {@link OutcomeReceiver} to listen for completion of the - * operation. On success, {@link OutcomeReceiver#onResult} is called with the - * interface name. On error, {@link OutcomeReceiver#onError} is called with more - * information about the error. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device or on an @@ -522,11 +515,11 @@ public class EthernetManager { @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, - @Nullable OutcomeReceiver callback) { + @Nullable BiConsumer listener) { Objects.requireNonNull(iface, "iface must be non-null"); Objects.requireNonNull(request, "request must be non-null"); - final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( - executor, callback); + final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( + executor, listener); try { mService.updateConfiguration(iface, request, proxy); } catch (RemoteException e) { @@ -537,17 +530,15 @@ public class EthernetManager { /** * Set an ethernet network's link state up. * - * When the link is successfully turned up, the callback will be called with the network - * interface was torn down, if any. If any error or unexpected condition happens while the - * system tries to turn the interface down, the callback will be called with an appropriate - * exception. The callback is guaranteed to be called exactly once for each call to this method. + * When the link is successfully turned up, the listener will be called with the resulting + * network. If any error or unexpected condition happens while the system tries to turn the + * interface up, the listener will be called with an appropriate exception. + * The listener is guaranteed to be called exactly once for each call to this method, but this + * may take an unbounded amount of time depending on the actual network conditions. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. - * @param callback an optional {@link OutcomeReceiver} to listen for completion of the - * operation. On success, {@link OutcomeReceiver#onResult} is called with the - * interface name. On error, {@link OutcomeReceiver#onError} is called with more - * information about the error. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -562,10 +553,10 @@ public class EthernetManager { public void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable OutcomeReceiver callback) { + @Nullable BiConsumer listener) { Objects.requireNonNull(iface, "iface must be non-null"); - final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( - executor, callback); + final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( + executor, listener); try { mService.connectNetwork(iface, proxy); } catch (RemoteException e) { @@ -576,17 +567,14 @@ public class EthernetManager { /** * Set an ethernet network's link state down. * - * When the link is successfully turned down, the callback will be called with the network - * interface was torn down, if any. If any error or unexpected condition happens while the - * system tries to turn the interface down, the callback will be called with an appropriate - * exception. The callback is guaranteed to be called exactly once for each call to this method. + * When the link is successfully turned down, the listener will be called with the network that + * was torn down, if any. If any error or unexpected condition happens while the system tries to + * turn the interface down, the listener will be called with an appropriate exception. + * The listener is guaranteed to be called exactly once for each call to this method. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. - * @param callback an optional {@link OutcomeReceiver} to listen for completion of the - * operation. On success, {@link OutcomeReceiver#onResult} is called with the - * interface name. On error, {@link OutcomeReceiver#onError} is called with more - * information about the error. + * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. + * @param listener an optional {@link BiConsumer} to listen for completion of the operation. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -601,10 +589,10 @@ public class EthernetManager { public void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable OutcomeReceiver callback) { + @Nullable BiConsumer listener) { Objects.requireNonNull(iface, "iface must be non-null"); - final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( - executor, callback); + final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( + executor, listener); try { mService.disconnectNetwork(iface, proxy); } catch (RemoteException e) { diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index 95ae907a3d..544d02ba76 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -18,9 +18,8 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; -import android.net.EthernetNetworkManagementException; +import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkUpdateRequest; -import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; /** @@ -40,7 +39,7 @@ interface IEthernetManager void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request, - in INetworkInterfaceOutcomeReceiver listener); - void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); - void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); + in IEthernetNetworkManagementListener listener); + void connectNetwork(String iface, in IEthernetNetworkManagementListener listener); + void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener); } diff --git a/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl b/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl similarity index 80% rename from framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl rename to framework-t/src/android/net/IEthernetNetworkManagementListener.aidl index 85795ead7a..93edccfdaf 100644 --- a/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl +++ b/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl @@ -17,9 +17,9 @@ package android.net; import android.net.EthernetNetworkManagementException; +import android.net.Network; /** @hide */ -oneway interface INetworkInterfaceOutcomeReceiver { - void onResult(in String iface); - void onError(in EthernetNetworkManagementException e); +oneway interface IEthernetNetworkManagementListener { + void onComplete(in Network network, in EthernetNetworkManagementException exception); } \ No newline at end of file From 39ef30ce644ca5f6d6d68680061156825b97f3a0 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Thu, 17 Mar 2022 19:19:21 +0000 Subject: [PATCH 867/881] Revert^2 "Change Ethernet API to use OutcomeReceiver" 7844d4151309dc8ab0f32512f5961077b59ba60e Merged-In: I7c46545a47034be409071c2ec007d9e1480c6ed0 Change-Id: If9b055e0862755f1d33b5ba6e026fd827bc1d0ea --- framework-t/Sources.bp | 2 +- .../src/android/net/EthernetManager.java | 102 ++++++++++-------- .../src/android/net/IEthernetManager.aidl | 9 +- ... => INetworkInterfaceOutcomeReceiver.aidl} | 6 +- 4 files changed, 66 insertions(+), 53 deletions(-) rename framework-t/src/android/net/{IEthernetNetworkManagementListener.aidl => INetworkInterfaceOutcomeReceiver.aidl} (80%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 217a1f67c3..bc27852857 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -131,8 +131,8 @@ filegroup { "src/android/net/EthernetNetworkUpdateRequest.java", "src/android/net/EthernetNetworkUpdateRequest.aidl", "src/android/net/IEthernetManager.aidl", - "src/android/net/IEthernetNetworkManagementListener.aidl", "src/android/net/IEthernetServiceListener.aidl", + "src/android/net/INetworkInterfaceOutcomeReceiver.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 793f28d5aa..4f61dbf38b 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -30,6 +30,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; +import android.os.OutcomeReceiver; import android.os.RemoteException; import com.android.internal.annotations.GuardedBy; @@ -40,7 +41,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; -import java.util.function.BiConsumer; /** * A class that manages and configures Ethernet interfaces. @@ -443,41 +443,45 @@ public class EthernetManager { return new TetheredInterfaceRequest(mService, cbInternal); } - private static final class InternalNetworkManagementListener - extends IEthernetNetworkManagementListener.Stub { + private static final class NetworkInterfaceOutcomeReceiver + extends INetworkInterfaceOutcomeReceiver.Stub { @NonNull private final Executor mExecutor; @NonNull - private final BiConsumer mListener; + private final OutcomeReceiver mCallback; - InternalNetworkManagementListener( + NetworkInterfaceOutcomeReceiver( @NonNull final Executor executor, - @NonNull final BiConsumer listener) { + @NonNull final OutcomeReceiver + callback) { Objects.requireNonNull(executor, "Pass a non-null executor"); - Objects.requireNonNull(listener, "Pass a non-null listener"); + Objects.requireNonNull(callback, "Pass a non-null callback"); mExecutor = executor; - mListener = listener; + mCallback = callback; } @Override - public void onComplete( - @Nullable final Network network, - @Nullable final EthernetNetworkManagementException e) { - mExecutor.execute(() -> mListener.accept(network, e)); + public void onResult(@NonNull String iface) { + mExecutor.execute(() -> mCallback.onResult(iface)); + } + + @Override + public void onError(@NonNull EthernetNetworkManagementException e) { + mExecutor.execute(() -> mCallback.onError(e)); } } - private InternalNetworkManagementListener getInternalNetworkManagementListener( + private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver( @Nullable final Executor executor, - @Nullable final BiConsumer listener) { - if (null != listener) { - Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); + @Nullable final OutcomeReceiver callback) { + if (null != callback) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback"); } - final InternalNetworkManagementListener proxy; - if (null == listener) { + final NetworkInterfaceOutcomeReceiver proxy; + if (null == callback) { proxy = null; } else { - proxy = new InternalNetworkManagementListener(executor, listener); + proxy = new NetworkInterfaceOutcomeReceiver(executor, callback); } return proxy; } @@ -492,14 +496,17 @@ public class EthernetManager { * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities} * object for this network to put inside the {@code request}. * - * If non-null, the listener will be called exactly once after this is called, unless - * a synchronous exception was thrown. + * This function accepts an {@link OutcomeReceiver} that is called once the operation has + * finished execution. * * @param iface the name of the interface to act upon. * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device or on an @@ -515,11 +522,11 @@ public class EthernetManager { @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); Objects.requireNonNull(request, "request must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.updateConfiguration(iface, request, proxy); } catch (RemoteException e) { @@ -530,15 +537,17 @@ public class EthernetManager { /** * Set an ethernet network's link state up. * - * When the link is successfully turned up, the listener will be called with the resulting - * network. If any error or unexpected condition happens while the system tries to turn the - * interface up, the listener will be called with an appropriate exception. - * The listener is guaranteed to be called exactly once for each call to this method, but this - * may take an unbounded amount of time depending on the actual network conditions. + * When the link is successfully turned up, the callback will be called with the network + * interface was torn down, if any. If any error or unexpected condition happens while the + * system tries to turn the interface down, the callback will be called with an appropriate + * exception. The callback is guaranteed to be called exactly once for each call to this method. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -553,10 +562,10 @@ public class EthernetManager { public void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.connectNetwork(iface, proxy); } catch (RemoteException e) { @@ -567,14 +576,17 @@ public class EthernetManager { /** * Set an ethernet network's link state down. * - * When the link is successfully turned down, the listener will be called with the network that - * was torn down, if any. If any error or unexpected condition happens while the system tries to - * turn the interface down, the listener will be called with an appropriate exception. - * The listener is guaranteed to be called exactly once for each call to this method. + * When the link is successfully turned down, the callback will be called with the network + * interface was torn down, if any. If any error or unexpected condition happens while the + * system tries to turn the interface down, the callback will be called with an appropriate + * exception. The callback is guaranteed to be called exactly once for each call to this method. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -589,10 +601,10 @@ public class EthernetManager { public void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.disconnectNetwork(iface, proxy); } catch (RemoteException e) { diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index 544d02ba76..95ae907a3d 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -18,8 +18,9 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkManagementException; import android.net.EthernetNetworkUpdateRequest; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; /** @@ -39,7 +40,7 @@ interface IEthernetManager void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request, - in IEthernetNetworkManagementListener listener); - void connectNetwork(String iface, in IEthernetNetworkManagementListener listener); - void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener); + in INetworkInterfaceOutcomeReceiver listener); + void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); + void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); } diff --git a/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl b/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl similarity index 80% rename from framework-t/src/android/net/IEthernetNetworkManagementListener.aidl rename to framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl index 93edccfdaf..85795ead7a 100644 --- a/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl +++ b/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl @@ -17,9 +17,9 @@ package android.net; import android.net.EthernetNetworkManagementException; -import android.net.Network; /** @hide */ -oneway interface IEthernetNetworkManagementListener { - void onComplete(in Network network, in EthernetNetworkManagementException exception); +oneway interface INetworkInterfaceOutcomeReceiver { + void onResult(in String iface); + void onError(in EthernetNetworkManagementException e); } \ No newline at end of file From c9b8505e0b4bd11e195443754d244ba6d9a7b10b Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Thu, 17 Mar 2022 19:19:21 +0000 Subject: [PATCH 868/881] Revert "Revert "Change network management listener to outcome re..." Revert submission 2030087-revert-2028203-ethernet-outcomereceiver-WFKWDORBPY Reason for revert: Reinstate changes Reverted Changes: Ibd1d70ac3:Revert "Change Ethernet API to use OutcomeReceiver... I45af594f7:Revert "Change Ethernet API to use OutcomeReceiver... I45ba68452:Revert "Change network management listener to outc... Merged-In: Id8fadfed9fcfd22f04f6d7c3460b5956e571e01f Change-Id: If3854c1c3a39aa6de84807c6bde267cf88f3d277 --- .../ethernet/EthernetNetworkFactory.java | 46 ++++++------ .../server/ethernet/EthernetServiceImpl.java | 8 +-- .../server/ethernet/EthernetTracker.java | 10 +-- .../ethernet/EthernetNetworkFactoryTest.java | 72 +++++++++---------- .../ethernet/EthernetServiceImplTest.java | 4 +- .../server/ethernet/EthernetTrackerTest.java | 6 +- 6 files changed, 71 insertions(+), 75 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index ef3abbaec0..4f153553d9 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -24,8 +24,8 @@ import android.net.ConnectivityManager; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.EthernetNetworkSpecifier; -import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -239,14 +239,14 @@ public class EthernetNetworkFactory extends NetworkFactory { * {@code null} is passed, then the network's current * {@link NetworkCapabilities} will be used in support of existing APIs as * the public API does not allow this. - * @param listener an optional {@link IEthernetNetworkManagementListener} to notify callers of + * @param listener an optional {@link INetworkInterfaceOutcomeReceiver} to notify callers of * completion. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected void updateInterface(@NonNull final String ifaceName, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return; @@ -295,7 +295,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return false; @@ -310,7 +310,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void maybeSendNetworkManagementCallbackForUntracked( - String ifaceName, IEthernetNetworkManagementListener listener) { + String ifaceName, INetworkInterfaceOutcomeReceiver listener) { maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( ifaceName + " can't be updated as it is not available.")); @@ -353,15 +353,19 @@ public class EthernetNetworkFactory extends NetworkFactory { } private static void maybeSendNetworkManagementCallback( - @Nullable final IEthernetNetworkManagementListener listener, - @Nullable final Network network, + @Nullable final INetworkInterfaceOutcomeReceiver listener, + @Nullable final String iface, @Nullable final EthernetNetworkManagementException e) { if (null == listener) { return; } try { - listener.onComplete(network, e); + if (iface != null) { + listener.onResult(iface); + } else { + listener.onError(e); + } } catch (RemoteException re) { Log.e(TAG, "Can't send onComplete for network management callback", re); } @@ -415,9 +419,9 @@ public class EthernetNetworkFactory extends NetworkFactory { private class EthernetIpClientCallback extends IpClientCallbacks { private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); - @Nullable IEthernetNetworkManagementListener mNetworkManagementListener; + @Nullable INetworkInterfaceOutcomeReceiver mNetworkManagementListener; - EthernetIpClientCallback(@Nullable final IEthernetNetworkManagementListener listener) { + EthernetIpClientCallback(@Nullable final INetworkInterfaceOutcomeReceiver listener) { mNetworkManagementListener = listener; } @@ -502,7 +506,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void updateInterface(@Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) { Log.d(TAG, "updateInterface, iface: " + name + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig @@ -533,7 +537,7 @@ public class EthernetNetworkFactory extends NetworkFactory { start(null); } - private void start(@Nullable final IEthernetNetworkManagementListener listener) { + private void start(@Nullable final INetworkInterfaceOutcomeReceiver listener) { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); return; @@ -553,7 +557,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStarted(@NonNull final LinkProperties linkProperties, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if(mIpClient == null) { // This call comes from a message posted on the handler thread, but the IpClient has // since been stopped such as may be the case if updateInterfaceLinkState() is @@ -593,10 +597,10 @@ public class EthernetNetworkFactory extends NetworkFactory { }); mNetworkAgent.register(); mNetworkAgent.markConnected(); - realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null); + realizeNetworkManagementCallback(name, null); } - void onIpLayerStopped(@Nullable final IEthernetNetworkManagementListener listener) { + void onIpLayerStopped(@Nullable final INetworkInterfaceOutcomeReceiver listener) { // This cannot happen due to provisioning timeout, because our timeout is 0. It can // happen due to errors while provisioning or on provisioning loss. if(mIpClient == null) { @@ -622,7 +626,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } // Must be called on the handler thread - private void realizeNetworkManagementCallback(@Nullable final Network network, + private void realizeNetworkManagementCallback(@Nullable final String iface, @Nullable final EthernetNetworkManagementException e) { ensureRunningOnEthernetHandlerThread(); if (null == mIpClientCallback) { @@ -630,7 +634,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } EthernetNetworkFactory.maybeSendNetworkManagementCallback( - mIpClientCallback.mNetworkManagementListener, network, e); + mIpClientCallback.mNetworkManagementListener, iface, e); // Only send a single callback per listener. mIpClientCallback.mNetworkManagementListener = null; } @@ -671,7 +675,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ boolean updateLinkState(final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (mLinkUp == up) { EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( @@ -681,13 +685,11 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkUp = up; if (!up) { // was up, goes down - // Save an instance of the current network to use with the callback before stop(). - final Network network = mNetworkAgent != null ? mNetworkAgent.getNetwork() : null; // Send an abort on a provisioning request callback if necessary before stopping. maybeSendNetworkManagementCallbackForAbort(); stop(); // If only setting the interface down, send a callback to signal completion. - EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, network, null); + EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null); } else { // was down, goes up stop(); start(listener); @@ -742,7 +744,7 @@ public class EthernetNetworkFactory extends NetworkFactory { restart(null); } - void restart(@Nullable final IEthernetNetworkManagementListener listener){ + void restart(@Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) Log.d(TAG, "reconnecting Ethernet"); stop(); start(listener); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 50b46845be..edda321494 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -24,7 +24,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; @@ -243,7 +243,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void updateConfiguration(@NonNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Objects.requireNonNull(iface); Objects.requireNonNull(request); throwIfEthernetNotStarted(); @@ -260,7 +260,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void connectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); @@ -272,7 +272,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void disconnectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 074c81bcb0..0a0e327f45 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -27,7 +27,7 @@ import android.content.res.Resources; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.INetd; import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfigurationParcel; @@ -291,7 +291,7 @@ public class EthernetTracker { protected void updateConfiguration(@NonNull final String iface, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities + ", ipConfig: " + ipConfig); @@ -314,13 +314,13 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void connectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { mHandler.post(() -> updateInterfaceState(iface, true, listener)); } @VisibleForTesting(visibility = PACKAGE) protected void disconnectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { mHandler.post(() -> updateInterfaceState(iface, false, listener)); } @@ -505,7 +505,7 @@ public class EthernetTracker { } private void updateInterfaceState(@NonNull final String iface, final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { final int mode = getInterfaceMode(iface); final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) && mFactory.updateInterfaceLinkState(iface, up, listener); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 726833f8ee..5d23aaf0da 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -41,8 +41,8 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; -import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -85,7 +85,7 @@ import java.util.concurrent.TimeUnit; public class EthernetNetworkFactoryTest { private static final int TIMEOUT_MS = 2_000; private static final String TEST_IFACE = "test123"; - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private static final String IP_ADDR = "192.0.2.2/25"; private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); private static final String HW_ADDR = "01:02:03:04:05:06"; @@ -322,7 +322,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verify(mIpClient).shutdown(); - assertSuccessfulListener(listener, null); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -336,7 +336,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verifyStop(); - assertSuccessfulListener(listener, mMockNetwork); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -353,7 +353,7 @@ public class EthernetNetworkFactoryTest { verify(mDeps, never()).makeIpClient(any(), any(), any()); verify(mDeps, never()) .makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); - assertSuccessfulListener(listener, null); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -367,7 +367,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - assertFailedListener(listener, "can't be updated as it is not available"); + listener.expectOnErrorWithMessage("can't be updated as it is not available"); } @Test @@ -381,7 +381,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - assertFailedListener(listener, "No changes"); + listener.expectOnErrorWithMessage("No changes"); } @Test @@ -638,18 +638,31 @@ public class EthernetNetworkFactoryTest { } private static final class TestNetworkManagementListener - implements IEthernetNetworkManagementListener { - private final CompletableFuture> mDone - = new CompletableFuture<>(); + implements INetworkInterfaceOutcomeReceiver { + private final CompletableFuture mResult = new CompletableFuture<>(); + private final CompletableFuture mError = + new CompletableFuture<>(); @Override - public void onComplete(final Network network, - final EthernetNetworkManagementException exception) { - mDone.complete(new Pair<>(network, exception)); + public void onResult(@NonNull String iface) { + mResult.complete(iface); } - Pair expectOnComplete() throws Exception { - return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + @Override + public void onError(@NonNull EthernetNetworkManagementException exception) { + mError.complete(exception); + } + + String expectOnResult() throws Exception { + return mResult.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + EthernetNetworkManagementException expectOnError() throws Exception { + return mError.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void expectOnErrorWithMessage(String msg) throws Exception { + assertTrue(expectOnError().getMessage().contains(msg)); } @Override @@ -669,7 +682,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - assertSuccessfulListener(listener, mMockNetwork); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available @@ -709,26 +722,7 @@ public class EthernetNetworkFactoryTest { triggerOnProvisioningSuccess(); }); - assertSuccessfulListener(successfulListener, mMockNetwork); - } - - private void assertSuccessfulListener( - @NonNull final TestNetworkManagementListener successfulListener, - @NonNull final Network expectedNetwork) throws Exception { - final Pair successfulResult = - successfulListener.expectOnComplete(); - assertEquals(expectedNetwork, successfulResult.first); - assertNull(successfulResult.second); - } - - private void assertFailedListener(@NonNull final TestNetworkManagementListener failedListener, - @NonNull final String errMsg) - throws Exception { - final Pair failedResult = - failedListener.expectOnComplete(); - assertNull(failedResult.first); - assertNotNull(failedResult.second); - assertTrue(failedResult.second.getMessage().contains(errMsg)); + assertEquals(successfulListener.expectOnResult(), TEST_IFACE); } private void verifyNetworkManagementCallIsAbortedWhenInterrupted( @@ -743,7 +737,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener); interruptingRunnable.run(); - assertFailedListener(failedListener, "aborted"); + failedListener.expectOnErrorWithMessage("aborted"); } @Test @@ -757,7 +751,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - listener.expectOnComplete(); + assertEquals(listener.expectOnResult(), TEST_IFACE); verify(mDeps).makeEthernetNetworkAgent(any(), any(), eq(capabilities), any(), any(), any(), any()); verifyRestart(ipConfiguration); @@ -774,7 +768,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); verifyNoStopOrStart(); - assertFailedListener(listener, "can't be updated as it is not available"); + listener.expectOnErrorWithMessage("can't be updated as it is not available"); } @Test diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 2131f7fcdb..e67c4c8b95 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -32,7 +32,7 @@ import android.Manifest; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; import android.net.NetworkCapabilities; @@ -64,7 +64,7 @@ public class EthernetServiceImplTest { new EthernetNetworkUpdateRequest.Builder() .setNetworkCapabilities(new NetworkCapabilities.Builder().build()) .build(); - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @Mock private Handler mHandler; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index ef70d94391..bab9643d23 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -33,7 +33,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.net.InetAddresses; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.INetd; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -66,7 +66,7 @@ public class EthernetTrackerTest { private static final String TEST_IFACE = "test123"; private static final int TIMEOUT_MS = 1_000; private static final String THREAD_NAME = "EthernetServiceThread"; - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private EthernetTracker tracker; private HandlerThread mHandlerThread; @Mock private Context mContext; @@ -334,7 +334,7 @@ public class EthernetTrackerTest { new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build(); final IpConfiguration ipConfig = new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build(); - final IEthernetNetworkManagementListener listener = null; + final INetworkInterfaceOutcomeReceiver listener = null; tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener); waitForIdle(); From 1d36db9653bf832fb907b4d73687120ea95410f2 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 15 Mar 2022 16:17:50 +0000 Subject: [PATCH 869/881] Add Executors to NSD callbacks Add Executor variants to all methods with callbacks. Bug: 218752665 Test: atest NsdManagerTest Change-Id: I4c31e2d7ae601ea808b1fd64df32d116c6fff97f --- .../src/android/net/nsd/NsdManager.java | 152 +++++++++++++----- 1 file changed, 115 insertions(+), 37 deletions(-) diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java index 512fbcee93..209f372fd3 100644 --- a/framework-t/src/android/net/nsd/NsdManager.java +++ b/framework-t/src/android/net/nsd/NsdManager.java @@ -45,6 +45,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import java.util.Objects; +import java.util.concurrent.Executor; /** * The Network Service Discovery Manager class provides the API to discover services @@ -285,8 +286,12 @@ public final class NsdManager { private final Context mContext; private int mListenerKey = FIRST_LISTENER_KEY; + @GuardedBy("mMapLock") private final SparseArray mListenerMap = new SparseArray(); + @GuardedBy("mMapLock") private final SparseArray mServiceMap = new SparseArray<>(); + @GuardedBy("mMapLock") + private final SparseArray mExecutorMap = new SparseArray<>(); private final Object mMapLock = new Object(); // Map of listener key sent by client -> per-network discovery tracker @GuardedBy("mPerNetworkDiscoveryMap") @@ -299,6 +304,7 @@ public final class NsdManager { final String mServiceType; final int mProtocolType; final DiscoveryListener mBaseListener; + final Executor mBaseExecutor; final ArrayMap mPerNetworkListeners = new ArrayMap<>(); @@ -308,7 +314,8 @@ public final class NsdManager { final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener( network, mBaseListener); mPerNetworkListeners.put(network, wrappedListener); - discoverServices(mServiceType, mProtocolType, network, wrappedListener); + discoverServices(mServiceType, mProtocolType, network, mBaseExecutor, + wrappedListener); } @Override @@ -355,9 +362,10 @@ public final class NsdManager { } private PerNetworkDiscoveryTracker(String serviceType, int protocolType, - DiscoveryListener baseListener) { + Executor baseExecutor, DiscoveryListener baseListener) { mServiceType = serviceType; mProtocolType = protocolType; + mBaseExecutor = baseExecutor; mBaseListener = baseListener; } @@ -644,9 +652,11 @@ public final class NsdManager { final int key = message.arg2; final Object listener; final NsdServiceInfo ns; + final Executor executor; synchronized (mMapLock) { listener = mListenerMap.get(key); ns = mServiceMap.get(key); + executor = mExecutorMap.get(key); } if (listener == null) { Log.d(TAG, "Stale key " + message.arg2); @@ -657,56 +667,64 @@ public final class NsdManager { } switch (what) { case DISCOVER_SERVICES_STARTED: - String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); - ((DiscoveryListener) listener).onDiscoveryStarted(s); + final String s = getNsdServiceInfoType((NsdServiceInfo) message.obj); + executor.execute(() -> ((DiscoveryListener) listener).onDiscoveryStarted(s)); break; case DISCOVER_SERVICES_FAILED: removeListener(key); - ((DiscoveryListener) listener).onStartDiscoveryFailed(getNsdServiceInfoType(ns), - message.arg1); + executor.execute(() -> ((DiscoveryListener) listener).onStartDiscoveryFailed( + getNsdServiceInfoType(ns), message.arg1)); break; case SERVICE_FOUND: - ((DiscoveryListener) listener).onServiceFound((NsdServiceInfo) message.obj); + executor.execute(() -> ((DiscoveryListener) listener).onServiceFound( + (NsdServiceInfo) message.obj)); break; case SERVICE_LOST: - ((DiscoveryListener) listener).onServiceLost((NsdServiceInfo) message.obj); + executor.execute(() -> ((DiscoveryListener) listener).onServiceLost( + (NsdServiceInfo) message.obj)); break; case STOP_DISCOVERY_FAILED: // TODO: failure to stop discovery should be internal and retried internally, as // the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED removeListener(key); - ((DiscoveryListener) listener).onStopDiscoveryFailed(getNsdServiceInfoType(ns), - message.arg1); + executor.execute(() -> ((DiscoveryListener) listener).onStopDiscoveryFailed( + getNsdServiceInfoType(ns), message.arg1)); break; case STOP_DISCOVERY_SUCCEEDED: removeListener(key); - ((DiscoveryListener) listener).onDiscoveryStopped(getNsdServiceInfoType(ns)); + executor.execute(() -> ((DiscoveryListener) listener).onDiscoveryStopped( + getNsdServiceInfoType(ns))); break; case REGISTER_SERVICE_FAILED: removeListener(key); - ((RegistrationListener) listener).onRegistrationFailed(ns, message.arg1); + executor.execute(() -> ((RegistrationListener) listener).onRegistrationFailed( + ns, message.arg1)); break; case REGISTER_SERVICE_SUCCEEDED: - ((RegistrationListener) listener).onServiceRegistered( - (NsdServiceInfo) message.obj); + executor.execute(() -> ((RegistrationListener) listener).onServiceRegistered( + (NsdServiceInfo) message.obj)); break; case UNREGISTER_SERVICE_FAILED: removeListener(key); - ((RegistrationListener) listener).onUnregistrationFailed(ns, message.arg1); + executor.execute(() -> ((RegistrationListener) listener).onUnregistrationFailed( + ns, message.arg1)); break; case UNREGISTER_SERVICE_SUCCEEDED: // TODO: do not unregister listener until service is unregistered, or provide // alternative way for unregistering ? removeListener(message.arg2); - ((RegistrationListener) listener).onServiceUnregistered(ns); + executor.execute(() -> ((RegistrationListener) listener).onServiceUnregistered( + ns)); break; case RESOLVE_SERVICE_FAILED: removeListener(key); - ((ResolveListener) listener).onResolveFailed(ns, message.arg1); + executor.execute(() -> ((ResolveListener) listener).onResolveFailed( + ns, message.arg1)); break; case RESOLVE_SERVICE_SUCCEEDED: removeListener(key); - ((ResolveListener) listener).onServiceResolved((NsdServiceInfo) message.obj); + executor.execute(() -> ((ResolveListener) listener).onServiceResolved( + (NsdServiceInfo) message.obj)); break; default: Log.d(TAG, "Ignored " + message); @@ -722,7 +740,7 @@ public final class NsdManager { } // Assert that the listener is not in the map, then add it and returns its key - private int putListener(Object listener, NsdServiceInfo s) { + private int putListener(Object listener, Executor e, NsdServiceInfo s) { checkListener(listener); final int key; synchronized (mMapLock) { @@ -733,6 +751,7 @@ public final class NsdManager { key = nextListenerKey(); mListenerMap.put(key, listener); mServiceMap.put(key, s); + mExecutorMap.put(key, e); } return key; } @@ -741,6 +760,7 @@ public final class NsdManager { synchronized (mMapLock) { mListenerMap.remove(key); mServiceMap.remove(key); + mExecutorMap.remove(key); } } @@ -779,12 +799,33 @@ public final class NsdManager { */ public void registerService(NsdServiceInfo serviceInfo, int protocolType, RegistrationListener listener) { + registerService(serviceInfo, protocolType, Runnable::run, listener); + } + + /** + * Register a service to be discovered by other services. + * + *

The function call immediately returns after sending a request to register service + * to the framework. The application is notified of a successful registration + * through the callback {@link RegistrationListener#onServiceRegistered} or a failure + * through {@link RegistrationListener#onRegistrationFailed}. + * + *

The application should call {@link #unregisterService} when the service + * registration is no longer required, and/or whenever the application is stopped. + * @param serviceInfo The service being registered + * @param protocolType The service discovery protocol + * @param executor Executor to run listener callbacks with + * @param listener The listener notifies of a successful registration and is used to + * unregister this service through a call on {@link #unregisterService}. Cannot be null. + */ + public void registerService(@NonNull NsdServiceInfo serviceInfo, int protocolType, + @NonNull Executor executor, @NonNull RegistrationListener listener) { if (serviceInfo.getPort() <= 0) { throw new IllegalArgumentException("Invalid port number"); } checkServiceInfo(serviceInfo); checkProtocol(protocolType); - int key = putListener(listener, serviceInfo); + int key = putListener(listener, executor, serviceInfo); try { mService.registerService(key, serviceInfo); } catch (RemoteException e) { @@ -814,14 +855,6 @@ public final class NsdManager { } } - /** - * Same as {@link #discoverServices(String, int, Network, DiscoveryListener)} with a null - * {@link Network}. - */ - public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { - discoverServices(serviceType, protocolType, (Network) null, listener); - } - /** * Initiate service discovery to browse for instances of a service type. Service discovery * consumes network bandwidth and will continue until the application calls @@ -846,13 +879,45 @@ public final class NsdManager { * @param serviceType The service type being discovered. Examples include "_http._tcp" for * http services or "_ipp._tcp" for printers * @param protocolType The service discovery protocol - * @param network Network to discover services on, or null to discover on all available networks * @param listener The listener notifies of a successful discovery and is used * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. * Cannot be null. Cannot be in use for an active service discovery. */ + public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) { + discoverServices(serviceType, protocolType, (Network) null, Runnable::run, listener); + } + + /** + * Initiate service discovery to browse for instances of a service type. Service discovery + * consumes network bandwidth and will continue until the application calls + * {@link #stopServiceDiscovery}. + * + *

The function call immediately returns after sending a request to start service + * discovery to the framework. The application is notified of a success to initiate + * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure + * through {@link DiscoveryListener#onStartDiscoveryFailed}. + * + *

Upon successful start, application is notified when a service is found with + * {@link DiscoveryListener#onServiceFound} or when a service is lost with + * {@link DiscoveryListener#onServiceLost}. + * + *

Upon failure to start, service discovery is not active and application does + * not need to invoke {@link #stopServiceDiscovery} + * + *

The application should call {@link #stopServiceDiscovery} when discovery of this + * service type is no longer required, and/or whenever the application is paused or + * stopped. + * @param serviceType The service type being discovered. Examples include "_http._tcp" for + * http services or "_ipp._tcp" for printers + * @param protocolType The service discovery protocol + * @param network Network to discover services on, or null to discover on all available networks + * @param executor Executor to run listener callbacks with + * @param listener The listener notifies of a successful discovery and is used + * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. + */ public void discoverServices(@NonNull String serviceType, int protocolType, - @Nullable Network network, @NonNull DiscoveryListener listener) { + @Nullable Network network, @NonNull Executor executor, + @NonNull DiscoveryListener listener) { if (TextUtils.isEmpty(serviceType)) { throw new IllegalArgumentException("Service type cannot be empty"); } @@ -862,7 +927,7 @@ public final class NsdManager { s.setServiceType(serviceType); s.setNetwork(network); - int key = putListener(listener, s); + int key = putListener(listener, executor, s); try { mService.discoverServices(key, s); } catch (RemoteException e) { @@ -899,18 +964,18 @@ public final class NsdManager { * themselves are encouraged to use this method instead of other overloads of * {@code discoverServices}, as they will receive proper notifications when a service becomes * available or unavailable due to network changes. - * * @param serviceType The service type being discovered. Examples include "_http._tcp" for * http services or "_ipp._tcp" for printers * @param protocolType The service discovery protocol * @param networkRequest Request specifying networks that should be considered when discovering + * @param executor Executor to run listener callbacks with * @param listener The listener notifies of a successful discovery and is used * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}. - * Cannot be null. Cannot be in use for an active service discovery. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void discoverServices(@NonNull String serviceType, int protocolType, - @NonNull NetworkRequest networkRequest, @NonNull DiscoveryListener listener) { + @NonNull NetworkRequest networkRequest, @NonNull Executor executor, + @NonNull DiscoveryListener listener) { if (TextUtils.isEmpty(serviceType)) { throw new IllegalArgumentException("Service type cannot be empty"); } @@ -920,10 +985,10 @@ public final class NsdManager { NsdServiceInfo s = new NsdServiceInfo(); s.setServiceType(serviceType); - final int baseListenerKey = putListener(listener, s); + final int baseListenerKey = putListener(listener, executor, s); final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker( - serviceType, protocolType, listener); + serviceType, protocolType, executor, listener); synchronized (mPerNetworkDiscoveryMap) { mPerNetworkDiscoveryMap.put(baseListenerKey, discoveryInfo); @@ -974,8 +1039,21 @@ public final class NsdManager { * Cannot be in use for an active service resolution. */ public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) { + resolveService(serviceInfo, Runnable::run, listener); + } + + /** + * Resolve a discovered service. An application can resolve a service right before + * establishing a connection to fetch the IP and port details on which to setup + * the connection. + * @param serviceInfo service to be resolved + * @param executor Executor to run listener callbacks with + * @param listener to receive callback upon success or failure. + */ + public void resolveService(@NonNull NsdServiceInfo serviceInfo, + @NonNull Executor executor, @NonNull ResolveListener listener) { checkServiceInfo(serviceInfo); - int key = putListener(listener, serviceInfo); + int key = putListener(listener, executor, serviceInfo); try { mService.resolveService(key, serviceInfo); } catch (RemoteException e) { From f4282112591ed65b3f71a18ada596ecdda7a6589 Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 16 Mar 2022 12:34:41 +0100 Subject: [PATCH 870/881] Fix ethernet enable / disable API The ethernet APIs connectNetwork() / disconnectNetwork() are inaccurately named. Physical link state cannot be changed by calling an API. This change renames these functions to enableInterface and disableInterface, respectively, to better reflect their intention and behavior. Test: atest EthernetManagerPermissionTest Merged-In: I3361ad0e01e761ffd77faf6c55924fa4612ede90 Change-Id: I3361ad0e01e761ffd77faf6c55924fa4612ede90 --- .../src/android/net/EthernetManager.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 4f61dbf38b..d2d49702cf 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -535,14 +535,13 @@ public class EthernetManager { } /** - * Set an ethernet network's link state up. + * Enable a network interface. * - * When the link is successfully turned up, the callback will be called with the network - * interface was torn down, if any. If any error or unexpected condition happens while the - * system tries to turn the interface down, the callback will be called with an appropriate - * exception. The callback is guaranteed to be called exactly once for each call to this method. + * Enables a previously disabled network interface. + * This function accepts an {@link OutcomeReceiver} that is called once the operation has + * finished execution. * - * @param iface the name of the interface to act upon. + * @param iface the name of the interface to enable. * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. * @param callback an optional {@link OutcomeReceiver} to listen for completion of the * operation. On success, {@link OutcomeReceiver#onResult} is called with the @@ -550,7 +549,6 @@ public class EthernetManager { * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. - * @throws UnsupportedOperationException if called on a non-automotive device. * @hide */ @SystemApi @@ -559,7 +557,7 @@ public class EthernetManager { android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) - public void connectNetwork( + public void enableInterface( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, @Nullable OutcomeReceiver callback) { @@ -574,14 +572,14 @@ public class EthernetManager { } /** - * Set an ethernet network's link state down. + * Disable a network interface. * - * When the link is successfully turned down, the callback will be called with the network - * interface was torn down, if any. If any error or unexpected condition happens while the - * system tries to turn the interface down, the callback will be called with an appropriate - * exception. The callback is guaranteed to be called exactly once for each call to this method. + * Disables the use of a network interface to fulfill network requests. If the interface + * currently serves a request, the network will be torn down. + * This function accepts an {@link OutcomeReceiver} that is called once the operation has + * finished execution. * - * @param iface the name of the interface to act upon. + * @param iface the name of the interface to disable. * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. * @param callback an optional {@link OutcomeReceiver} to listen for completion of the * operation. On success, {@link OutcomeReceiver#onResult} is called with the @@ -589,7 +587,6 @@ public class EthernetManager { * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. - * @throws UnsupportedOperationException if called on a non-automotive device. * @hide */ @SystemApi @@ -598,7 +595,7 @@ public class EthernetManager { android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE) - public void disconnectNetwork( + public void disableInterface( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, @Nullable OutcomeReceiver callback) { From c854d709b30bcf79d0dd910762eb0e8697d4b1d2 Mon Sep 17 00:00:00 2001 From: markchien Date: Thu, 17 Mar 2022 18:19:39 +0800 Subject: [PATCH 871/881] Add setEthernetEnabled and its listener API Bug: 171872016 Test: atest EthernetServiceTests Merged-In: Iefd24d955572589c5bd3ca9a8139ea6e44979e8a Change-Id: Iefd24d955572589c5bd3ca9a8139ea6e44979e8a --- .../src/android/net/EthernetManager.java | 151 +++++++++++++++--- .../src/android/net/IEthernetManager.aidl | 1 + .../android/net/IEthernetServiceListener.aidl | 1 + 3 files changed, 128 insertions(+), 25 deletions(-) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 4f61dbf38b..217d670743 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -41,6 +41,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.function.IntConsumer; /** * A class that manages and configures Ethernet interfaces. @@ -53,15 +54,31 @@ public class EthernetManager { private static final String TAG = "EthernetManager"; private final IEthernetManager mService; - @GuardedBy("mListeners") - private final ArrayList mListeners = new ArrayList<>(); + @GuardedBy("mListenerLock") + private final ArrayList> mIfaceListeners = + new ArrayList<>(); + @GuardedBy("mListenerLock") + private final ArrayList> mEthernetStateListeners = + new ArrayList<>(); + final Object mListenerLock = new Object(); private final IEthernetServiceListener.Stub mServiceListener = new IEthernetServiceListener.Stub() { + @Override + public void onEthernetStateChanged(int state) { + synchronized (mListenerLock) { + for (ListenerInfo li : mEthernetStateListeners) { + li.executor.execute(() -> { + li.listener.accept(state); + }); + } + } + } + @Override public void onInterfaceStateChanged(String iface, int state, int role, IpConfiguration configuration) { - synchronized (mListeners) { - for (ListenerInfo li : mListeners) { + synchronized (mListenerLock) { + for (ListenerInfo li : mIfaceListeners) { li.executor.execute(() -> li.listener.onInterfaceStateChanged(iface, state, role, configuration)); @@ -70,13 +87,29 @@ public class EthernetManager { } }; - private static class ListenerInfo { + /** + * Indicates that Ethernet is disabled. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int ETHERNET_STATE_DISABLED = 0; + + /** + * Indicates that Ethernet is enabled. + * + * @hide + */ + @SystemApi(client = MODULE_LIBRARIES) + public static final int ETHERNET_STATE_ENABLED = 1; + + private static class ListenerInfo { @NonNull public final Executor executor; @NonNull - public final InterfaceStateListener listener; + public final T listener; - private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) { + private ListenerInfo(@NonNull Executor executor, @NonNull T listener) { this.executor = executor; this.listener = listener; } @@ -289,18 +322,24 @@ public class EthernetManager { if (listener == null || executor == null) { throw new NullPointerException("listener and executor must not be null"); } - synchronized (mListeners) { - mListeners.add(new ListenerInfo(executor, listener)); - if (mListeners.size() == 1) { - try { - mService.addListener(mServiceListener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + synchronized (mListenerLock) { + maybeAddServiceListener(); + mIfaceListeners.add(new ListenerInfo(executor, listener)); } } + @GuardedBy("mListenerLock") + private void maybeAddServiceListener() { + if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return; + + try { + mService.addListener(mServiceListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + } + /** * Returns an array of available Ethernet interface names. * @hide @@ -323,15 +362,20 @@ public class EthernetManager { @SystemApi(client = MODULE_LIBRARIES) public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) { Objects.requireNonNull(listener); - synchronized (mListeners) { - mListeners.removeIf(l -> l.listener == listener); - if (mListeners.isEmpty()) { - try { - mService.removeListener(mServiceListener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + synchronized (mListenerLock) { + mIfaceListeners.removeIf(l -> l.listener == listener); + maybeRemoveServiceListener(); + } + } + + @GuardedBy("mListenerLock") + private void maybeRemoveServiceListener() { + if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return; + + try { + mService.removeListener(mServiceListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } } @@ -611,4 +655,61 @@ public class EthernetManager { throw e.rethrowFromSystemServer(); } } + + /** + * Change ethernet setting. + * + * @param enabled enable or disable ethernet settings. + * + * @hide + */ + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS}) + @SystemApi(client = MODULE_LIBRARIES) + public void setEthernetEnabled(boolean enabled) { + try { + mService.setEthernetEnabled(enabled); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Listen to changes in the state of ethernet. + * + * @param executor to run callbacks on. + * @param listener to listen ethernet state changed. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @SystemApi(client = MODULE_LIBRARIES) + public void addEthernetStateListener(@NonNull Executor executor, + @NonNull IntConsumer listener) { + Objects.requireNonNull(executor); + Objects.requireNonNull(listener); + synchronized (mListenerLock) { + maybeAddServiceListener(); + mEthernetStateListeners.add(new ListenerInfo(executor, listener)); + } + } + + /** + * Removes a listener. + * + * @param listener to listen ethernet state changed. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @SystemApi(client = MODULE_LIBRARIES) + public void removeEthernetStateListener(@NonNull IntConsumer listener) { + Objects.requireNonNull(listener); + synchronized (mListenerLock) { + mEthernetStateListeners.removeIf(l -> l.listener == listener); + maybeRemoveServiceListener(); + } + } } diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index 95ae907a3d..44e27e26f5 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -43,4 +43,5 @@ interface IEthernetManager in INetworkInterfaceOutcomeReceiver listener); void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); + void setEthernetEnabled(boolean enabled); } diff --git a/framework-t/src/android/net/IEthernetServiceListener.aidl b/framework-t/src/android/net/IEthernetServiceListener.aidl index 6d2ba03f78..751605bb38 100644 --- a/framework-t/src/android/net/IEthernetServiceListener.aidl +++ b/framework-t/src/android/net/IEthernetServiceListener.aidl @@ -21,6 +21,7 @@ import android.net.IpConfiguration; /** @hide */ oneway interface IEthernetServiceListener { + void onEthernetStateChanged(int state); void onInterfaceStateChanged(String iface, int state, int role, in IpConfiguration configuration); } From 332338bd75cdb391af3348c3f426d15fe6c9e756 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Thu, 17 Mar 2022 05:56:09 +0000 Subject: [PATCH 872/881] Add getInterfaceList module-lib API in EthernetManager. Bug: 171872016 Test: m Merged-In: Ib0e6c8f67c6ded7d17bb9e0ff49e7ff495c8819d Change-Id: I94fd147d0f8cf09cb7445fd2b5bc8e4528e8390e --- .../src/android/net/EthernetManager.java | 17 +++++++++++++++++ .../src/android/net/IEthernetManager.aidl | 3 +++ 2 files changed, 20 insertions(+) diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 217d670743..fc9f1c6366 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -39,6 +39,7 @@ import com.android.modules.utils.BackgroundThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; import java.util.function.IntConsumer; @@ -712,4 +713,20 @@ public class EthernetManager { maybeRemoveServiceListener(); } } + + /** + * Returns an array of existing Ethernet interface names regardless whether the interface + * is available or not currently. + * @hide + */ + @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) + @SystemApi(client = MODULE_LIBRARIES) + @NonNull + public List getInterfaceList() { + try { + return mService.getInterfaceList(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } } diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index 44e27e26f5..42e4c1ac55 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -23,6 +23,8 @@ import android.net.EthernetNetworkUpdateRequest; import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; +import java.util.List; + /** * Interface that answers queries about, and allows changing * ethernet configuration. @@ -44,4 +46,5 @@ interface IEthernetManager void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); void setEthernetEnabled(boolean enabled); + List getInterfaceList(); } From c606dbb66b0fa368271b1dbea8f3ec68d8cb508d Mon Sep 17 00:00:00 2001 From: James Mattis Date: Tue, 15 Mar 2022 21:42:10 -0700 Subject: [PATCH 873/881] Fixing multithreading issues in Ethernet Factory IP client callbacks could be executed updating the state of an ethernet interface even if they were no longer the callbacks for the currently active interface. This can happen as IP client callbacks were being called from a thread separate from ethernet. Bug: 224890356 Test: atest EthernetServiceTests atest CtsNetTestCasesLatestSdk :android.net.cts.EthernetManagerTest --iterations 30 Change-Id: I238cb75caa01472bccc79db5bafa82bccdaeba52 --- .../ethernet/EthernetNetworkFactory.java | 50 +++++++------- .../ethernet/EthernetNetworkFactoryTest.java | 66 ++++++++----------- 2 files changed, 53 insertions(+), 63 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 4f153553d9..9c3148b14c 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -439,24 +439,44 @@ public class EthernetNetworkFactory extends NetworkFactory { mIpClientShutdownCv.block(); } + // At the time IpClient is stopped, an IpClient event may have already been posted on + // the back of the handler and is awaiting execution. Once that event is executed, the + // associated callback object may not be valid anymore + // (NetworkInterfaceState#mIpClientCallback points to a different object / null). + private boolean isCurrentCallback() { + return this == mIpClientCallback; + } + + private void handleIpEvent(final @NonNull Runnable r) { + mHandler.post(() -> { + if (!isCurrentCallback()) { + Log.i(TAG, "Ignoring stale IpClientCallbacks " + this); + return; + } + r.run(); + }); + } + @Override public void onProvisioningSuccess(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStarted(newLp, mNetworkManagementListener)); + handleIpEvent(() -> onIpLayerStarted(newLp, mNetworkManagementListener)); } @Override public void onProvisioningFailure(LinkProperties newLp) { - mHandler.post(() -> onIpLayerStopped(mNetworkManagementListener)); + // This cannot happen due to provisioning timeout, because our timeout is 0. It can + // happen due to errors while provisioning or on provisioning loss. + handleIpEvent(() -> onIpLayerStopped(mNetworkManagementListener)); } @Override public void onLinkPropertiesChange(LinkProperties newLp) { - mHandler.post(() -> updateLinkProperties(newLp)); + handleIpEvent(() -> updateLinkProperties(newLp)); } @Override public void onReachabilityLost(String logMsg) { - mHandler.post(() -> updateNeighborLostEvent(logMsg)); + handleIpEvent(() -> updateNeighborLostEvent(logMsg)); } @Override @@ -558,14 +578,6 @@ public class EthernetNetworkFactory extends NetworkFactory { void onIpLayerStarted(@NonNull final LinkProperties linkProperties, @Nullable final INetworkInterfaceOutcomeReceiver listener) { - if(mIpClient == null) { - // This call comes from a message posted on the handler thread, but the IpClient has - // since been stopped such as may be the case if updateInterfaceLinkState() is - // queued on the handler thread prior. As network management callbacks are sent in - // stop(), there is no need to send them again here. - if (DBG) Log.d(TAG, "IpClient is not initialized."); - return; - } if (mNetworkAgent != null) { Log.e(TAG, "Already have a NetworkAgent - aborting new request"); stop(); @@ -601,12 +613,6 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStopped(@Nullable final INetworkInterfaceOutcomeReceiver listener) { - // This cannot happen due to provisioning timeout, because our timeout is 0. It can - // happen due to errors while provisioning or on provisioning loss. - if(mIpClient == null) { - if (DBG) Log.d(TAG, "IpClient is not initialized."); - return; - } // There is no point in continuing if the interface is gone as stop() will be triggered // by removeInterface() when processed on the handler thread and start() won't // work for a non-existent interface. @@ -648,10 +654,6 @@ public class EthernetNetworkFactory extends NetworkFactory { } void updateLinkProperties(LinkProperties linkProperties) { - if(mIpClient == null) { - if (DBG) Log.d(TAG, "IpClient is not initialized."); - return; - } mLinkProperties = linkProperties; if (mNetworkAgent != null) { mNetworkAgent.sendLinkPropertiesImpl(linkProperties); @@ -659,10 +661,6 @@ public class EthernetNetworkFactory extends NetworkFactory { } void updateNeighborLostEvent(String logMsg) { - if(mIpClient == null) { - if (DBG) Log.d(TAG, "IpClient is not initialized."); - return; - } Log.i(TAG, "updateNeighborLostEvent " + logMsg); // Reachability lost will be seen only if the gateway is not reachable. // Since ethernet FW doesn't have the mechanism to scan for new networks diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index 2d5bd1d988..4d3e4d36d2 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -21,6 +21,7 @@ import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -543,68 +544,59 @@ public class EthernetNetworkFactoryTest { verifyRestart(createDefaultIpConfig()); } - @Test - public void testIgnoreOnIpLayerStartedCallbackAfterIpClientHasStopped() throws Exception { - initEthernetNetworkFactory(); + private IpClientCallbacks getStaleIpClientCallbacks() throws Exception { createAndVerifyProvisionedInterface(TEST_IFACE); - mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); - mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); - mLooper.dispatchAll(); + final IpClientCallbacks staleIpClientCallbacks = mIpClientCallbacks; + mNetFactory.removeInterface(TEST_IFACE); verifyStop(); + assertNotSame(mIpClientCallbacks, staleIpClientCallbacks); + return staleIpClientCallbacks; + } + + @Test + public void testIgnoreOnIpLayerStartedCallbackForStaleCallback() throws Exception { + initEthernetNetworkFactory(); + final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); + + staleIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); + mLooper.dispatchAll(); - // ipClient has been shut down first, we should not retry verify(mIpClient, never()).startProvisioning(any()); verify(mNetworkAgent, never()).register(); } @Test - public void testIgnoreOnIpLayerStoppedCallbackAfterIpClientHasStopped() throws Exception { + public void testIgnoreOnIpLayerStoppedCallbackForStaleCallback() throws Exception { initEthernetNetworkFactory(); - createAndVerifyProvisionedInterface(TEST_IFACE); when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); - mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); - mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); - mLooper.dispatchAll(); - verifyStop(); + final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); - // ipClient has been shut down first, we should not retry - verify(mIpClient).startProvisioning(any()); + staleIpClientCallbacks.onProvisioningFailure(new LinkProperties()); + mLooper.dispatchAll(); + + verify(mIpClient, never()).startProvisioning(any()); } @Test - public void testIgnoreLinkPropertiesCallbackAfterIpClientHasStopped() throws Exception { + public void testIgnoreLinkPropertiesCallbackForStaleCallback() throws Exception { initEthernetNetworkFactory(); - createAndVerifyProvisionedInterface(TEST_IFACE); - LinkProperties lp = new LinkProperties(); + final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); + final LinkProperties lp = new LinkProperties(); - // The test requires the two proceeding methods to happen one after the other in ENF and - // verifies onLinkPropertiesChange doesn't complete execution for a downed interface. - // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks - // to null which will throw an NPE in the test if executed synchronously. - mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER)); - mIpClientCallbacks.onLinkPropertiesChange(lp); + staleIpClientCallbacks.onLinkPropertiesChange(lp); mLooper.dispatchAll(); - verifyStop(); - // ipClient has been shut down first, we should not update - verify(mNetworkAgent, never()).sendLinkPropertiesImpl(same(lp)); + verify(mNetworkAgent, never()).sendLinkPropertiesImpl(eq(lp)); } @Test - public void testIgnoreNeighborLossCallbackAfterIpClientHasStopped() throws Exception { + public void testIgnoreNeighborLossCallbackForStaleCallback() throws Exception { initEthernetNetworkFactory(); - createAndVerifyProvisionedInterface(TEST_IFACE); + final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); - // The test requires the two proceeding methods to happen one after the other in ENF and - // verifies onReachabilityLost doesn't complete execution for a downed interface. - // Posting is necessary as updateInterfaceLinkState with false will set mIpClientCallbacks - // to null which will throw an NPE in the test if executed synchronously. - mHandler.post(() -> mNetFactory.updateInterfaceLinkState(TEST_IFACE, false, NULL_LISTENER)); - mIpClientCallbacks.onReachabilityLost("Neighbor Lost"); + staleIpClientCallbacks.onReachabilityLost("Neighbor Lost"); mLooper.dispatchAll(); - verifyStop(); - // ipClient has been shut down first, we should not update verify(mIpClient, never()).startProvisioning(any()); verify(mNetworkAgent, never()).register(); } From cd032406be861aaea980ef850142a8076a638c8f Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 16 Mar 2022 20:15:18 +0100 Subject: [PATCH 874/881] Change Ethernet API to use OutcomeReceiver This change addresses API review feedback. In addition, it changes the returned result from Network to the interface name. The current API returning a Network object is racy and cannot be implemented correctly. Users should instead use the ConnectivityManager#requestNetwork() API to get hold of the Network for a given interface. CP note: the Merged-In ID is not the actual Change-Id of this change in tm-dev. This change was originally merged in aosp, but was subsequently reverted and cherry-picked into tm-dev. The cherry-pick falsely reused the Change-Id of the (now reverted) original change. This causes automerger to skip this change on all branches between aosp-master and tm-dev when the correct Merged-In ID is used. Therefore, the Merged-In ID listed is the Change-Id of an unrelated change that is present in tm-dev but not aosp-master. Bug: 220017952 Test: TH Ignore-AOSP-First: CP to make automerger happy. Merged-In: I61c5209f50ab62327b75813804bde1aa1a014054 Change-Id: I4c204a8489c0be006c00581d833f2bb46ae0e71d --- framework-t/api/system-current.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/framework-t/api/system-current.txt b/framework-t/api/system-current.txt index 0149115e16..e110155a93 100644 --- a/framework-t/api/system-current.txt +++ b/framework-t/api/system-current.txt @@ -13,10 +13,10 @@ package android.app.usage { package android.net { public class EthernetManager { - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable android.os.OutcomeReceiver); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable android.os.OutcomeReceiver); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback); - method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer); + method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.os.OutcomeReceiver); } public static interface EthernetManager.TetheredInterfaceCallback { From a096a664bb116793451d884892b910743d2adb2a Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 16 Mar 2022 10:49:18 +0100 Subject: [PATCH 875/881] Change network management listener to outcome receiver Adopts new API according to API review feedback. The outcome receiver can later be removed from most of the ethernet code; in a perfect world, a result can be generated and an exception captured directly from EthernetServiceImpl. This will greatly simplify the current implementation. CP note: the Merged-In ID is not the actual Change-Id of this change in tm-dev. This change was originally merged in aosp, but was subsequently reverted and cherry-picked into tm-dev. The cherry-pick falsely reused the Change-Id of the (now reverted) original change. This causes automerger to skip this change on all branches between aosp-master and tm-dev when the correct Merged-In ID is used. Therefore, the Merged-In ID listed is the Change-Id of an unrelated change that is present in tm-dev but not aosp-master. Bug: 220017952 Test: atest EthernetServiceTests Ignore-AOSP-First: CP to make automerger happy. Merged-In: Iee4b48511ff668a2a7df90fd9bfe563d7ff23940 Change-Id: Id8fadfed9fcfd22f04f6d7c3460b5956e571e01f --- .../ethernet/EthernetNetworkFactory.java | 46 ++++++------ .../server/ethernet/EthernetServiceImpl.java | 8 +-- .../server/ethernet/EthernetTracker.java | 10 +-- .../ethernet/EthernetNetworkFactoryTest.java | 72 +++++++++---------- .../ethernet/EthernetServiceImplTest.java | 4 +- .../server/ethernet/EthernetTrackerTest.java | 6 +- 6 files changed, 71 insertions(+), 75 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index ef3abbaec0..4f153553d9 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -24,8 +24,8 @@ import android.net.ConnectivityManager; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.EthernetNetworkSpecifier; -import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; @@ -239,14 +239,14 @@ public class EthernetNetworkFactory extends NetworkFactory { * {@code null} is passed, then the network's current * {@link NetworkCapabilities} will be used in support of existing APIs as * the public API does not allow this. - * @param listener an optional {@link IEthernetNetworkManagementListener} to notify callers of + * @param listener an optional {@link INetworkInterfaceOutcomeReceiver} to notify callers of * completion. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected void updateInterface(@NonNull final String ifaceName, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return; @@ -295,7 +295,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) protected boolean updateInterfaceLinkState(@NonNull final String ifaceName, final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (!hasInterface(ifaceName)) { maybeSendNetworkManagementCallbackForUntracked(ifaceName, listener); return false; @@ -310,7 +310,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } private void maybeSendNetworkManagementCallbackForUntracked( - String ifaceName, IEthernetNetworkManagementListener listener) { + String ifaceName, INetworkInterfaceOutcomeReceiver listener) { maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( ifaceName + " can't be updated as it is not available.")); @@ -353,15 +353,19 @@ public class EthernetNetworkFactory extends NetworkFactory { } private static void maybeSendNetworkManagementCallback( - @Nullable final IEthernetNetworkManagementListener listener, - @Nullable final Network network, + @Nullable final INetworkInterfaceOutcomeReceiver listener, + @Nullable final String iface, @Nullable final EthernetNetworkManagementException e) { if (null == listener) { return; } try { - listener.onComplete(network, e); + if (iface != null) { + listener.onResult(iface); + } else { + listener.onError(e); + } } catch (RemoteException re) { Log.e(TAG, "Can't send onComplete for network management callback", re); } @@ -415,9 +419,9 @@ public class EthernetNetworkFactory extends NetworkFactory { private class EthernetIpClientCallback extends IpClientCallbacks { private final ConditionVariable mIpClientStartCv = new ConditionVariable(false); private final ConditionVariable mIpClientShutdownCv = new ConditionVariable(false); - @Nullable IEthernetNetworkManagementListener mNetworkManagementListener; + @Nullable INetworkInterfaceOutcomeReceiver mNetworkManagementListener; - EthernetIpClientCallback(@Nullable final IEthernetNetworkManagementListener listener) { + EthernetIpClientCallback(@Nullable final INetworkInterfaceOutcomeReceiver listener) { mNetworkManagementListener = listener; } @@ -502,7 +506,7 @@ public class EthernetNetworkFactory extends NetworkFactory { void updateInterface(@Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) { Log.d(TAG, "updateInterface, iface: " + name + ", ipConfig: " + ipConfig + ", old ipConfig: " + mIpConfig @@ -533,7 +537,7 @@ public class EthernetNetworkFactory extends NetworkFactory { start(null); } - private void start(@Nullable final IEthernetNetworkManagementListener listener) { + private void start(@Nullable final INetworkInterfaceOutcomeReceiver listener) { if (mIpClient != null) { if (DBG) Log.d(TAG, "IpClient already started"); return; @@ -553,7 +557,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } void onIpLayerStarted(@NonNull final LinkProperties linkProperties, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if(mIpClient == null) { // This call comes from a message posted on the handler thread, but the IpClient has // since been stopped such as may be the case if updateInterfaceLinkState() is @@ -593,10 +597,10 @@ public class EthernetNetworkFactory extends NetworkFactory { }); mNetworkAgent.register(); mNetworkAgent.markConnected(); - realizeNetworkManagementCallback(mNetworkAgent.getNetwork(), null); + realizeNetworkManagementCallback(name, null); } - void onIpLayerStopped(@Nullable final IEthernetNetworkManagementListener listener) { + void onIpLayerStopped(@Nullable final INetworkInterfaceOutcomeReceiver listener) { // This cannot happen due to provisioning timeout, because our timeout is 0. It can // happen due to errors while provisioning or on provisioning loss. if(mIpClient == null) { @@ -622,7 +626,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } // Must be called on the handler thread - private void realizeNetworkManagementCallback(@Nullable final Network network, + private void realizeNetworkManagementCallback(@Nullable final String iface, @Nullable final EthernetNetworkManagementException e) { ensureRunningOnEthernetHandlerThread(); if (null == mIpClientCallback) { @@ -630,7 +634,7 @@ public class EthernetNetworkFactory extends NetworkFactory { } EthernetNetworkFactory.maybeSendNetworkManagementCallback( - mIpClientCallback.mNetworkManagementListener, network, e); + mIpClientCallback.mNetworkManagementListener, iface, e); // Only send a single callback per listener. mIpClientCallback.mNetworkManagementListener = null; } @@ -671,7 +675,7 @@ public class EthernetNetworkFactory extends NetworkFactory { /** Returns true if state has been modified */ boolean updateLinkState(final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (mLinkUp == up) { EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, null, new EthernetNetworkManagementException( @@ -681,13 +685,11 @@ public class EthernetNetworkFactory extends NetworkFactory { mLinkUp = up; if (!up) { // was up, goes down - // Save an instance of the current network to use with the callback before stop(). - final Network network = mNetworkAgent != null ? mNetworkAgent.getNetwork() : null; // Send an abort on a provisioning request callback if necessary before stopping. maybeSendNetworkManagementCallbackForAbort(); stop(); // If only setting the interface down, send a callback to signal completion. - EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, network, null); + EthernetNetworkFactory.maybeSendNetworkManagementCallback(listener, name, null); } else { // was down, goes up stop(); start(listener); @@ -742,7 +744,7 @@ public class EthernetNetworkFactory extends NetworkFactory { restart(null); } - void restart(@Nullable final IEthernetNetworkManagementListener listener){ + void restart(@Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) Log.d(TAG, "reconnecting Ethernet"); stop(); start(listener); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index 50b46845be..edda321494 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -24,7 +24,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.IEthernetManager; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; @@ -243,7 +243,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void updateConfiguration(@NonNull final String iface, @NonNull final EthernetNetworkUpdateRequest request, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Objects.requireNonNull(iface); Objects.requireNonNull(request); throwIfEthernetNotStarted(); @@ -260,7 +260,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void connectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Log.i(TAG, "connectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); @@ -272,7 +272,7 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { @Override public void disconnectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { Log.i(TAG, "disconnectNetwork called with: iface=" + iface + ", listener=" + listener); Objects.requireNonNull(iface); throwIfEthernetNotStarted(); diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 074c81bcb0..0a0e327f45 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -27,7 +27,7 @@ import android.content.res.Resources; import android.net.ConnectivityResources; import android.net.EthernetManager; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.INetd; import android.net.ITetheredInterfaceCallback; import android.net.InterfaceConfigurationParcel; @@ -291,7 +291,7 @@ public class EthernetTracker { protected void updateConfiguration(@NonNull final String iface, @Nullable final IpConfiguration ipConfig, @Nullable final NetworkCapabilities capabilities, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { if (DBG) { Log.i(TAG, "updateConfiguration, iface: " + iface + ", capabilities: " + capabilities + ", ipConfig: " + ipConfig); @@ -314,13 +314,13 @@ public class EthernetTracker { @VisibleForTesting(visibility = PACKAGE) protected void connectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { mHandler.post(() -> updateInterfaceState(iface, true, listener)); } @VisibleForTesting(visibility = PACKAGE) protected void disconnectNetwork(@NonNull final String iface, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { mHandler.post(() -> updateInterfaceState(iface, false, listener)); } @@ -505,7 +505,7 @@ public class EthernetTracker { } private void updateInterfaceState(@NonNull final String iface, final boolean up, - @Nullable final IEthernetNetworkManagementListener listener) { + @Nullable final INetworkInterfaceOutcomeReceiver listener) { final int mode = getInterfaceMode(iface); final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) && mFactory.updateInterfaceLinkState(iface, up, listener); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java index e256add891..2d5bd1d988 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetNetworkFactoryTest.java @@ -41,8 +41,8 @@ import android.content.Context; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.EthernetNetworkSpecifier; -import android.net.IEthernetNetworkManagementListener; import android.net.EthernetNetworkManagementException; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.IpConfiguration; import android.net.LinkAddress; import android.net.LinkProperties; @@ -85,7 +85,7 @@ import java.util.concurrent.TimeUnit; public class EthernetNetworkFactoryTest { private static final int TIMEOUT_MS = 2_000; private static final String TEST_IFACE = "test123"; - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private static final String IP_ADDR = "192.0.2.2/25"; private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); private static final String HW_ADDR = "01:02:03:04:05:06"; @@ -316,7 +316,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verify(mIpClient).shutdown(); - assertSuccessfulListener(listener, null); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -330,7 +330,7 @@ public class EthernetNetworkFactoryTest { assertTrue(ret); verifyStop(); - assertSuccessfulListener(listener, mMockNetwork); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -347,7 +347,7 @@ public class EthernetNetworkFactoryTest { verify(mDeps, never()).makeIpClient(any(), any(), any()); verify(mDeps, never()) .makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); - assertSuccessfulListener(listener, null); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @Test @@ -361,7 +361,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - assertFailedListener(listener, "can't be updated as it is not available"); + listener.expectOnErrorWithMessage("can't be updated as it is not available"); } @Test @@ -375,7 +375,7 @@ public class EthernetNetworkFactoryTest { assertFalse(ret); verifyNoStopOrStart(); - assertFailedListener(listener, "No changes"); + listener.expectOnErrorWithMessage("No changes"); } @Test @@ -632,18 +632,31 @@ public class EthernetNetworkFactoryTest { } private static final class TestNetworkManagementListener - implements IEthernetNetworkManagementListener { - private final CompletableFuture> mDone - = new CompletableFuture<>(); + implements INetworkInterfaceOutcomeReceiver { + private final CompletableFuture mResult = new CompletableFuture<>(); + private final CompletableFuture mError = + new CompletableFuture<>(); @Override - public void onComplete(final Network network, - final EthernetNetworkManagementException exception) { - mDone.complete(new Pair<>(network, exception)); + public void onResult(@NonNull String iface) { + mResult.complete(iface); } - Pair expectOnComplete() throws Exception { - return mDone.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + @Override + public void onError(@NonNull EthernetNetworkManagementException exception) { + mError.complete(exception); + } + + String expectOnResult() throws Exception { + return mResult.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + EthernetNetworkManagementException expectOnError() throws Exception { + return mError.get(TIMEOUT_MS, TimeUnit.MILLISECONDS); + } + + void expectOnErrorWithMessage(String msg) throws Exception { + assertTrue(expectOnError().getMessage().contains(msg)); } @Override @@ -663,7 +676,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - assertSuccessfulListener(listener, mMockNetwork); + assertEquals(listener.expectOnResult(), TEST_IFACE); } @DevSdkIgnoreRule.IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available @@ -703,26 +716,7 @@ public class EthernetNetworkFactoryTest { triggerOnProvisioningSuccess(); }); - assertSuccessfulListener(successfulListener, mMockNetwork); - } - - private void assertSuccessfulListener( - @NonNull final TestNetworkManagementListener successfulListener, - @NonNull final Network expectedNetwork) throws Exception { - final Pair successfulResult = - successfulListener.expectOnComplete(); - assertEquals(expectedNetwork, successfulResult.first); - assertNull(successfulResult.second); - } - - private void assertFailedListener(@NonNull final TestNetworkManagementListener failedListener, - @NonNull final String errMsg) - throws Exception { - final Pair failedResult = - failedListener.expectOnComplete(); - assertNull(failedResult.first); - assertNotNull(failedResult.second); - assertTrue(failedResult.second.getMessage().contains(errMsg)); + assertEquals(successfulListener.expectOnResult(), TEST_IFACE); } private void verifyNetworkManagementCallIsAbortedWhenInterrupted( @@ -737,7 +731,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(iface, ipConfiguration, capabilities, failedListener); interruptingRunnable.run(); - assertFailedListener(failedListener, "aborted"); + failedListener.expectOnErrorWithMessage("aborted"); } @Test @@ -751,7 +745,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); triggerOnProvisioningSuccess(); - listener.expectOnComplete(); + assertEquals(listener.expectOnResult(), TEST_IFACE); verify(mDeps).makeEthernetNetworkAgent(any(), any(), eq(capabilities), any(), any(), any(), any()); verifyRestart(ipConfiguration); @@ -768,7 +762,7 @@ public class EthernetNetworkFactoryTest { mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities, listener); verifyNoStopOrStart(); - assertFailedListener(listener, "can't be updated as it is not available"); + listener.expectOnErrorWithMessage("can't be updated as it is not available"); } @Test diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index 2131f7fcdb..e67c4c8b95 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -32,7 +32,7 @@ import android.Manifest; import android.annotation.NonNull; import android.content.Context; import android.content.pm.PackageManager; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.EthernetNetworkUpdateRequest; import android.net.IpConfiguration; import android.net.NetworkCapabilities; @@ -64,7 +64,7 @@ public class EthernetServiceImplTest { new EthernetNetworkUpdateRequest.Builder() .setNetworkCapabilities(new NetworkCapabilities.Builder().build()) .build(); - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private EthernetServiceImpl mEthernetServiceImpl; @Mock private Context mContext; @Mock private Handler mHandler; diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index ef70d94391..bab9643d23 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -33,7 +33,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; import android.net.InetAddresses; -import android.net.IEthernetNetworkManagementListener; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.INetd; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; @@ -66,7 +66,7 @@ public class EthernetTrackerTest { private static final String TEST_IFACE = "test123"; private static final int TIMEOUT_MS = 1_000; private static final String THREAD_NAME = "EthernetServiceThread"; - private static final IEthernetNetworkManagementListener NULL_LISTENER = null; + private static final INetworkInterfaceOutcomeReceiver NULL_LISTENER = null; private EthernetTracker tracker; private HandlerThread mHandlerThread; @Mock private Context mContext; @@ -334,7 +334,7 @@ public class EthernetTrackerTest { new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build(); final IpConfiguration ipConfig = new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build(); - final IEthernetNetworkManagementListener listener = null; + final INetworkInterfaceOutcomeReceiver listener = null; tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener); waitForIdle(); From 2e6c345418b840a22a83b89946c52f9c18bd197e Mon Sep 17 00:00:00 2001 From: Patrick Rohr Date: Wed, 16 Mar 2022 11:31:06 +0100 Subject: [PATCH 876/881] Change Ethernet API to use OutcomeReceiver This change addresses API review feedback. In addition, it changes the returned result from Network to the interface name. The current API returning a Network object is racy and cannot be implemented correctly. Users should instead use the ConnectivityManager#requestNetwork() API to get hold of the Network for a given interface. CP note: the Merged-In ID is not the actual Change-Id of this change in tm-dev. This change was originally merged in aosp, but was subsequently reverted and cherry-picked into tm-dev. The cherry-pick falsely reused the Change-Id of the (now reverted) original change. This causes automerger to skip this change on all branches between aosp-master and tm-dev when the correct Merged-In ID is used. Therefore, the Merged-In ID listed is the Change-Id of an unrelated change that is present in tm-dev but not aosp-master. Bug: 220017952 Test: TH Ignore-AOSP-First: CP to make automerger happy. Merged-In: Iefd24d955572589c5bd3ca9a8139ea6e44979e8a Change-Id: I7c46545a47034be409071c2ec007d9e1480c6ed0 --- framework-t/Sources.bp | 2 +- .../src/android/net/EthernetManager.java | 102 ++++++++++-------- .../src/android/net/IEthernetManager.aidl | 9 +- ... => INetworkInterfaceOutcomeReceiver.aidl} | 6 +- 4 files changed, 66 insertions(+), 53 deletions(-) rename framework-t/src/android/net/{IEthernetNetworkManagementListener.aidl => INetworkInterfaceOutcomeReceiver.aidl} (80%) diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index 217a1f67c3..bc27852857 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -131,8 +131,8 @@ filegroup { "src/android/net/EthernetNetworkUpdateRequest.java", "src/android/net/EthernetNetworkUpdateRequest.aidl", "src/android/net/IEthernetManager.aidl", - "src/android/net/IEthernetNetworkManagementListener.aidl", "src/android/net/IEthernetServiceListener.aidl", + "src/android/net/INetworkInterfaceOutcomeReceiver.aidl", "src/android/net/ITetheredInterfaceCallback.aidl", ], path: "src", diff --git a/framework-t/src/android/net/EthernetManager.java b/framework-t/src/android/net/EthernetManager.java index 793f28d5aa..4f61dbf38b 100644 --- a/framework-t/src/android/net/EthernetManager.java +++ b/framework-t/src/android/net/EthernetManager.java @@ -30,6 +30,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; +import android.os.OutcomeReceiver; import android.os.RemoteException; import com.android.internal.annotations.GuardedBy; @@ -40,7 +41,6 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Executor; -import java.util.function.BiConsumer; /** * A class that manages and configures Ethernet interfaces. @@ -443,41 +443,45 @@ public class EthernetManager { return new TetheredInterfaceRequest(mService, cbInternal); } - private static final class InternalNetworkManagementListener - extends IEthernetNetworkManagementListener.Stub { + private static final class NetworkInterfaceOutcomeReceiver + extends INetworkInterfaceOutcomeReceiver.Stub { @NonNull private final Executor mExecutor; @NonNull - private final BiConsumer mListener; + private final OutcomeReceiver mCallback; - InternalNetworkManagementListener( + NetworkInterfaceOutcomeReceiver( @NonNull final Executor executor, - @NonNull final BiConsumer listener) { + @NonNull final OutcomeReceiver + callback) { Objects.requireNonNull(executor, "Pass a non-null executor"); - Objects.requireNonNull(listener, "Pass a non-null listener"); + Objects.requireNonNull(callback, "Pass a non-null callback"); mExecutor = executor; - mListener = listener; + mCallback = callback; } @Override - public void onComplete( - @Nullable final Network network, - @Nullable final EthernetNetworkManagementException e) { - mExecutor.execute(() -> mListener.accept(network, e)); + public void onResult(@NonNull String iface) { + mExecutor.execute(() -> mCallback.onResult(iface)); + } + + @Override + public void onError(@NonNull EthernetNetworkManagementException e) { + mExecutor.execute(() -> mCallback.onError(e)); } } - private InternalNetworkManagementListener getInternalNetworkManagementListener( + private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver( @Nullable final Executor executor, - @Nullable final BiConsumer listener) { - if (null != listener) { - Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener"); + @Nullable final OutcomeReceiver callback) { + if (null != callback) { + Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback"); } - final InternalNetworkManagementListener proxy; - if (null == listener) { + final NetworkInterfaceOutcomeReceiver proxy; + if (null == callback) { proxy = null; } else { - proxy = new InternalNetworkManagementListener(executor, listener); + proxy = new NetworkInterfaceOutcomeReceiver(executor, callback); } return proxy; } @@ -492,14 +496,17 @@ public class EthernetManager { * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities} * object for this network to put inside the {@code request}. * - * If non-null, the listener will be called exactly once after this is called, unless - * a synchronous exception was thrown. + * This function accepts an {@link OutcomeReceiver} that is called once the operation has + * finished execution. * * @param iface the name of the interface to act upon. * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device or on an @@ -515,11 +522,11 @@ public class EthernetManager { @NonNull String iface, @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); Objects.requireNonNull(request, "request must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.updateConfiguration(iface, request, proxy); } catch (RemoteException e) { @@ -530,15 +537,17 @@ public class EthernetManager { /** * Set an ethernet network's link state up. * - * When the link is successfully turned up, the listener will be called with the resulting - * network. If any error or unexpected condition happens while the system tries to turn the - * interface up, the listener will be called with an appropriate exception. - * The listener is guaranteed to be called exactly once for each call to this method, but this - * may take an unbounded amount of time depending on the actual network conditions. + * When the link is successfully turned up, the callback will be called with the network + * interface was torn down, if any. If any error or unexpected condition happens while the + * system tries to turn the interface down, the callback will be called with an appropriate + * exception. The callback is guaranteed to be called exactly once for each call to this method. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -553,10 +562,10 @@ public class EthernetManager { public void connectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.connectNetwork(iface, proxy); } catch (RemoteException e) { @@ -567,14 +576,17 @@ public class EthernetManager { /** * Set an ethernet network's link state down. * - * When the link is successfully turned down, the listener will be called with the network that - * was torn down, if any. If any error or unexpected condition happens while the system tries to - * turn the interface down, the listener will be called with an appropriate exception. - * The listener is guaranteed to be called exactly once for each call to this method. + * When the link is successfully turned down, the callback will be called with the network + * interface was torn down, if any. If any error or unexpected condition happens while the + * system tries to turn the interface down, the callback will be called with an appropriate + * exception. The callback is guaranteed to be called exactly once for each call to this method. * * @param iface the name of the interface to act upon. - * @param executor an {@link Executor} to execute the listener on. Optional if listener is null. - * @param listener an optional {@link BiConsumer} to listen for completion of the operation. + * @param executor an {@link Executor} to execute the callback on. Optional if callback is null. + * @param callback an optional {@link OutcomeReceiver} to listen for completion of the + * operation. On success, {@link OutcomeReceiver#onResult} is called with the + * interface name. On error, {@link OutcomeReceiver#onError} is called with more + * information about the error. * @throws SecurityException if the process doesn't hold * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}. * @throws UnsupportedOperationException if called on a non-automotive device. @@ -589,10 +601,10 @@ public class EthernetManager { public void disconnectNetwork( @NonNull String iface, @Nullable @CallbackExecutor Executor executor, - @Nullable BiConsumer listener) { + @Nullable OutcomeReceiver callback) { Objects.requireNonNull(iface, "iface must be non-null"); - final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener( - executor, listener); + final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver( + executor, callback); try { mService.disconnectNetwork(iface, proxy); } catch (RemoteException e) { diff --git a/framework-t/src/android/net/IEthernetManager.aidl b/framework-t/src/android/net/IEthernetManager.aidl index 544d02ba76..95ae907a3d 100644 --- a/framework-t/src/android/net/IEthernetManager.aidl +++ b/framework-t/src/android/net/IEthernetManager.aidl @@ -18,8 +18,9 @@ package android.net; import android.net.IpConfiguration; import android.net.IEthernetServiceListener; -import android.net.IEthernetNetworkManagementListener; +import android.net.EthernetNetworkManagementException; import android.net.EthernetNetworkUpdateRequest; +import android.net.INetworkInterfaceOutcomeReceiver; import android.net.ITetheredInterfaceCallback; /** @@ -39,7 +40,7 @@ interface IEthernetManager void requestTetheredInterface(in ITetheredInterfaceCallback callback); void releaseTetheredInterface(in ITetheredInterfaceCallback callback); void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request, - in IEthernetNetworkManagementListener listener); - void connectNetwork(String iface, in IEthernetNetworkManagementListener listener); - void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener); + in INetworkInterfaceOutcomeReceiver listener); + void connectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); + void disconnectNetwork(String iface, in INetworkInterfaceOutcomeReceiver listener); } diff --git a/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl b/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl similarity index 80% rename from framework-t/src/android/net/IEthernetNetworkManagementListener.aidl rename to framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl index 93edccfdaf..85795ead7a 100644 --- a/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl +++ b/framework-t/src/android/net/INetworkInterfaceOutcomeReceiver.aidl @@ -17,9 +17,9 @@ package android.net; import android.net.EthernetNetworkManagementException; -import android.net.Network; /** @hide */ -oneway interface IEthernetNetworkManagementListener { - void onComplete(in Network network, in EthernetNetworkManagementException exception); +oneway interface INetworkInterfaceOutcomeReceiver { + void onResult(in String iface); + void onError(in EthernetNetworkManagementException e); } \ No newline at end of file From e732c508822d98a218b70c2462db76e58bcadd39 Mon Sep 17 00:00:00 2001 From: markchien Date: Wed, 16 Mar 2022 15:59:33 +0800 Subject: [PATCH 877/881] Add global change ethernet state API Provide a new API to enable or disable ethernet. Also have a listener for call to check whether enable state is sucessful. Bug: 171872016 Test: atest EthernetServiceTests Change-Id: Iee4b48511ff668a2a7df90fd9bfe563d7ff23940 Merged-In: Iee4b48511ff668a2a7df90fd9bfe563d7ff23940 --- .../ethernet/EthernetNetworkFactory.java | 9 ++- .../server/ethernet/EthernetServiceImpl.java | 8 +++ .../server/ethernet/EthernetTracker.java | 53 ++++++++++++++++ .../ethernet/EthernetServiceImplTest.java | 30 ++++++++++ .../server/ethernet/EthernetTrackerTest.java | 60 +++++++++++++++++++ 5 files changed, 157 insertions(+), 3 deletions(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java index 4f153553d9..342d5072a7 100644 --- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java +++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java @@ -183,7 +183,8 @@ public class EthernetNetworkFactory extends NetworkFactory { * Returns an array of available interface names. The array is sorted: unrestricted interfaces * goes first, then sorted by name. */ - String[] getAvailableInterfaces(boolean includeRestricted) { + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + protected String[] getAvailableInterfaces(boolean includeRestricted) { return mTrackingInterfaces.values() .stream() .filter(iface -> !iface.isRestricted() || includeRestricted) @@ -195,7 +196,8 @@ public class EthernetNetworkFactory extends NetworkFactory { .toArray(String[]::new); } - void addInterface(@NonNull final String ifaceName, @NonNull final String hwAddress, + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + protected void addInterface(@NonNull final String ifaceName, @NonNull final String hwAddress, @NonNull final IpConfiguration ipConfig, @NonNull final NetworkCapabilities capabilities) { if (mTrackingInterfaces.containsKey(ifaceName)) { @@ -282,7 +284,8 @@ public class EthernetNetworkFactory extends NetworkFactory { .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET).build(); } - void removeInterface(String interfaceName) { + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + protected void removeInterface(String interfaceName) { NetworkInterfaceState iface = mTrackingInterfaces.remove(interfaceName); if (iface != null) { iface.maybeSendNetworkManagementCallbackForAbort(); diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index edda321494..afed01a258 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -281,4 +281,12 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker.disconnectNetwork(iface, listener); } + + @Override + public void setEthernetEnabled(boolean enabled) { + PermissionUtils.enforceNetworkStackPermissionOr(mContext, + android.Manifest.permission.NETWORK_SETTINGS); + + mTracker.setEthernetEnabled(enabled); + } } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index 0a0e327f45..c38c900d03 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -16,6 +16,8 @@ package com.android.server.ethernet; +import static android.net.EthernetManager.ETHERNET_STATE_DISABLED; +import static android.net.EthernetManager.ETHERNET_STATE_ENABLED; import static android.net.TestNetworkManager.TEST_TAP_PREFIX; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; @@ -119,6 +121,8 @@ public class EthernetTracker { private boolean mTetheredInterfaceWasAvailable = false; private volatile IpConfiguration mIpConfigForDefaultInterface; + private int mEthernetState = ETHERNET_STATE_ENABLED; + private class TetheredInterfaceRequestList extends RemoteCallbackList { @Override @@ -355,6 +359,8 @@ public class EthernetTracker { for (String iface : getInterfaces(canUseRestrictedNetworks)) { unicastInterfaceStateChange(listener, iface); } + + unicastEthernetStateChange(listener, mEthernetState); }); } @@ -825,6 +831,53 @@ public class EthernetTracker { } } + @VisibleForTesting(visibility = PACKAGE) + protected void setEthernetEnabled(boolean enabled) { + mHandler.post(() -> { + int newState = enabled ? ETHERNET_STATE_ENABLED : ETHERNET_STATE_DISABLED; + if (mEthernetState == newState) return; + + mEthernetState = newState; + + if (enabled) { + trackAvailableInterfaces(); + } else { + // TODO: maybe also disable server mode interface as well. + untrackFactoryInterfaces(); + } + broadcastEthernetStateChange(mEthernetState); + }); + } + + private void untrackFactoryInterfaces() { + for (String iface : mFactory.getAvailableInterfaces(true /* includeRestricted */)) { + stopTrackingInterface(iface); + } + } + + private void unicastEthernetStateChange(@NonNull IEthernetServiceListener listener, + int state) { + ensureRunningOnEthernetServiceThread(); + try { + listener.onEthernetStateChanged(state); + } catch (RemoteException e) { + // Do nothing here. + } + } + + private void broadcastEthernetStateChange(int state) { + ensureRunningOnEthernetServiceThread(); + final int n = mListeners.beginBroadcast(); + for (int i = 0; i < n; i++) { + try { + mListeners.getBroadcastItem(i).onEthernetStateChanged(state); + } catch (RemoteException e) { + // Do nothing here. + } + } + mListeners.finishBroadcast(); + } + void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { postAndWaitForRunnable(() -> { pw.println(getClass().getSimpleName()); diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java index e67c4c8b95..dd1f1edba7 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetServiceImplTest.java @@ -19,12 +19,15 @@ package com.android.server.ethernet; import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -339,4 +342,31 @@ public class EthernetServiceImplTest { mEthernetServiceImpl.disconnectNetwork(TEST_IFACE, NULL_LISTENER); verify(mEthernetTracker).disconnectNetwork(eq(TEST_IFACE), eq(NULL_LISTENER)); } + + private void denyPermissions(String... permissions) { + for (String permission: permissions) { + doReturn(PackageManager.PERMISSION_DENIED).when(mContext) + .checkCallingOrSelfPermission(eq(permission)); + } + } + + @Test + public void testSetEthernetEnabled() { + denyPermissions(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + mEthernetServiceImpl.setEthernetEnabled(true); + verify(mEthernetTracker).setEthernetEnabled(true); + reset(mEthernetTracker); + + denyPermissions(Manifest.permission.NETWORK_STACK); + mEthernetServiceImpl.setEthernetEnabled(false); + verify(mEthernetTracker).setEthernetEnabled(false); + reset(mEthernetTracker); + + denyPermissions(Manifest.permission.NETWORK_SETTINGS); + try { + mEthernetServiceImpl.setEthernetEnabled(true); + fail("Should get SecurityException"); + } catch (SecurityException e) { } + verify(mEthernetTracker, never()).setEthernetEnabled(false); + } } diff --git a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java index bab9643d23..b1831c411b 100644 --- a/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java +++ b/tests/ethernet/java/com/android/server/ethernet/EthernetTrackerTest.java @@ -25,19 +25,26 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; +import android.net.EthernetManager; import android.net.InetAddresses; import android.net.INetworkInterfaceOutcomeReceiver; +import android.net.IEthernetServiceListener; import android.net.INetd; import android.net.IpConfiguration; import android.net.IpConfiguration.IpAssignment; import android.net.IpConfiguration.ProxySettings; +import android.net.InterfaceConfigurationParcel; import android.net.LinkAddress; import android.net.NetworkCapabilities; import android.net.StaticIpConfiguration; @@ -393,4 +400,57 @@ public class EthernetTrackerTest { assertTrue(isValidTestInterface); } + + public static class EthernetStateListener extends IEthernetServiceListener.Stub { + @Override + public void onEthernetStateChanged(int state) { } + + @Override + public void onInterfaceStateChanged(String iface, int state, int role, + IpConfiguration configuration) { } + } + + @Test + public void testListenEthernetStateChange() throws Exception { + final String testIface = "testtap123"; + final String testHwAddr = "11:22:33:44:55:66"; + final InterfaceConfigurationParcel ifaceParcel = new InterfaceConfigurationParcel(); + ifaceParcel.ifName = testIface; + ifaceParcel.hwAddr = testHwAddr; + ifaceParcel.flags = new String[] {INetd.IF_STATE_UP}; + + tracker.setIncludeTestInterfaces(true); + waitForIdle(); + + when(mNetd.interfaceGetList()).thenReturn(new String[] {testIface}); + when(mNetd.interfaceGetCfg(eq(testIface))).thenReturn(ifaceParcel); + doReturn(new String[] {testIface}).when(mFactory).getAvailableInterfaces(anyBoolean()); + doReturn(EthernetManager.STATE_LINK_UP).when(mFactory).getInterfaceState(eq(testIface)); + + final EthernetStateListener listener = spy(new EthernetStateListener()); + tracker.addListener(listener, true /* canUseRestrictedNetworks */); + // Check default state. + waitForIdle(); + verify(listener).onInterfaceStateChanged(eq(testIface), eq(EthernetManager.STATE_LINK_UP), + anyInt(), any()); + verify(listener).onEthernetStateChanged(eq(EthernetManager.ETHERNET_STATE_ENABLED)); + reset(listener); + + doReturn(EthernetManager.STATE_ABSENT).when(mFactory).getInterfaceState(eq(testIface)); + tracker.setEthernetEnabled(false); + waitForIdle(); + verify(mFactory).removeInterface(eq(testIface)); + verify(listener).onEthernetStateChanged(eq(EthernetManager.ETHERNET_STATE_DISABLED)); + verify(listener).onInterfaceStateChanged(eq(testIface), eq(EthernetManager.STATE_ABSENT), + anyInt(), any()); + reset(listener); + + doReturn(EthernetManager.STATE_LINK_UP).when(mFactory).getInterfaceState(eq(testIface)); + tracker.setEthernetEnabled(true); + waitForIdle(); + verify(mFactory).addInterface(eq(testIface), eq(testHwAddr), any(), any()); + verify(listener).onEthernetStateChanged(eq(EthernetManager.ETHERNET_STATE_ENABLED)); + verify(listener).onInterfaceStateChanged(eq(testIface), eq(EthernetManager.STATE_LINK_UP), + anyInt(), any()); + } } From 6e44855f90e05d8bab82da864f3ba1db40e69594 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Thu, 17 Mar 2022 05:57:25 +0000 Subject: [PATCH 878/881] Add getInterfaceList API implementation in Ethernet service. Bug: 171872016 Test: m Merged-In: I8eeb2cd211c6a2ec6bc997c5e18995b585c6118a Change-Id: Ic36d26be7dae5fd3f72abce3cea1ee845813a6e5 --- .../server/ethernet/EthernetServiceImpl.java | 7 +++++++ .../server/ethernet/EthernetTracker.java | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java index afed01a258..5e830ad83a 100644 --- a/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java +++ b/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java @@ -41,6 +41,7 @@ import com.android.net.module.util.PermissionUtils; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; @@ -289,4 +290,10 @@ public class EthernetServiceImpl extends IEthernetManager.Stub { mTracker.setEthernetEnabled(enabled); } + + @Override + public List getInterfaceList() { + PermissionUtils.enforceAccessNetworkStatePermission(mContext, TAG); + return mTracker.getInterfaceList(); + } } diff --git a/service-t/src/com/android/server/ethernet/EthernetTracker.java b/service-t/src/com/android/server/ethernet/EthernetTracker.java index c38c900d03..c291b3ff66 100644 --- a/service-t/src/com/android/server/ethernet/EthernetTracker.java +++ b/service-t/src/com/android/server/ethernet/EthernetTracker.java @@ -57,6 +57,7 @@ import com.android.net.module.util.PermissionUtils; import java.io.FileDescriptor; import java.net.InetAddress; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -90,7 +91,7 @@ public class EthernetTracker { * Interface names we track. This is a product-dependent regular expression, plus, * if setIncludeTestInterfaces is true, any test interfaces. */ - private String mIfaceMatch; + private volatile String mIfaceMatch; /** * Track test interfaces if true, don't track otherwise. */ @@ -341,6 +342,22 @@ public class EthernetTracker { return mFactory.getAvailableInterfaces(includeRestricted); } + List getInterfaceList() { + final List interfaceList = new ArrayList(); + final String[] ifaces; + try { + ifaces = mNetd.interfaceGetList(); + } catch (RemoteException e) { + Log.e(TAG, "Could not get list of interfaces " + e); + return interfaceList; + } + final String ifaceMatch = mIfaceMatch; + for (String iface : ifaces) { + if (iface.matches(ifaceMatch)) interfaceList.add(iface); + } + return interfaceList; + } + /** * Returns true if given interface was configured as restricted (doesn't have * NET_CAPABILITY_NOT_RESTRICTED) capability. Otherwise, returns false. From 3476030bad76003498ebc1b0e07bd6542c02ae22 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 8 Mar 2022 19:49:49 +0900 Subject: [PATCH 879/881] Use Sources.bp for building Reference Sources.bp from Android.bp, so that they are used as build files. Sources.bp is separate from Android.bp as it was migrated from the Android.bp files in the old code location. They can be merged into the main Android.bp file (or removed by removing the filegroups) after the migration is done. Also remove references to the AIDL filegroups, as files are now merged into the common framework/aidl-export directory which is used as include directory for aidl source generation already, so they do not need to be referenced separately. framework/aidl-export can contain AIDLs for S- API classes that became updatable API in T (the contents of framework-t), as they are the same as any other API class for the purposes of AIDL code generation: it's OK for any S+ code to reference S+ API classes. Finally, fix reference to mByteStream in IpConfigStoreTest. It was already wrong but did not break the build because the test was not being built in the old location. Bug: 222234190 Test: TH Merged-In: I87843d554d1e726158f8784aa2ec61c92867ad3e Change-Id: I9093f9ae2f9d76e597f20de48680e459891755b4 --- framework-t/Android.bp | 3 ++ framework-t/Sources.bp | 30 ------------------- service-t/Android.bp | 3 ++ service-t/Sources.bp | 5 ---- .../android/server/net/IpConfigStoreTest.java | 2 +- 5 files changed, 7 insertions(+), 36 deletions(-) diff --git a/framework-t/Android.bp b/framework-t/Android.bp index f46d887f78..1e508a04bd 100644 --- a/framework-t/Android.bp +++ b/framework-t/Android.bp @@ -19,6 +19,9 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +// Include build rules from Sources.bp +build = ["Sources.bp"] + java_defaults { name: "enable-framework-connectivity-t-targets", enabled: true, diff --git a/framework-t/Sources.bp b/framework-t/Sources.bp index bc27852857..53b4163b93 100644 --- a/framework-t/Sources.bp +++ b/framework-t/Sources.bp @@ -14,11 +14,6 @@ // limitations under the License. // -package { - // See: http://go/android-license-faq - default_applicable_licenses: ["Android-Apache-2.0"], -} - // NetworkStats related libraries. filegroup { @@ -46,23 +41,10 @@ filegroup { ], } -filegroup { - name: "framework-connectivity-netstats-aidl-export-sources", - srcs: [ - "aidl-export/android/net/NetworkStats.aidl", - "aidl-export/android/net/NetworkTemplate.aidl", - ], - path: "aidl-export", - visibility: [ - "//visibility:private", - ], -} - filegroup { name: "framework-connectivity-netstats-sources", srcs: [ ":framework-connectivity-netstats-internal-sources", - ":framework-connectivity-netstats-aidl-export-sources", ], visibility: [ "//visibility:private", @@ -83,22 +65,10 @@ filegroup { ], } -filegroup { - name: "framework-connectivity-nsd-aidl-export-sources", - srcs: [ - "aidl-export/android/net/nsd/*.aidl", - ], - path: "aidl-export", - visibility: [ - "//visibility:private", - ], -} - filegroup { name: "framework-connectivity-nsd-sources", srcs: [ ":framework-connectivity-nsd-internal-sources", - ":framework-connectivity-nsd-aidl-export-sources", ], visibility: [ "//visibility:private", diff --git a/service-t/Android.bp b/service-t/Android.bp index 8851554751..50dd995ef4 100644 --- a/service-t/Android.bp +++ b/service-t/Android.bp @@ -19,6 +19,9 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +// Include build rules from Sources.bp +build = ["Sources.bp"] + // This builds T+ services depending on framework-connectivity-t // hidden symbols separately from the S+ services, to ensure that S+ // services cannot accidentally depend on T+ hidden symbols from diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 4b799c599b..04866fb9cc 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -14,11 +14,6 @@ // limitations under the License. // -package { - // See: http://go/android-license-faq - default_applicable_licenses: ["Android-Apache-2.0"], -} - // NetworkStats related libraries. filegroup { diff --git a/tests/unit/java/com/android/server/net/IpConfigStoreTest.java b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java index ad0be5862c..e9a53096b7 100644 --- a/tests/unit/java/com/android/server/net/IpConfigStoreTest.java +++ b/tests/unit/java/com/android/server/net/IpConfigStoreTest.java @@ -105,7 +105,7 @@ public class IpConfigStoreTest { IpConfigStore store = new IpConfigStore(writer); store.writeIpConfigurations("file/path/not/used/", expectedNetworks); - InputStream in = new ByteArrayInputStream(writer.byteStream.toByteArray()); + InputStream in = new ByteArrayInputStream(writer.mByteStream.toByteArray()); ArrayMap actualNetworks = IpConfigStore.readIpConfigurations(in); assertNotNull(actualNetworks); assertEquals(2, actualNetworks.size()); From 96f1413c01f926d180f762f54be36eb08c2984b2 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Sat, 26 Mar 2022 22:09:49 +0000 Subject: [PATCH 880/881] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I12a9a3cc6e207d3e4761977ad30c4bbaaa535df3 --- .../res/values-af/strings.xml | 40 +++++++++---------- .../res/values-am/strings.xml | 40 +++++++++---------- .../res/values-ar/strings.xml | 40 +++++++++---------- .../res/values-as/strings.xml | 40 +++++++++---------- .../res/values-az/strings.xml | 40 +++++++++---------- .../res/values-b+sr+Latn/strings.xml | 40 +++++++++---------- .../res/values-be/strings.xml | 40 +++++++++---------- .../res/values-bg/strings.xml | 40 +++++++++---------- .../res/values-bn/strings.xml | 40 +++++++++---------- .../res/values-bs/strings.xml | 40 +++++++++---------- .../res/values-ca/strings.xml | 40 +++++++++---------- .../res/values-cs/strings.xml | 40 +++++++++---------- .../res/values-da/strings.xml | 40 +++++++++---------- .../res/values-de/strings.xml | 40 +++++++++---------- .../res/values-el/strings.xml | 40 +++++++++---------- .../res/values-en-rAU/strings.xml | 40 +++++++++---------- .../res/values-en-rCA/strings.xml | 40 +++++++++---------- .../res/values-en-rGB/strings.xml | 40 +++++++++---------- .../res/values-en-rIN/strings.xml | 40 +++++++++---------- .../res/values-en-rXC/strings.xml | 40 +++++++++---------- .../res/values-es-rUS/strings.xml | 40 +++++++++---------- .../res/values-es/strings.xml | 40 +++++++++---------- .../res/values-et/strings.xml | 40 +++++++++---------- .../res/values-eu/strings.xml | 40 +++++++++---------- .../res/values-fa/strings.xml | 40 +++++++++---------- .../res/values-fi/strings.xml | 40 +++++++++---------- .../res/values-fr-rCA/strings.xml | 40 +++++++++---------- .../res/values-fr/strings.xml | 40 +++++++++---------- .../res/values-gl/strings.xml | 40 +++++++++---------- .../res/values-gu/strings.xml | 40 +++++++++---------- .../res/values-hi/strings.xml | 40 +++++++++---------- .../res/values-hr/strings.xml | 40 +++++++++---------- .../res/values-hu/strings.xml | 40 +++++++++---------- .../res/values-hy/strings.xml | 40 +++++++++---------- .../res/values-in/strings.xml | 40 +++++++++---------- .../res/values-is/strings.xml | 40 +++++++++---------- .../res/values-it/strings.xml | 40 +++++++++---------- .../res/values-iw/strings.xml | 40 +++++++++---------- .../res/values-ja/strings.xml | 40 +++++++++---------- .../res/values-ka/strings.xml | 40 +++++++++---------- .../res/values-kk/strings.xml | 40 +++++++++---------- .../res/values-km/strings.xml | 40 +++++++++---------- .../res/values-kn/strings.xml | 40 +++++++++---------- .../res/values-ko/strings.xml | 40 +++++++++---------- .../res/values-ky/strings.xml | 40 +++++++++---------- .../res/values-lo/strings.xml | 40 +++++++++---------- .../res/values-lt/strings.xml | 40 +++++++++---------- .../res/values-lv/strings.xml | 40 +++++++++---------- .../res/values-mk/strings.xml | 40 +++++++++---------- .../res/values-ml/strings.xml | 40 +++++++++---------- .../res/values-mn/strings.xml | 40 +++++++++---------- .../res/values-mr/strings.xml | 40 +++++++++---------- .../res/values-ms/strings.xml | 40 +++++++++---------- .../res/values-my/strings.xml | 40 +++++++++---------- .../res/values-nb/strings.xml | 40 +++++++++---------- .../res/values-ne/strings.xml | 40 +++++++++---------- .../res/values-nl/strings.xml | 40 +++++++++---------- .../res/values-or/strings.xml | 40 +++++++++---------- .../res/values-pa/strings.xml | 40 +++++++++---------- .../res/values-pl/strings.xml | 40 +++++++++---------- .../res/values-pt-rBR/strings.xml | 40 +++++++++---------- .../res/values-pt-rPT/strings.xml | 40 +++++++++---------- .../res/values-pt/strings.xml | 40 +++++++++---------- .../res/values-ro/strings.xml | 40 +++++++++---------- .../res/values-ru/strings.xml | 40 +++++++++---------- .../res/values-si/strings.xml | 40 +++++++++---------- .../res/values-sk/strings.xml | 40 +++++++++---------- .../res/values-sl/strings.xml | 40 +++++++++---------- .../res/values-sq/strings.xml | 40 +++++++++---------- .../res/values-sr/strings.xml | 40 +++++++++---------- .../res/values-sv/strings.xml | 40 +++++++++---------- .../res/values-sw/strings.xml | 40 +++++++++---------- .../res/values-ta/strings.xml | 40 +++++++++---------- .../res/values-te/strings.xml | 40 +++++++++---------- .../res/values-th/strings.xml | 40 +++++++++---------- .../res/values-tl/strings.xml | 40 +++++++++---------- .../res/values-tr/strings.xml | 40 +++++++++---------- .../res/values-uk/strings.xml | 40 +++++++++---------- .../res/values-ur/strings.xml | 40 +++++++++---------- .../res/values-uz/strings.xml | 40 +++++++++---------- .../res/values-vi/strings.xml | 40 +++++++++---------- .../res/values-zh-rCN/strings.xml | 40 +++++++++---------- .../res/values-zh-rHK/strings.xml | 40 +++++++++---------- .../res/values-zh-rTW/strings.xml | 40 +++++++++---------- .../res/values-zu/strings.xml | 40 +++++++++---------- 85 files changed, 1700 insertions(+), 1700 deletions(-) diff --git a/service/ServiceConnectivityResources/res/values-af/strings.xml b/service/ServiceConnectivityResources/res/values-af/strings.xml index 550ab8a65d..086c6e332c 100644 --- a/service/ServiceConnectivityResources/res/values-af/strings.xml +++ b/service/ServiceConnectivityResources/res/values-af/strings.xml @@ -17,27 +17,27 @@ - "Stelselkonnektiwiteithulpbronne" - "Meld aan by Wi-Fi-netwerk" - "Meld by netwerk aan" - + "Stelselkonnektiwiteithulpbronne" + "Meld aan by Wi-Fi-netwerk" + "Meld by netwerk aan" + - "%1$s het geen internettoegang nie" - "Tik vir opsies" - "Selnetwerk het nie internettoegang nie" - "Netwerk het nie internettoegang nie" - "Daar kan nie by private DNS-bediener ingegaan word nie" - "%1$s het beperkte konnektiwiteit" - "Tik om in elk geval te koppel" - "Het oorgeskakel na %1$s" - "Toestel gebruik %1$s wanneer %2$s geen internettoegang het nie. Heffings kan geld." - "Het oorgeskakel van %1$s na %2$s" + "%1$s het geen internettoegang nie" + "Tik vir opsies" + "Selnetwerk het nie internettoegang nie" + "Netwerk het nie internettoegang nie" + "Daar kan nie by private DNS-bediener ingegaan word nie" + "%1$s het beperkte konnektiwiteit" + "Tik om in elk geval te koppel" + "Het oorgeskakel na %1$s" + "Toestel gebruik %1$s wanneer %2$s geen internettoegang het nie. Heffings kan geld." + "Het oorgeskakel van %1$s na %2$s" - "mobiele data" - "Wi-fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobiele data" + "Wi-fi" + "Bluetooth" + "Ethernet" + "VPN" - "\'n onbekende netwerktipe" + "\'n onbekende netwerktipe" diff --git a/service/ServiceConnectivityResources/res/values-am/strings.xml b/service/ServiceConnectivityResources/res/values-am/strings.xml index 7f1a9dbe51..886b3533e8 100644 --- a/service/ServiceConnectivityResources/res/values-am/strings.xml +++ b/service/ServiceConnectivityResources/res/values-am/strings.xml @@ -17,27 +17,27 @@ - "የስርዓት ግንኙነት መርጃዎች" - "ወደ Wi-Fi አውታረ መረብ በመለያ ግባ" - "ወደ አውታረ መረብ በመለያ ይግቡ" - + "የስርዓት ግንኙነት መርጃዎች" + "ወደ Wi-Fi አውታረ መረብ በመለያ ግባ" + "ወደ አውታረ መረብ በመለያ ይግቡ" + - "%1$s ምንም የበይነ መረብ መዳረሻ የለም" - "ለአማራጮች መታ ያድርጉ" - "የተንቀሳቃሽ ስልክ አውታረ መረብ የበይነመረብ መዳረሻ የለውም" - "አውታረ መረብ የበይነመረብ መዳረሻ የለውም" - "የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም" - "%1$s የተገደበ ግንኙነት አለው" - "ለማንኛውም ለማገናኘት መታ ያድርጉ" - "ወደ %1$s ተቀይሯል" - "%2$s ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች %1$sን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።" - "ከ%1$s ወደ %2$s ተቀይሯል" + "%1$s ምንም የበይነ መረብ መዳረሻ የለም" + "ለአማራጮች መታ ያድርጉ" + "የተንቀሳቃሽ ስልክ አውታረ መረብ የበይነመረብ መዳረሻ የለውም" + "አውታረ መረብ የበይነመረብ መዳረሻ የለውም" + "የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም" + "%1$s የተገደበ ግንኙነት አለው" + "ለማንኛውም ለማገናኘት መታ ያድርጉ" + "ወደ %1$s ተቀይሯል" + "%2$s ምንም ዓይነት የበይነመረብ ግንኙነት በማይኖረው ጊዜ መሣሪያዎች %1$sን ይጠቀማሉ። ክፍያዎች ተፈጻሚ ሊሆኑ ይችላሉ።" + "ከ%1$s ወደ %2$s ተቀይሯል" - "የተንቀሳቃሽ ስልክ ውሂብ" - "Wi-Fi" - "ብሉቱዝ" - "ኢተርኔት" - "VPN" + "የተንቀሳቃሽ ስልክ ውሂብ" + "Wi-Fi" + "ብሉቱዝ" + "ኢተርኔት" + "VPN" - "አንድ ያልታወቀ አውታረ መረብ ዓይነት" + "አንድ ያልታወቀ አውታረ መረብ ዓይነት" diff --git a/service/ServiceConnectivityResources/res/values-ar/strings.xml b/service/ServiceConnectivityResources/res/values-ar/strings.xml index b7a62c5e1d..07d9c2eef9 100644 --- a/service/ServiceConnectivityResources/res/values-ar/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ar/strings.xml @@ -17,27 +17,27 @@ - "مصادر إمكانية اتصال الخادم" - "‏تسجيل الدخول إلى شبكة Wi-Fi" - "تسجيل الدخول إلى الشبكة" - + "مصادر إمكانية اتصال الخادم" + "‏تسجيل الدخول إلى شبكة Wi-Fi" + "تسجيل الدخول إلى الشبكة" + - "لا يتوفّر في %1$s إمكانية الاتصال بالإنترنت." - "انقر للحصول على الخيارات." - "شبكة الجوّال هذه غير متصلة بالإنترنت" - "الشبكة غير متصلة بالإنترنت" - "لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص" - "إمكانية اتصال %1$s محدودة." - "يمكنك النقر للاتصال على أي حال." - "تم التبديل إلى %1$s" - "يستخدم الجهاز %1$s عندما لا يتوفر اتصال بالإنترنت في شبكة %2$s، ويمكن أن يتم فرض رسوم مقابل ذلك." - "تم التبديل من %1$s إلى %2$s" + "لا يتوفّر في %1$s إمكانية الاتصال بالإنترنت." + "انقر للحصول على الخيارات." + "شبكة الجوّال هذه غير متصلة بالإنترنت" + "الشبكة غير متصلة بالإنترنت" + "لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص" + "إمكانية اتصال %1$s محدودة." + "يمكنك النقر للاتصال على أي حال." + "تم التبديل إلى %1$s" + "يستخدم الجهاز %1$s عندما لا يتوفر اتصال بالإنترنت في شبكة %2$s، ويمكن أن يتم فرض رسوم مقابل ذلك." + "تم التبديل من %1$s إلى %2$s" - "بيانات الجوّال" - "Wi-Fi" - "بلوتوث" - "إيثرنت" - "‏شبكة افتراضية خاصة (VPN)" + "بيانات الجوّال" + "Wi-Fi" + "بلوتوث" + "إيثرنت" + "‏شبكة افتراضية خاصة (VPN)" - "نوع شبكة غير معروف" + "نوع شبكة غير معروف" diff --git a/service/ServiceConnectivityResources/res/values-as/strings.xml b/service/ServiceConnectivityResources/res/values-as/strings.xml index cf8e6ac9d4..e753cb3bf2 100644 --- a/service/ServiceConnectivityResources/res/values-as/strings.xml +++ b/service/ServiceConnectivityResources/res/values-as/strings.xml @@ -17,27 +17,27 @@ - "ছিষ্টেম সংযোগৰ উৎস" - "ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক" - "নেটৱৰ্কত ছাইন ইন কৰক" - + "ছিষ্টেম সংযোগৰ উৎস" + "ৱাই-ফাই নেটৱৰ্কত ছাইন ইন কৰক" + "নেটৱৰ্কত ছাইন ইন কৰক" + - "%1$sৰ ইণ্টাৰনেটৰ এক্সেছ নাই" - "অধিক বিকল্পৰ বাবে টিপক" - "ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" - "নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" - "ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি" - "%1$sৰ সকলো সেৱাৰ এক্সেছ নাই" - "যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক" - "%1$sলৈ সলনি কৰা হ’ল" - "যেতিয়া %2$sত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে %1$sক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।" - "%1$sৰ পৰা %2$s লৈ সলনি কৰা হ’ল" + "%1$sৰ ইণ্টাৰনেটৰ এক্সেছ নাই" + "অধিক বিকল্পৰ বাবে টিপক" + "ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" + "নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই" + "ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি" + "%1$sৰ সকলো সেৱাৰ এক্সেছ নাই" + "যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক" + "%1$sলৈ সলনি কৰা হ’ল" + "যেতিয়া %2$sত ইণ্টাৰনেট নাথাকে, তেতিয়া ডিভাইচে %1$sক ব্যৱহাৰ কৰে। মাচুল প্ৰযোজ্য হ\'ব পাৰে।" + "%1$sৰ পৰা %2$s লৈ সলনি কৰা হ’ল" - "ম’বাইল ডেটা" - "ৱাই-ফাই" - "ব্লুটুথ" - "ইথাৰনেট" - "ভিপিএন" + "ম’বাইল ডেটা" + "ৱাই-ফাই" + "ব্লুটুথ" + "ইথাৰনেট" + "ভিপিএন" - "অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক" + "অজ্ঞাত প্ৰকাৰৰ নেটৱৰ্ক" diff --git a/service/ServiceConnectivityResources/res/values-az/strings.xml b/service/ServiceConnectivityResources/res/values-az/strings.xml index 7e927ed41b..f33a3e3569 100644 --- a/service/ServiceConnectivityResources/res/values-az/strings.xml +++ b/service/ServiceConnectivityResources/res/values-az/strings.xml @@ -17,27 +17,27 @@ - "Sistem Bağlantı Resursları" - "Wi-Fi şəbəkəsinə daxil ol" - "Şəbəkəyə daxil olun" - + "Sistem Bağlantı Resursları" + "Wi-Fi şəbəkəsinə daxil ol" + "Şəbəkəyə daxil olun" + - "%1$s üçün internet girişi əlçatan deyil" - "Seçimlər üçün tıklayın" - "Mobil şəbəkənin internetə girişi yoxdur" - "Şəbəkənin internetə girişi yoxdur" - "Özəl DNS serverinə giriş mümkün deyil" - "%1$s bağlantını məhdudlaşdırdı" - "İstənilən halda klikləyin" - "%1$s şəbəkə növünə keçirildi" - "%2$s şəbəkəsinin internetə girişi olmadıqda, cihaz %1$s şəbəkəsini istifadə edir. Xidmət haqqı tutula bilər." - "%1$s şəbəkəsindən %2$s şəbəkəsinə keçirildi" + "%1$s üçün internet girişi əlçatan deyil" + "Seçimlər üçün tıklayın" + "Mobil şəbəkənin internetə girişi yoxdur" + "Şəbəkənin internetə girişi yoxdur" + "Özəl DNS serverinə giriş mümkün deyil" + "%1$s bağlantını məhdudlaşdırdı" + "İstənilən halda klikləyin" + "%1$s şəbəkə növünə keçirildi" + "%2$s şəbəkəsinin internetə girişi olmadıqda, cihaz %1$s şəbəkəsini istifadə edir. Xidmət haqqı tutula bilər." + "%1$s şəbəkəsindən %2$s şəbəkəsinə keçirildi" - "mobil data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobil data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "naməlum şəbəkə növü" + "naməlum şəbəkə növü" diff --git a/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml b/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml index 3f1b976fb9..7398e7cf79 100644 --- a/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml +++ b/service/ServiceConnectivityResources/res/values-b+sr+Latn/strings.xml @@ -17,27 +17,27 @@ - "Resursi za povezivanje sa sistemom" - "Prijavljivanje na WiFi mrežu" - "Prijavite se na mrežu" - + "Resursi za povezivanje sa sistemom" + "Prijavljivanje na WiFi mrežu" + "Prijavite se na mrežu" + - "%1$s nema pristup internetu" - "Dodirnite za opcije" - "Mobilna mreža nema pristup internetu" - "Mreža nema pristup internetu" - "Pristup privatnom DNS serveru nije uspeo" - "%1$s ima ograničenu vezu" - "Dodirnite da biste se ipak povezali" - "Prešli ste na tip mreže %1$s" - "Uređaj koristi tip mreže %1$s kada tip mreže %2$s nema pristup internetu. Možda će se naplaćivati troškovi." - "Prešli ste sa tipa mreže %1$s na tip mreže %2$s" + "%1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Pristup privatnom DNS serveru nije uspeo" + "%1$s ima ograničenu vezu" + "Dodirnite da biste se ipak povezali" + "Prešli ste na tip mreže %1$s" + "Uređaj koristi tip mreže %1$s kada tip mreže %2$s nema pristup internetu. Možda će se naplaćivati troškovi." + "Prešli ste sa tipa mreže %1$s na tip mreže %2$s" - "mobilni podaci" - "WiFi" - "Bluetooth" - "Eternet" - "VPN" + "mobilni podaci" + "WiFi" + "Bluetooth" + "Eternet" + "VPN" - "nepoznat tip mreže" + "nepoznat tip mreže" diff --git a/service/ServiceConnectivityResources/res/values-be/strings.xml b/service/ServiceConnectivityResources/res/values-be/strings.xml index 21edf24054..3459cc7c7c 100644 --- a/service/ServiceConnectivityResources/res/values-be/strings.xml +++ b/service/ServiceConnectivityResources/res/values-be/strings.xml @@ -17,27 +17,27 @@ - "Рэсурсы для падключэння да сістэмы" - "Уваход у сетку Wi-Fi" - "Увайдзіце ў сетку" - + "Рэсурсы для падключэння да сістэмы" + "Уваход у сетку Wi-Fi" + "Увайдзіце ў сетку" + - "%1$s не мае доступу ў інтэрнэт" - "Дакраніцеся, каб убачыць параметры" - "Мабільная сетка не мае доступу ў інтэрнэт" - "Сетка не мае доступу ў інтэрнэт" - "Не ўдалося атрымаць доступ да прыватнага DNS-сервера" - "%1$s мае абмежаваную магчымасць падключэння" - "Націсніце, каб падключыцца" - "Выкананы пераход да %1$s" - "Прылада выкарыстоўвае сетку %1$s, калі ў сетцы %2$s няма доступу да інтэрнэту. Можа спаганяцца плата." - "Выкананы пераход з %1$s да %2$s" + "%1$s не мае доступу ў інтэрнэт" + "Дакраніцеся, каб убачыць параметры" + "Мабільная сетка не мае доступу ў інтэрнэт" + "Сетка не мае доступу ў інтэрнэт" + "Не ўдалося атрымаць доступ да прыватнага DNS-сервера" + "%1$s мае абмежаваную магчымасць падключэння" + "Націсніце, каб падключыцца" + "Выкананы пераход да %1$s" + "Прылада выкарыстоўвае сетку %1$s, калі ў сетцы %2$s няма доступу да інтэрнэту. Можа спаганяцца плата." + "Выкананы пераход з %1$s да %2$s" - "мабільная перадача даных" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "мабільная перадача даных" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "невядомы тып сеткі" + "невядомы тып сеткі" diff --git a/service/ServiceConnectivityResources/res/values-bg/strings.xml b/service/ServiceConnectivityResources/res/values-bg/strings.xml index c3c2d722f4..b4ae618a40 100644 --- a/service/ServiceConnectivityResources/res/values-bg/strings.xml +++ b/service/ServiceConnectivityResources/res/values-bg/strings.xml @@ -17,27 +17,27 @@ - "Ресурси за свързаността на системата" - "Влизане в Wi-Fi мрежа" - "Вход в мрежата" - + "Ресурси за свързаността на системата" + "Влизане в Wi-Fi мрежа" + "Вход в мрежата" + - "%1$s няма достъп до интернет" - "Докоснете за опции" - "Мобилната мрежа няма достъп до интернет" - "Мрежата няма достъп до интернет" - "Не може да се осъществи достъп до частния DNS сървър" - "%1$s има ограничена свързаност" - "Докоснете, за да се свържете въпреки това" - "Превключи се към %1$s" - "Устройството използва %1$s, когато %2$s няма достъп до интернет. Възможно е да бъдете таксувани." - "Превключи се от %1$s към %2$s" + "%1$s няма достъп до интернет" + "Докоснете за опции" + "Мобилната мрежа няма достъп до интернет" + "Мрежата няма достъп до интернет" + "Не може да се осъществи достъп до частния DNS сървър" + "%1$s има ограничена свързаност" + "Докоснете, за да се свържете въпреки това" + "Превключи се към %1$s" + "Устройството използва %1$s, когато %2$s няма достъп до интернет. Възможно е да бъдете таксувани." + "Превключи се от %1$s към %2$s" - "мобилни данни" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "мобилни данни" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "неизвестен тип мрежа" + "неизвестен тип мрежа" diff --git a/service/ServiceConnectivityResources/res/values-bn/strings.xml b/service/ServiceConnectivityResources/res/values-bn/strings.xml index 0f693bd60c..3b32973a40 100644 --- a/service/ServiceConnectivityResources/res/values-bn/strings.xml +++ b/service/ServiceConnectivityResources/res/values-bn/strings.xml @@ -17,27 +17,27 @@ - "সিস্টেম কানেক্টিভিটি রিসোর্সেস" - "ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন" - "নেটওয়ার্কে সাইন-ইন করুন" - + "সিস্টেম কানেক্টিভিটি রিসোর্সেস" + "ওয়াই-ফাই নেটওয়ার্কে সাইন-ইন করুন" + "নেটওয়ার্কে সাইন-ইন করুন" + - "%1$s-এর ইন্টারনেটে অ্যাক্সেস নেই" - "বিকল্পগুলির জন্য আলতো চাপুন" - "মোবাইল নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" - "নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" - "ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না" - "%1$s-এর সীমিত কানেক্টিভিটি আছে" - "তবুও কানেক্ট করতে ট্যাপ করুন" - "%1$s এ পাল্টানো হয়েছে" - "%2$s এ ইন্টারনেট অ্যাক্সেস না থাকলে %1$s ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷" - "%1$s থেকে %2$s এ পাল্টানো হয়েছে" + "%1$s-এর ইন্টারনেটে অ্যাক্সেস নেই" + "বিকল্পগুলির জন্য আলতো চাপুন" + "মোবাইল নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" + "নেটওয়ার্কে কোনও ইন্টারনেট অ্যাক্সেস নেই" + "ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না" + "%1$s-এর সীমিত কানেক্টিভিটি আছে" + "তবুও কানেক্ট করতে ট্যাপ করুন" + "%1$s এ পাল্টানো হয়েছে" + "%2$s এ ইন্টারনেট অ্যাক্সেস না থাকলে %1$s ব্যবহার করা হয়৷ ডেটা চার্জ প্রযোজ্য৷" + "%1$s থেকে %2$s এ পাল্টানো হয়েছে" - "মোবাইল ডেটা" - "ওয়াই-ফাই" - "ব্লুটুথ" - "ইথারনেট" - "VPN" + "মোবাইল ডেটা" + "ওয়াই-ফাই" + "ব্লুটুথ" + "ইথারনেট" + "VPN" - "এই নেটওয়ার্কের ধরন অজানা" + "এই নেটওয়ার্কের ধরন অজানা" diff --git a/service/ServiceConnectivityResources/res/values-bs/strings.xml b/service/ServiceConnectivityResources/res/values-bs/strings.xml index 33d6ed9147..0bc0a7c5ef 100644 --- a/service/ServiceConnectivityResources/res/values-bs/strings.xml +++ b/service/ServiceConnectivityResources/res/values-bs/strings.xml @@ -17,27 +17,27 @@ - "Izvori povezivosti sistema" - "Prijavljivanje na WiFi mrežu" - "Prijava na mrežu" - + "Izvori povezivosti sistema" + "Prijavljivanje na WiFi mrežu" + "Prijava na mrežu" + - "Mreža %1$s nema pristup internetu" - "Dodirnite za opcije" - "Mobilna mreža nema pristup internetu" - "Mreža nema pristup internetu" - "Nije moguće pristupiti privatnom DNS serveru" - "Mreža %1$s ima ograničenu povezivost" - "Dodirnite da se ipak povežete" - "Prebačeno na: %1$s" - "Kada %2$s nema pristup internetu, uređaj koristi mrežu %1$s. Moguća je naplata usluge." - "Prebačeno iz mreže %1$s u %2$s mrežu" + "Mreža %1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Nije moguće pristupiti privatnom DNS serveru" + "Mreža %1$s ima ograničenu povezivost" + "Dodirnite da se ipak povežete" + "Prebačeno na: %1$s" + "Kada %2$s nema pristup internetu, uređaj koristi mrežu %1$s. Moguća je naplata usluge." + "Prebačeno iz mreže %1$s u %2$s mrežu" - "prijenos podataka na mobilnoj mreži" - "WiFi" - "Bluetooth" - "Ethernet" - "VPN" + "prijenos podataka na mobilnoj mreži" + "WiFi" + "Bluetooth" + "Ethernet" + "VPN" - "nepoznata vrsta mreže" + "nepoznata vrsta mreže" diff --git a/service/ServiceConnectivityResources/res/values-ca/strings.xml b/service/ServiceConnectivityResources/res/values-ca/strings.xml index 04f6bd211c..22b9dbd9e8 100644 --- a/service/ServiceConnectivityResources/res/values-ca/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ca/strings.xml @@ -17,27 +17,27 @@ - "Recursos de connectivitat del sistema" - "Inicia la sessió a la xarxa Wi-Fi" - "Inicia la sessió a la xarxa" - + "Recursos de connectivitat del sistema" + "Inicia la sessió a la xarxa Wi-Fi" + "Inicia la sessió a la xarxa" + - "%1$s no té accés a Internet" - "Toca per veure les opcions" - "La xarxa mòbil no té accés a Internet" - "La xarxa no té accés a Internet" - "No es pot accedir al servidor DNS privat" - "%1$s té una connectivitat limitada" - "Toca per connectar igualment" - "Actualment en ús: %1$s" - "El dispositiu utilitza %1$s en cas que %2$s no tingui accés a Internet. És possible que s\'hi apliquin càrrecs." - "Abans es feia servir la xarxa %1$s; ara s\'utilitza %2$s" + "%1$s no té accés a Internet" + "Toca per veure les opcions" + "La xarxa mòbil no té accés a Internet" + "La xarxa no té accés a Internet" + "No es pot accedir al servidor DNS privat" + "%1$s té una connectivitat limitada" + "Toca per connectar igualment" + "Actualment en ús: %1$s" + "El dispositiu utilitza %1$s en cas que %2$s no tingui accés a Internet. És possible que s\'hi apliquin càrrecs." + "Abans es feia servir la xarxa %1$s; ara s\'utilitza %2$s" - "dades mòbils" - "Wi‑Fi" - "Bluetooth" - "Ethernet" - "VPN" + "dades mòbils" + "Wi‑Fi" + "Bluetooth" + "Ethernet" + "VPN" - "un tipus de xarxa desconegut" + "un tipus de xarxa desconegut" diff --git a/service/ServiceConnectivityResources/res/values-cs/strings.xml b/service/ServiceConnectivityResources/res/values-cs/strings.xml index 6309e788e6..ccf21ee179 100644 --- a/service/ServiceConnectivityResources/res/values-cs/strings.xml +++ b/service/ServiceConnectivityResources/res/values-cs/strings.xml @@ -17,27 +17,27 @@ - "Zdroje pro připojení systému" - "Přihlásit se k síti Wi-Fi" - "Přihlásit se k síti" - + "Zdroje pro připojení systému" + "Přihlásit se k síti Wi-Fi" + "Přihlásit se k síti" + - "Síť %1$s nemá přístup k internetu" - "Klepnutím zobrazíte možnosti" - "Mobilní síť nemá přístup k internetu" - "Síť nemá přístup k internetu" - "Nelze získat přístup k soukromému serveru DNS" - "Síť %1$s umožňuje jen omezené připojení" - "Klepnutím se i přesto připojíte" - "Přechod na síť %1$s" - "Když síť %2$s nebude mít přístup k internetu, zařízení použije síť %1$s. Mohou být účtovány poplatky." - "Přechod ze sítě %1$s na síť %2$s" + "Síť %1$s nemá přístup k internetu" + "Klepnutím zobrazíte možnosti" + "Mobilní síť nemá přístup k internetu" + "Síť nemá přístup k internetu" + "Nelze získat přístup k soukromému serveru DNS" + "Síť %1$s umožňuje jen omezené připojení" + "Klepnutím se i přesto připojíte" + "Přechod na síť %1$s" + "Když síť %2$s nebude mít přístup k internetu, zařízení použije síť %1$s. Mohou být účtovány poplatky." + "Přechod ze sítě %1$s na síť %2$s" - "mobilní data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobilní data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "neznámý typ sítě" + "neznámý typ sítě" diff --git a/service/ServiceConnectivityResources/res/values-da/strings.xml b/service/ServiceConnectivityResources/res/values-da/strings.xml index 57c58afc41..a33143e082 100644 --- a/service/ServiceConnectivityResources/res/values-da/strings.xml +++ b/service/ServiceConnectivityResources/res/values-da/strings.xml @@ -17,27 +17,27 @@ - "Systemets forbindelsesressourcer" - "Log ind på Wi-Fi-netværk" - "Log ind på netværk" - + "Systemets forbindelsesressourcer" + "Log ind på Wi-Fi-netværk" + "Log ind på netværk" + - "%1$s har ingen internetforbindelse" - "Tryk for at se valgmuligheder" - "Mobilnetværket har ingen internetadgang" - "Netværket har ingen internetadgang" - "Der er ikke adgang til den private DNS-server" - "%1$s har begrænset forbindelse" - "Tryk for at oprette forbindelse alligevel" - "Der blev skiftet til %1$s" - "Enheden benytter %1$s, når der ikke er internetadgang via %2$s. Der opkræves muligvis betaling." - "Der blev skiftet fra %1$s til %2$s" + "%1$s har ingen internetforbindelse" + "Tryk for at se valgmuligheder" + "Mobilnetværket har ingen internetadgang" + "Netværket har ingen internetadgang" + "Der er ikke adgang til den private DNS-server" + "%1$s har begrænset forbindelse" + "Tryk for at oprette forbindelse alligevel" + "Der blev skiftet til %1$s" + "Enheden benytter %1$s, når der ikke er internetadgang via %2$s. Der opkræves muligvis betaling." + "Der blev skiftet fra %1$s til %2$s" - "mobildata" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "en ukendt netværkstype" + "en ukendt netværkstype" diff --git a/service/ServiceConnectivityResources/res/values-de/strings.xml b/service/ServiceConnectivityResources/res/values-de/strings.xml index d0c255197a..96cc7d2ef0 100644 --- a/service/ServiceConnectivityResources/res/values-de/strings.xml +++ b/service/ServiceConnectivityResources/res/values-de/strings.xml @@ -17,27 +17,27 @@ - "Systemverbindungsressourcen" - "In WLAN anmelden" - "Im Netzwerk anmelden" - + "Systemverbindungsressourcen" + "In WLAN anmelden" + "Im Netzwerk anmelden" + - "%1$s hat keinen Internetzugriff" - "Für Optionen tippen" - "Mobiles Netzwerk hat keinen Internetzugriff" - "Netzwerk hat keinen Internetzugriff" - "Auf den privaten DNS-Server kann nicht zugegriffen werden" - "Schlechte Verbindung mit %1$s" - "Tippen, um die Verbindung trotzdem herzustellen" - "Zu %1$s gewechselt" - "Auf dem Gerät werden %1$s genutzt, wenn über %2$s kein Internet verfügbar ist. Eventuell fallen Gebühren an." - "Von \"%1$s\" zu \"%2$s\" gewechselt" + "%1$s hat keinen Internetzugriff" + "Für Optionen tippen" + "Mobiles Netzwerk hat keinen Internetzugriff" + "Netzwerk hat keinen Internetzugriff" + "Auf den privaten DNS-Server kann nicht zugegriffen werden" + "Schlechte Verbindung mit %1$s" + "Tippen, um die Verbindung trotzdem herzustellen" + "Zu %1$s gewechselt" + "Auf dem Gerät werden %1$s genutzt, wenn über %2$s kein Internet verfügbar ist. Eventuell fallen Gebühren an." + "Von \"%1$s\" zu \"%2$s\" gewechselt" - "Mobile Daten" - "WLAN" - "Bluetooth" - "Ethernet" - "VPN" + "Mobile Daten" + "WLAN" + "Bluetooth" + "Ethernet" + "VPN" - "ein unbekannter Netzwerktyp" + "ein unbekannter Netzwerktyp" diff --git a/service/ServiceConnectivityResources/res/values-el/strings.xml b/service/ServiceConnectivityResources/res/values-el/strings.xml index 1c2838dfd4..b5f319d5ab 100644 --- a/service/ServiceConnectivityResources/res/values-el/strings.xml +++ b/service/ServiceConnectivityResources/res/values-el/strings.xml @@ -17,27 +17,27 @@ - "Πόροι συνδεσιμότητας συστήματος" - "Συνδεθείτε στο δίκτυο Wi-Fi" - "Σύνδεση στο δίκτυο" - + "Πόροι συνδεσιμότητας συστήματος" + "Συνδεθείτε στο δίκτυο Wi-Fi" + "Σύνδεση στο δίκτυο" + - "Η εφαρμογή %1$s δεν έχει πρόσβαση στο διαδίκτυο" - "Πατήστε για να δείτε τις επιλογές" - "Το δίκτυο κινητής τηλεφωνίας δεν έχει πρόσβαση στο διαδίκτυο." - "Το δίκτυο δεν έχει πρόσβαση στο διαδίκτυο." - "Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS." - "Το δίκτυο %1$s έχει περιορισμένη συνδεσιμότητα" - "Πατήστε για σύνδεση ούτως ή άλλως" - "Μετάβαση σε δίκτυο %1$s" - "Η συσκευή χρησιμοποιεί το δίκτυο %1$s όταν το δίκτυο %2$s δεν έχει πρόσβαση στο διαδίκτυο. Μπορεί να ισχύουν χρεώσεις." - "Μετάβαση από το δίκτυο %1$s στο δίκτυο %2$s" + "Η εφαρμογή %1$s δεν έχει πρόσβαση στο διαδίκτυο" + "Πατήστε για να δείτε τις επιλογές" + "Το δίκτυο κινητής τηλεφωνίας δεν έχει πρόσβαση στο διαδίκτυο." + "Το δίκτυο δεν έχει πρόσβαση στο διαδίκτυο." + "Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS." + "Το δίκτυο %1$s έχει περιορισμένη συνδεσιμότητα" + "Πατήστε για σύνδεση ούτως ή άλλως" + "Μετάβαση σε δίκτυο %1$s" + "Η συσκευή χρησιμοποιεί το δίκτυο %1$s όταν το δίκτυο %2$s δεν έχει πρόσβαση στο διαδίκτυο. Μπορεί να ισχύουν χρεώσεις." + "Μετάβαση από το δίκτυο %1$s στο δίκτυο %2$s" - "δεδομένα κινητής τηλεφωνίας" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "δεδομένα κινητής τηλεφωνίας" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "άγνωστος τύπος δικτύου" + "άγνωστος τύπος δικτύου" diff --git a/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml b/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml index db5ad7029b..c490cf8da4 100644 --- a/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml +++ b/service/ServiceConnectivityResources/res/values-en-rAU/strings.xml @@ -17,27 +17,27 @@ - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - + "System connectivity resources" + "Sign in to a Wi-Fi network" + "Sign in to network" + - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "an unknown network type" + "an unknown network type" diff --git a/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml b/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml index db5ad7029b..c490cf8da4 100644 --- a/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml +++ b/service/ServiceConnectivityResources/res/values-en-rCA/strings.xml @@ -17,27 +17,27 @@ - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - + "System connectivity resources" + "Sign in to a Wi-Fi network" + "Sign in to network" + - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "an unknown network type" + "an unknown network type" diff --git a/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml b/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml index db5ad7029b..c490cf8da4 100644 --- a/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml +++ b/service/ServiceConnectivityResources/res/values-en-rGB/strings.xml @@ -17,27 +17,27 @@ - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - + "System connectivity resources" + "Sign in to a Wi-Fi network" + "Sign in to network" + - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "an unknown network type" + "an unknown network type" diff --git a/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml b/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml index db5ad7029b..c490cf8da4 100644 --- a/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml +++ b/service/ServiceConnectivityResources/res/values-en-rIN/strings.xml @@ -17,27 +17,27 @@ - "System connectivity resources" - "Sign in to a Wi-Fi network" - "Sign in to network" - + "System connectivity resources" + "Sign in to a Wi-Fi network" + "Sign in to network" + - "%1$s has no Internet access" - "Tap for options" - "Mobile network has no Internet access" - "Network has no Internet access" - "Private DNS server cannot be accessed" - "%1$s has limited connectivity" - "Tap to connect anyway" - "Switched to %1$s" - "Device uses %1$s when %2$s has no Internet access. Charges may apply." - "Switched from %1$s to %2$s" + "%1$s has no Internet access" + "Tap for options" + "Mobile network has no Internet access" + "Network has no Internet access" + "Private DNS server cannot be accessed" + "%1$s has limited connectivity" + "Tap to connect anyway" + "Switched to %1$s" + "Device uses %1$s when %2$s has no Internet access. Charges may apply." + "Switched from %1$s to %2$s" - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "an unknown network type" + "an unknown network type" diff --git a/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml b/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml index 2602bfa065..67c3659349 100644 --- a/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml +++ b/service/ServiceConnectivityResources/res/values-en-rXC/strings.xml @@ -17,27 +17,27 @@ - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‎System Connectivity Resources‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎Sign in to Wi-Fi network‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎Sign in to network‎‏‎‎‏‎" - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎System Connectivity Resources‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎Sign in to Wi-Fi network‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‏‎Sign in to network‎‏‎‎‏‎" + - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has no internet access‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‎Tap for options‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎Mobile network has no internet access‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎Network has no internet access‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎Private DNS server cannot be accessed‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has limited connectivity‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎Tap to connect anyway‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎Switched to ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎Device uses ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ when ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ has no internet access. Charges may apply.‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎Switched from ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎Tap for options‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎Mobile network has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎Network has no internet access‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‏‏‎Private DNS server cannot be accessed‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ has limited connectivity‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‎‏‎Tap to connect anyway‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‏‎Switched to ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎Device uses ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ when ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎ has no internet access. Charges may apply.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‏‏‏‎Switched from ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎mobile data‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎Wi-Fi‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎Bluetooth‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎Ethernet‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‏‎VPN‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‏‎mobile data‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎Wi-Fi‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎Bluetooth‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‎Ethernet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎VPN‎‏‎‎‏‎" - "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎an unknown network type‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎an unknown network type‎‏‎‎‏‎" diff --git a/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml b/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml index e5f1833fdd..fdca46809c 100644 --- a/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml +++ b/service/ServiceConnectivityResources/res/values-es-rUS/strings.xml @@ -17,27 +17,27 @@ - "Recursos de conectividad del sistema" - "Accede a una red Wi-Fi." - "Acceder a la red" - + "Recursos de conectividad del sistema" + "Accede a una red Wi-Fi." + "Acceder a la red" + - "%1$sno tiene acceso a Internet" - "Presiona para ver opciones" - "La red móvil no tiene acceso a Internet" - "La red no tiene acceso a Internet" - "No se puede acceder al servidor DNS privado" - "%1$s tiene conectividad limitada" - "Presiona para conectarte de todas formas" - "Se cambió a %1$s" - "El dispositivo usa %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." - "Se cambió de %1$s a %2$s" + "%1$sno tiene acceso a Internet" + "Presiona para ver opciones" + "La red móvil no tiene acceso a Internet" + "La red no tiene acceso a Internet" + "No se puede acceder al servidor DNS privado" + "%1$s tiene conectividad limitada" + "Presiona para conectarte de todas formas" + "Se cambió a %1$s" + "El dispositivo usa %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." + "Se cambió de %1$s a %2$s" - "Datos móviles" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "Datos móviles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "un tipo de red desconocido" + "un tipo de red desconocido" diff --git a/service/ServiceConnectivityResources/res/values-es/strings.xml b/service/ServiceConnectivityResources/res/values-es/strings.xml index e4f4307f33..f4a7e3d0e8 100644 --- a/service/ServiceConnectivityResources/res/values-es/strings.xml +++ b/service/ServiceConnectivityResources/res/values-es/strings.xml @@ -17,27 +17,27 @@ - "Recursos de conectividad del sistema" - "Iniciar sesión en red Wi-Fi" - "Iniciar sesión en la red" - + "Recursos de conectividad del sistema" + "Iniciar sesión en red Wi-Fi" + "Iniciar sesión en la red" + - "%1$s no tiene acceso a Internet" - "Toca para ver opciones" - "La red móvil no tiene acceso a Internet" - "La red no tiene acceso a Internet" - "No se ha podido acceder al servidor DNS privado" - "%1$s tiene una conectividad limitada" - "Toca para conectarte de todas formas" - "Se ha cambiado a %1$s" - "El dispositivo utiliza %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." - "Se ha cambiado de %1$s a %2$s" + "%1$s no tiene acceso a Internet" + "Toca para ver opciones" + "La red móvil no tiene acceso a Internet" + "La red no tiene acceso a Internet" + "No se ha podido acceder al servidor DNS privado" + "%1$s tiene una conectividad limitada" + "Toca para conectarte de todas formas" + "Se ha cambiado a %1$s" + "El dispositivo utiliza %1$s cuando %2$s no tiene acceso a Internet. Es posible que se apliquen cargos." + "Se ha cambiado de %1$s a %2$s" - "datos móviles" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "datos móviles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "un tipo de red desconocido" + "un tipo de red desconocido" diff --git a/service/ServiceConnectivityResources/res/values-et/strings.xml b/service/ServiceConnectivityResources/res/values-et/strings.xml index cec408fd94..cf997b3336 100644 --- a/service/ServiceConnectivityResources/res/values-et/strings.xml +++ b/service/ServiceConnectivityResources/res/values-et/strings.xml @@ -17,27 +17,27 @@ - "Süsteemi ühenduvuse allikad" - "Logi sisse WiFi-võrku" - "Võrku sisselogimine" - + "Süsteemi ühenduvuse allikad" + "Logi sisse WiFi-võrku" + "Võrku sisselogimine" + - "Võrgul %1$s puudub Interneti-ühendus" - "Puudutage valikute nägemiseks" - "Mobiilsidevõrgul puudub Interneti-ühendus" - "Võrgul puudub Interneti-ühendus" - "Privaatsele DNS-serverile ei pääse juurde" - "Võrgu %1$s ühendus on piiratud" - "Puudutage, kui soovite siiski ühenduse luua" - "Lülitati võrgule %1$s" - "Seade kasutab võrku %1$s, kui võrgul %2$s puudub juurdepääs Internetile. Rakenduda võivad tasud." - "Lülitati võrgult %1$s võrgule %2$s" + "Võrgul %1$s puudub Interneti-ühendus" + "Puudutage valikute nägemiseks" + "Mobiilsidevõrgul puudub Interneti-ühendus" + "Võrgul puudub Interneti-ühendus" + "Privaatsele DNS-serverile ei pääse juurde" + "Võrgu %1$s ühendus on piiratud" + "Puudutage, kui soovite siiski ühenduse luua" + "Lülitati võrgule %1$s" + "Seade kasutab võrku %1$s, kui võrgul %2$s puudub juurdepääs Internetile. Rakenduda võivad tasud." + "Lülitati võrgult %1$s võrgule %2$s" - "mobiilne andmeside" - "WiFi" - "Bluetooth" - "Ethernet" - "VPN" + "mobiilne andmeside" + "WiFi" + "Bluetooth" + "Ethernet" + "VPN" - "tundmatu võrgutüüp" + "tundmatu võrgutüüp" diff --git a/service/ServiceConnectivityResources/res/values-eu/strings.xml b/service/ServiceConnectivityResources/res/values-eu/strings.xml index f3ee9b1287..2c4e431109 100644 --- a/service/ServiceConnectivityResources/res/values-eu/strings.xml +++ b/service/ServiceConnectivityResources/res/values-eu/strings.xml @@ -17,27 +17,27 @@ - "Sistemaren konexio-baliabideak" - "Hasi saioa Wi-Fi sarean" - "Hasi saioa sarean" - + "Sistemaren konexio-baliabideak" + "Hasi saioa Wi-Fi sarean" + "Hasi saioa sarean" + - "Ezin da konektatu Internetera %1$s sarearen bidez" - "Sakatu aukerak ikusteko" - "Sare mugikorra ezin da konektatu Internetera" - "Sarea ezin da konektatu Internetera" - "Ezin da atzitu DNS zerbitzari pribatua" - "%1$s sareak konektagarritasun murriztua du" - "Sakatu hala ere konektatzeko" - "%1$s erabiltzen ari zara orain" - "%2$s Internetera konektatzeko gauza ez denean, %1$s erabiltzen du gailuak. Agian kostuak ordaindu beharko dituzu." - "%1$s erabiltzen ari zinen, baina %2$s erabiltzen ari zara orain" + "Ezin da konektatu Internetera %1$s sarearen bidez" + "Sakatu aukerak ikusteko" + "Sare mugikorra ezin da konektatu Internetera" + "Sarea ezin da konektatu Internetera" + "Ezin da atzitu DNS zerbitzari pribatua" + "%1$s sareak konektagarritasun murriztua du" + "Sakatu hala ere konektatzeko" + "%1$s erabiltzen ari zara orain" + "%2$s Internetera konektatzeko gauza ez denean, %1$s erabiltzen du gailuak. Baliteke zerbait ordaindu behar izatea." + "%1$s erabiltzen ari zinen, baina %2$s erabiltzen ari zara orain" - "datu-konexioa" - "Wifia" - "Bluetooth-a" - "Ethernet-a" - "VPNa" + "datu-konexioa" + "Wifia" + "Bluetooth-a" + "Ethernet-a" + "VPNa" - "sare mota ezezaguna" + "sare mota ezezaguna" diff --git a/service/ServiceConnectivityResources/res/values-fa/strings.xml b/service/ServiceConnectivityResources/res/values-fa/strings.xml index 0c5b147e5a..296ce8ecab 100644 --- a/service/ServiceConnectivityResources/res/values-fa/strings.xml +++ b/service/ServiceConnectivityResources/res/values-fa/strings.xml @@ -17,27 +17,27 @@ - "منابع اتصال سیستم" - "‏ورود به شبکه Wi-Fi" - "ورود به سیستم شبکه" - + "منابع اتصال سیستم" + "‏ورود به شبکه Wi-Fi" + "ورود به سیستم شبکه" + - "%1$s به اینترنت دسترسی ندارد" - "برای گزینه‌ها ضربه بزنید" - "شبکه تلفن همراه به اینترنت دسترسی ندارد" - "شبکه به اینترنت دسترسی ندارد" - "‏سرور DNS خصوصی قابل دسترسی نیست" - "%1$s اتصال محدودی دارد" - "به‌هرصورت، برای اتصال ضربه بزنید" - "به %1$s تغییر کرد" - "وقتی %2$s به اینترنت دسترسی نداشته باشد، دستگاه از %1$s استفاده می‌کند. ممکن است هزینه‌هایی اعمال شود." - "از %1$s به %2$s تغییر کرد" + "%1$s به اینترنت دسترسی ندارد" + "برای گزینه‌ها ضربه بزنید" + "شبکه تلفن همراه به اینترنت دسترسی ندارد" + "شبکه به اینترنت دسترسی ندارد" + "‏سرور DNS خصوصی قابل دسترسی نیست" + "%1$s اتصال محدودی دارد" + "به‌هرصورت، برای اتصال ضربه بزنید" + "به %1$s تغییر کرد" + "وقتی %2$s به اینترنت دسترسی نداشته باشد، دستگاه از %1$s استفاده می‌کند. ممکن است هزینه‌هایی اعمال شود." + "از %1$s به %2$s تغییر کرد" - "داده تلفن همراه" - "Wi-Fi" - "بلوتوث" - "اترنت" - "VPN" + "داده تلفن همراه" + "Wi-Fi" + "بلوتوث" + "اترنت" + "VPN" - "نوع شبکه نامشخص" + "نوع شبکه نامشخص" diff --git a/service/ServiceConnectivityResources/res/values-fi/strings.xml b/service/ServiceConnectivityResources/res/values-fi/strings.xml index 84c0034f8b..07d2907410 100644 --- a/service/ServiceConnectivityResources/res/values-fi/strings.xml +++ b/service/ServiceConnectivityResources/res/values-fi/strings.xml @@ -17,27 +17,27 @@ - "Järjestelmän yhteysresurssit" - "Kirjaudu Wi-Fi-verkkoon" - "Kirjaudu verkkoon" - + "Järjestelmän yhteysresurssit" + "Kirjaudu Wi-Fi-verkkoon" + "Kirjaudu verkkoon" + - "%1$s ei ole yhteydessä internetiin" - "Näytä vaihtoehdot napauttamalla." - "Mobiiliverkko ei ole yhteydessä internetiin" - "Verkko ei ole yhteydessä internetiin" - "Ei pääsyä yksityiselle DNS-palvelimelle" - "%1$s toimii rajoitetulla yhteydellä" - "Yhdistä napauttamalla" - "%1$s otettiin käyttöön" - "%1$s otetaan käyttöön, kun %2$s ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia." - "%1$s poistettiin käytöstä ja %2$s otettiin käyttöön." + "%1$s ei ole yhteydessä internetiin" + "Näytä vaihtoehdot napauttamalla." + "Mobiiliverkko ei ole yhteydessä internetiin" + "Verkko ei ole yhteydessä internetiin" + "Ei pääsyä yksityiselle DNS-palvelimelle" + "%1$s toimii rajoitetulla yhteydellä" + "Yhdistä napauttamalla" + "%1$s otettiin käyttöön" + "%1$s otetaan käyttöön, kun %2$s ei voi muodostaa yhteyttä internetiin. Veloitukset ovat mahdollisia." + "%1$s poistettiin käytöstä ja %2$s otettiin käyttöön." - "mobiilidata" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobiilidata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "tuntematon verkon tyyppi" + "tuntematon verkon tyyppi" diff --git a/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml b/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml index 0badf1be0f..7d5b366cf7 100644 --- a/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml +++ b/service/ServiceConnectivityResources/res/values-fr-rCA/strings.xml @@ -17,27 +17,27 @@ - "Ressources de connectivité système" - "Connectez-vous au réseau Wi-Fi" - "Connectez-vous au réseau" - + "Ressources de connectivité système" + "Connectez-vous au réseau Wi-Fi" + "Connectez-vous au réseau" + - "Le réseau %1$s n\'offre aucun accès à Internet" - "Touchez pour afficher les options" - "Le réseau cellulaire n\'offre aucun accès à Internet" - "Le réseau n\'offre aucun accès à Internet" - "Impossible d\'accéder au serveur DNS privé" - "Le réseau %1$s offre une connectivité limitée" - "Touchez pour vous connecter quand même" - "Passé au réseau %1$s" - "L\'appareil utilise %1$s quand %2$s n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer." - "Passé du réseau %1$s au %2$s" + "Le réseau %1$s n\'offre aucun accès à Internet" + "Touchez pour afficher les options" + "Le réseau cellulaire n\'offre aucun accès à Internet" + "Le réseau n\'offre aucun accès à Internet" + "Impossible d\'accéder au serveur DNS privé" + "Le réseau %1$s offre une connectivité limitée" + "Touchez pour vous connecter quand même" + "Passé au réseau %1$s" + "L\'appareil utilise %1$s quand %2$s n\'a pas d\'accès à Internet. Des frais peuvent s\'appliquer." + "Passé du réseau %1$s au %2$s" - "données cellulaires" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "RPV" + "données cellulaires" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "RPV" - "un type de réseau inconnu" + "un type de réseau inconnu" diff --git a/service/ServiceConnectivityResources/res/values-fr/strings.xml b/service/ServiceConnectivityResources/res/values-fr/strings.xml index b4835258d9..2331d9ba59 100644 --- a/service/ServiceConnectivityResources/res/values-fr/strings.xml +++ b/service/ServiceConnectivityResources/res/values-fr/strings.xml @@ -17,27 +17,27 @@ - "Ressources de connectivité système" - "Connectez-vous au réseau Wi-Fi" - "Se connecter au réseau" - + "Ressources de connectivité système" + "Connectez-vous au réseau Wi-Fi" + "Se connecter au réseau" + - "Aucune connexion à Internet pour %1$s" - "Appuyez ici pour afficher des options." - "Le réseau mobile ne dispose d\'aucun accès à Internet" - "Le réseau ne dispose d\'aucun accès à Internet" - "Impossible d\'accéder au serveur DNS privé" - "La connectivité de %1$s est limitée" - "Appuyer pour se connecter quand même" - "Nouveau réseau : %1$s" - "L\'appareil utilise %1$s lorsque %2$s n\'a pas de connexion Internet. Des frais peuvent s\'appliquer." - "Ancien réseau : %1$s. Nouveau réseau : %2$s" + "Aucune connexion à Internet pour %1$s" + "Appuyez ici pour afficher des options." + "Le réseau mobile ne dispose d\'aucun accès à Internet" + "Le réseau ne dispose d\'aucun accès à Internet" + "Impossible d\'accéder au serveur DNS privé" + "La connectivité de %1$s est limitée" + "Appuyer pour se connecter quand même" + "Nouveau réseau : %1$s" + "L\'appareil utilise %1$s lorsque %2$s n\'a pas de connexion Internet. Des frais peuvent s\'appliquer." + "Ancien réseau : %1$s. Nouveau réseau : %2$s" - "données mobiles" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "données mobiles" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "type de réseau inconnu" + "type de réseau inconnu" diff --git a/service/ServiceConnectivityResources/res/values-gl/strings.xml b/service/ServiceConnectivityResources/res/values-gl/strings.xml index dfe813746e..f46f84b0d9 100644 --- a/service/ServiceConnectivityResources/res/values-gl/strings.xml +++ b/service/ServiceConnectivityResources/res/values-gl/strings.xml @@ -17,27 +17,27 @@ - "Recursos de conectividade do sistema" - "Inicia sesión na rede wifi" - "Inicia sesión na rede" - + "Recursos de conectividade do sistema" + "Inicia sesión na rede wifi" + "Inicia sesión na rede" + - "%1$s non ten acceso a Internet" - "Toca para ver opcións." - "A rede de telefonía móbil non ten acceso a Internet" - "A rede non ten acceso a Internet" - "Non se puido acceder ao servidor DNS privado" - "A conectividade de %1$s é limitada" - "Toca para conectarte de todas formas" - "Cambiouse a: %1$s" - "O dispositivo utiliza %1$s cando %2$s non ten acceso a Internet. Pódense aplicar cargos." - "Cambiouse de %1$s a %2$s" + "%1$s non ten acceso a Internet" + "Toca para ver opcións." + "A rede de telefonía móbil non ten acceso a Internet" + "A rede non ten acceso a Internet" + "Non se puido acceder ao servidor DNS privado" + "A conectividade de %1$s é limitada" + "Toca para conectarte de todas formas" + "Cambiouse a: %1$s" + "O dispositivo utiliza %1$s cando %2$s non ten acceso a Internet. Pódense aplicar cargos." + "Cambiouse de %1$s a %2$s" - "datos móbiles" - "wifi" - "Bluetooth" - "Ethernet" - "VPN" + "datos móbiles" + "wifi" + "Bluetooth" + "Ethernet" + "VPN" - "un tipo de rede descoñecido" + "un tipo de rede descoñecido" diff --git a/service/ServiceConnectivityResources/res/values-gu/strings.xml b/service/ServiceConnectivityResources/res/values-gu/strings.xml index e49b11d21e..ec9ecd30ec 100644 --- a/service/ServiceConnectivityResources/res/values-gu/strings.xml +++ b/service/ServiceConnectivityResources/res/values-gu/strings.xml @@ -17,27 +17,27 @@ - "સિસ્ટમની કનેક્ટિવિટીનાં સાધનો" - "વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો" - "નેટવર્ક પર સાઇન ઇન કરો" - + "સિસ્ટમની કનેક્ટિવિટીનાં સાધનો" + "વાઇ-ફાઇ નેટવર્ક પર સાઇન ઇન કરો" + "નેટવર્ક પર સાઇન ઇન કરો" + - "%1$s ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" - "વિકલ્પો માટે ટૅપ કરો" - "મોબાઇલ નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" - "નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" - "ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી" - "%1$s મર્યાદિત કનેક્ટિવિટી ધરાવે છે" - "છતાં કનેક્ટ કરવા માટે ટૅપ કરો" - "%1$s પર સ્વિચ કર્યું" - "જ્યારે %2$s પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ %1$sનો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે." - "%1$s પરથી %2$s પર સ્વિચ કર્યું" + "%1$s ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "વિકલ્પો માટે ટૅપ કરો" + "મોબાઇલ નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "નેટવર્ક કોઈ ઇન્ટરનેટ ઍક્સેસ ધરાવતું નથી" + "ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી" + "%1$s મર્યાદિત કનેક્ટિવિટી ધરાવે છે" + "છતાં કનેક્ટ કરવા માટે ટૅપ કરો" + "%1$s પર સ્વિચ કર્યું" + "જ્યારે %2$s પાસે કોઈ ઇન્ટરનેટ ઍક્સેસ ન હોય ત્યારે ઉપકરણ %1$sનો ઉપયોગ કરે છે. શુલ્ક લાગુ થઈ શકે છે." + "%1$s પરથી %2$s પર સ્વિચ કર્યું" - "મોબાઇલ ડેટા" - "વાઇ-ફાઇ" - "બ્લૂટૂથ" - "ઇથરનેટ" - "VPN" + "મોબાઇલ ડેટા" + "વાઇ-ફાઇ" + "બ્લૂટૂથ" + "ઇથરનેટ" + "VPN" - "કોઈ અજાણ્યો નેટવર્કનો પ્રકાર" + "કોઈ અજાણ્યો નેટવર્કનો પ્રકાર" diff --git a/service/ServiceConnectivityResources/res/values-hi/strings.xml b/service/ServiceConnectivityResources/res/values-hi/strings.xml index 80ed699768..6e3bc6b919 100644 --- a/service/ServiceConnectivityResources/res/values-hi/strings.xml +++ b/service/ServiceConnectivityResources/res/values-hi/strings.xml @@ -17,27 +17,27 @@ - "सिस्टम कनेक्टिविटी के संसाधन" - "वाई-फ़ाई नेटवर्क में साइन इन करें" - "नेटवर्क में साइन इन करें" - + "सिस्टम कनेक्टिविटी के संसाधन" + "वाई-फ़ाई नेटवर्क में साइन इन करें" + "नेटवर्क में साइन इन करें" + - "%1$s का इंटरनेट नहीं चल रहा है" - "विकल्पों के लिए टैप करें" - "मोबाइल नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" - "इस नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" - "निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता" - "%1$s की कनेक्टिविटी सीमित है" - "फिर भी कनेक्ट करने के लिए टैप करें" - "%1$s पर ले जाया गया" - "%2$s में इंटरनेट की सुविधा नहीं होने पर डिवाइस %1$s का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है." - "%1$s से %2$s पर ले जाया गया" + "%1$s का इंटरनेट नहीं चल रहा है" + "विकल्पों के लिए टैप करें" + "मोबाइल नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" + "इस नेटवर्क पर इंटरनेट ऐक्सेस नहीं है" + "निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता" + "%1$s की कनेक्टिविटी सीमित है" + "फिर भी कनेक्ट करने के लिए टैप करें" + "%1$s पर ले जाया गया" + "%2$s में इंटरनेट की सुविधा नहीं होने पर डिवाइस %1$s का इस्तेमाल करता है. इसके लिए शुल्क लिया जा सकता है." + "%1$s से %2$s पर ले जाया गया" - "मोबाइल डेटा" - "वाई-फ़ाई" - "ब्लूटूथ" - "ईथरनेट" - "वीपीएन" + "मोबाइल डेटा" + "वाई-फ़ाई" + "ब्लूटूथ" + "ईथरनेट" + "वीपीएन" - "अज्ञात नेटवर्क टाइप" + "अज्ञात नेटवर्क टाइप" diff --git a/service/ServiceConnectivityResources/res/values-hr/strings.xml b/service/ServiceConnectivityResources/res/values-hr/strings.xml index 24bb22fd69..6a6de4cdaf 100644 --- a/service/ServiceConnectivityResources/res/values-hr/strings.xml +++ b/service/ServiceConnectivityResources/res/values-hr/strings.xml @@ -17,27 +17,27 @@ - "Resursi za povezivost sustava" - "Prijava na Wi-Fi mrežu" - "Prijava na mrežu" - + "Resursi za povezivost sustava" + "Prijava na Wi-Fi mrežu" + "Prijava na mrežu" + - "%1$s nema pristup internetu" - "Dodirnite za opcije" - "Mobilna mreža nema pristup internetu" - "Mreža nema pristup internetu" - "Nije moguće pristupiti privatnom DNS poslužitelju" - "%1$s ima ograničenu povezivost" - "Dodirnite da biste se ipak povezali" - "Prelazak na drugu mrežu: %1$s" - "Kada %2$s nema pristup internetu, na uređaju se upotrebljava %1$s. Moguća je naplata naknade." - "Mreža je promijenjena: %1$s > %2$s" + "%1$s nema pristup internetu" + "Dodirnite za opcije" + "Mobilna mreža nema pristup internetu" + "Mreža nema pristup internetu" + "Nije moguće pristupiti privatnom DNS poslužitelju" + "%1$s ima ograničenu povezivost" + "Dodirnite da biste se ipak povezali" + "Prelazak na drugu mrežu: %1$s" + "Kada %2$s nema pristup internetu, na uređaju se upotrebljava %1$s. Moguća je naplata naknade." + "Mreža je promijenjena: %1$s > %2$s" - "mobilni podaci" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobilni podaci" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "nepoznata vrsta mreže" + "nepoznata vrsta mreže" diff --git a/service/ServiceConnectivityResources/res/values-hu/strings.xml b/service/ServiceConnectivityResources/res/values-hu/strings.xml index 47a1142ac3..1d39d308f7 100644 --- a/service/ServiceConnectivityResources/res/values-hu/strings.xml +++ b/service/ServiceConnectivityResources/res/values-hu/strings.xml @@ -17,27 +17,27 @@ - "Rendszerkapcsolat erőforrásai" - "Bejelentkezés Wi-Fi hálózatba" - "Bejelentkezés a hálózatba" - + "Rendszerkapcsolat erőforrásai" + "Bejelentkezés Wi-Fi hálózatba" + "Bejelentkezés a hálózatba" + - "A(z) %1$s hálózaton nincs internet-hozzáférés" - "Koppintson a beállítások megjelenítéséhez" - "A mobilhálózaton nincs internet-hozzáférés" - "A hálózaton nincs internet-hozzáférés" - "A privát DNS-kiszolgálóhoz nem lehet hozzáférni" - "A(z) %1$s hálózat korlátozott kapcsolatot biztosít" - "Koppintson, ha mindenképpen csatlakozni szeretne" - "Átváltva erre: %1$s" - "%1$s használata, ha nincs internet-hozzáférés %2$s-kapcsolaton keresztül. A szolgáltató díjat számíthat fel." - "Átváltva %1$s-hálózatról erre: %2$s" + "A(z) %1$s hálózaton nincs internet-hozzáférés" + "Koppintson a beállítások megjelenítéséhez" + "A mobilhálózaton nincs internet-hozzáférés" + "A hálózaton nincs internet-hozzáférés" + "A privát DNS-kiszolgálóhoz nem lehet hozzáférni" + "A(z) %1$s hálózat korlátozott kapcsolatot biztosít" + "Koppintson, ha mindenképpen csatlakozni szeretne" + "Átváltva erre: %1$s" + "%1$s használata, ha nincs internet-hozzáférés %2$s-kapcsolaton keresztül. A szolgáltató díjat számíthat fel." + "Átváltva %1$s-hálózatról erre: %2$s" - "mobiladatok" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobiladatok" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "ismeretlen hálózati típus" + "ismeretlen hálózati típus" diff --git a/service/ServiceConnectivityResources/res/values-hy/strings.xml b/service/ServiceConnectivityResources/res/values-hy/strings.xml index dd951e8182..99386d445a 100644 --- a/service/ServiceConnectivityResources/res/values-hy/strings.xml +++ b/service/ServiceConnectivityResources/res/values-hy/strings.xml @@ -17,27 +17,27 @@ - "System Connectivity Resources" - "Մուտք գործեք Wi-Fi ցանց" - "Մուտք գործեք ցանց" - + "System Connectivity Resources" + "Մուտք գործեք Wi-Fi ցանց" + "Մուտք գործեք ցանց" + - "%1$s ցանցը չունի մուտք ինտերնետին" - "Հպեք՝ ընտրանքները տեսնելու համար" - "Բջջային ցանցը չի ապահովում ինտերնետ կապ" - "Ցանցը միացված չէ ինտերնետին" - "Մասնավոր DNS սերվերն անհասանելի է" - "%1$s ցանցի կապը սահմանափակ է" - "Հպեք՝ միանալու համար" - "Անցել է %1$s ցանցի" - "Երբ %2$s ցանցում ինտերնետ կապ չի լինում, սարքն անցնում է %1$s ցանցի: Նման դեպքում կարող են վճարներ գանձվել:" - "%1$s ցանցից անցել է %2$s ցանցի" + "%1$s ցանցը չունի մուտք ինտերնետին" + "Հպեք՝ ընտրանքները տեսնելու համար" + "Բջջային ցանցը չի ապահովում ինտերնետ կապ" + "Ցանցը միացված չէ ինտերնետին" + "Մասնավոր DNS սերվերն անհասանելի է" + "%1$s ցանցի կապը սահմանափակ է" + "Հպեք՝ միանալու համար" + "Անցել է %1$s ցանցի" + "Երբ %2$s ցանցում ինտերնետ կապ չի լինում, սարքն անցնում է %1$s ցանցի: Նման դեպքում կարող են վճարներ գանձվել:" + "%1$s ցանցից անցել է %2$s ցանցի" - "բջջային ինտերնետ" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "բջջային ինտերնետ" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "ցանցի անհայտ տեսակ" + "ցանցի անհայտ տեսակ" diff --git a/service/ServiceConnectivityResources/res/values-in/strings.xml b/service/ServiceConnectivityResources/res/values-in/strings.xml index d559f6b11e..f47d25752e 100644 --- a/service/ServiceConnectivityResources/res/values-in/strings.xml +++ b/service/ServiceConnectivityResources/res/values-in/strings.xml @@ -17,27 +17,27 @@ - "Resource Konektivitas Sistem" - "Login ke jaringan Wi-Fi" - "Login ke jaringan" - + "Resource Konektivitas Sistem" + "Login ke jaringan Wi-Fi" + "Login ke jaringan" + - "%1$s tidak memiliki akses internet" - "Ketuk untuk melihat opsi" - "Jaringan seluler tidak memiliki akses internet" - "Jaringan tidak memiliki akses internet" - "Server DNS pribadi tidak dapat diakses" - "%1$s memiliki konektivitas terbatas" - "Ketuk untuk tetap menyambungkan" - "Dialihkan ke %1$s" - "Perangkat menggunakan %1$s jika %2$s tidak memiliki akses internet. Tarif mungkin berlaku." - "Dialihkan dari %1$s ke %2$s" + "%1$s tidak memiliki akses internet" + "Ketuk untuk melihat opsi" + "Jaringan seluler tidak memiliki akses internet" + "Jaringan tidak memiliki akses internet" + "Server DNS pribadi tidak dapat diakses" + "%1$s memiliki konektivitas terbatas" + "Ketuk untuk tetap menyambungkan" + "Dialihkan ke %1$s" + "Perangkat menggunakan %1$s jika %2$s tidak memiliki akses internet. Tarif mungkin berlaku." + "Dialihkan dari %1$s ke %2$s" - "data seluler" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "data seluler" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "jenis jaringan yang tidak dikenal" + "jenis jaringan yang tidak dikenal" diff --git a/service/ServiceConnectivityResources/res/values-is/strings.xml b/service/ServiceConnectivityResources/res/values-is/strings.xml index 877c85f147..eeba2311fa 100644 --- a/service/ServiceConnectivityResources/res/values-is/strings.xml +++ b/service/ServiceConnectivityResources/res/values-is/strings.xml @@ -17,27 +17,27 @@ - "Tengigögn kerfis" - "Skrá inn á Wi-Fi net" - "Skrá inn á net" - + "Tengigögn kerfis" + "Skrá inn á Wi-Fi net" + "Skrá inn á net" + - "%1$s er ekki með internetaðgang" - "Ýttu til að sjá valkosti" - "Farsímakerfið er ekki tengt við internetið" - "Netkerfið er ekki tengt við internetið" - "Ekki næst í DNS-einkaþjón" - "Tengigeta %1$s er takmörkuð" - "Ýttu til að tengjast samt" - "Skipt yfir á %1$s" - "Tækið notar %1$s þegar %2$s er ekki með internetaðgang. Gjöld kunna að eiga við." - "Skipt úr %1$s yfir í %2$s" + "%1$s er ekki með internetaðgang" + "Ýttu til að sjá valkosti" + "Farsímakerfið er ekki tengt við internetið" + "Netkerfið er ekki tengt við internetið" + "Ekki næst í DNS-einkaþjón" + "Tengigeta %1$s er takmörkuð" + "Ýttu til að tengjast samt" + "Skipt yfir á %1$s" + "Tækið notar %1$s þegar %2$s er ekki með internetaðgang. Gjöld kunna að eiga við." + "Skipt úr %1$s yfir í %2$s" - "farsímagögn" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "farsímagögn" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "óþekkt tegund netkerfis" + "óþekkt tegund netkerfis" diff --git a/service/ServiceConnectivityResources/res/values-it/strings.xml b/service/ServiceConnectivityResources/res/values-it/strings.xml index bcac393c9c..ec3ff8c711 100644 --- a/service/ServiceConnectivityResources/res/values-it/strings.xml +++ b/service/ServiceConnectivityResources/res/values-it/strings.xml @@ -17,27 +17,27 @@ - "Risorse per connettività di sistema" - "Accedi a rete Wi-Fi" - "Accedi alla rete" - + "Risorse per connettività di sistema" + "Accedi a rete Wi-Fi" + "Accedi alla rete" + - "%1$s non ha accesso a Internet" - "Tocca per le opzioni" - "La rete mobile non ha accesso a Internet" - "La rete non ha accesso a Internet" - "Non è possibile accedere al server DNS privato" - "%1$s ha una connettività limitata" - "Tocca per connettere comunque" - "Passato a %1$s" - "Il dispositivo utilizza %1$s quando %2$s non ha accesso a Internet. Potrebbero essere applicati costi." - "Passato da %1$s a %2$s" + "%1$s non ha accesso a Internet" + "Tocca per le opzioni" + "La rete mobile non ha accesso a Internet" + "La rete non ha accesso a Internet" + "Non è possibile accedere al server DNS privato" + "%1$s ha una connettività limitata" + "Tocca per connettere comunque" + "Passato a %1$s" + "Il dispositivo utilizza %1$s quando %2$s non ha accesso a Internet. Potrebbero essere applicati costi." + "Passato da %1$s a %2$s" - "dati mobili" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "dati mobili" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "tipo di rete sconosciuto" + "tipo di rete sconosciuto" diff --git a/service/ServiceConnectivityResources/res/values-iw/strings.xml b/service/ServiceConnectivityResources/res/values-iw/strings.xml index d6684ce106..d123ebba03 100644 --- a/service/ServiceConnectivityResources/res/values-iw/strings.xml +++ b/service/ServiceConnectivityResources/res/values-iw/strings.xml @@ -17,27 +17,27 @@ - "משאבי קישוריות מערכת" - "‏היכנס לרשת Wi-Fi" - "היכנס לרשת" - + "משאבי קישוריות מערכת" + "‏היכנס לרשת Wi-Fi" + "היכנס לרשת" + - "ל-%1$s אין גישה לאינטרנט" - "הקש לקבלת אפשרויות" - "לרשת הסלולרית אין גישה לאינטרנט" - "לרשת אין גישה לאינטרנט" - "‏לא ניתן לגשת לשרת DNS הפרטי" - "הקישוריות של %1$s מוגבלת" - "כדי להתחבר למרות זאת יש להקיש" - "מעבר אל %1$s" - "המכשיר משתמש ברשת %1$s כשלרשת %2$s אין גישה לאינטרנט. עשויים לחול חיובים." - "עבר מרשת %1$s לרשת %2$s" + "ל-%1$s אין גישה לאינטרנט" + "הקש לקבלת אפשרויות" + "לרשת הסלולרית אין גישה לאינטרנט" + "לרשת אין גישה לאינטרנט" + "‏לא ניתן לגשת לשרת DNS הפרטי" + "הקישוריות של %1$s מוגבלת" + "כדי להתחבר למרות זאת יש להקיש" + "מעבר אל %1$s" + "המכשיר משתמש ברשת %1$s כשלרשת %2$s אין גישה לאינטרנט. עשויים לחול חיובים." + "עבר מרשת %1$s לרשת %2$s" - "חבילת גלישה" - "Wi-Fi" - "Bluetooth" - "אתרנט" - "VPN" + "חבילת גלישה" + "Wi-Fi" + "Bluetooth" + "אתרנט" + "VPN" - "סוג רשת לא מזוהה" + "סוג רשת לא מזוהה" diff --git a/service/ServiceConnectivityResources/res/values-ja/strings.xml b/service/ServiceConnectivityResources/res/values-ja/strings.xml index fa4a30aedb..7bb6f85620 100644 --- a/service/ServiceConnectivityResources/res/values-ja/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ja/strings.xml @@ -17,27 +17,27 @@ - "システム接続リソース" - "Wi-Fiネットワークにログイン" - "ネットワークにログインしてください" - + "システム接続リソース" + "Wi-Fiネットワークにログイン" + "ネットワークにログインしてください" + - "%1$s はインターネットにアクセスできません" - "タップしてその他のオプションを表示" - "モバイル ネットワークがインターネットに接続されていません" - "ネットワークがインターネットに接続されていません" - "プライベート DNS サーバーにアクセスできません" - "%1$s の接続が制限されています" - "接続するにはタップしてください" - "「%1$s」に切り替えました" - "デバイスで「%2$s」によるインターネット接続ができない場合に「%1$s」を使用します。通信料が発生することがあります。" - "「%1$s」から「%2$s」に切り替えました" + "%1$s はインターネットにアクセスできません" + "タップしてその他のオプションを表示" + "モバイル ネットワークがインターネットに接続されていません" + "ネットワークがインターネットに接続されていません" + "プライベート DNS サーバーにアクセスできません" + "%1$s の接続が制限されています" + "接続するにはタップしてください" + "「%1$s」に切り替えました" + "デバイスで「%2$s」によるインターネット接続ができない場合に「%1$s」を使用します。通信料が発生することがあります。" + "「%1$s」から「%2$s」に切り替えました" - "モバイルデータ" - "Wi-Fi" - "Bluetooth" - "イーサネット" - "VPN" + "モバイルデータ" + "Wi-Fi" + "Bluetooth" + "イーサネット" + "VPN" - "不明なネットワーク タイプ" + "不明なネットワーク タイプ" diff --git a/service/ServiceConnectivityResources/res/values-ka/strings.xml b/service/ServiceConnectivityResources/res/values-ka/strings.xml index 418331036e..f42c567147 100644 --- a/service/ServiceConnectivityResources/res/values-ka/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ka/strings.xml @@ -17,27 +17,27 @@ - "სისტემის კავშირის რესურსები" - "Wi-Fi ქსელთან დაკავშირება" - "ქსელში შესვლა" - + "სისტემის კავშირის რესურსები" + "Wi-Fi ქსელთან დაკავშირება" + "ქსელში შესვლა" + - "%1$s-ს არ აქვს ინტერნეტზე წვდომა" - "შეეხეთ ვარიანტების სანახავად" - "მობილურ ქსელს არ აქვს ინტერნეტზე წვდომა" - "ქსელს არ აქვს ინტერნეტზე წვდომა" - "პირად DNS სერვერზე წვდომა შეუძლებელია" - "%1$s-ის კავშირები შეზღუდულია" - "შეეხეთ, თუ მაინც გსურთ დაკავშირება" - "ახლა გამოიყენება %1$s" - "თუ %2$s ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ %1$s იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს." - "ახლა გამოიყენება %1$s (გამოიყენებოდა %2$s)" + "%1$s-ს არ აქვს ინტერნეტზე წვდომა" + "შეეხეთ ვარიანტების სანახავად" + "მობილურ ქსელს არ აქვს ინტერნეტზე წვდომა" + "ქსელს არ აქვს ინტერნეტზე წვდომა" + "პირად DNS სერვერზე წვდომა შეუძლებელია" + "%1$s-ის კავშირები შეზღუდულია" + "შეეხეთ, თუ მაინც გსურთ დაკავშირება" + "ახლა გამოიყენება %1$s" + "თუ %2$s ინტერნეტთან კავშირს დაკარგავს, მოწყობილობის მიერ %1$s იქნება გამოყენებული, რამაც შეიძლება დამატებითი ხარჯები გამოიწვიოს." + "ახლა გამოიყენება %1$s (გამოიყენებოდა %2$s)" - "მობილური ინტერნეტი" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "მობილური ინტერნეტი" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "უცნობი ტიპის ქსელი" + "უცნობი ტიპის ქსელი" diff --git a/service/ServiceConnectivityResources/res/values-kk/strings.xml b/service/ServiceConnectivityResources/res/values-kk/strings.xml index 54d5eb30cd..00c0f3926e 100644 --- a/service/ServiceConnectivityResources/res/values-kk/strings.xml +++ b/service/ServiceConnectivityResources/res/values-kk/strings.xml @@ -17,27 +17,27 @@ - "Жүйе байланысы ресурстары" - "Wi-Fi желісіне кіру" - "Желіге кіру" - + "Жүйе байланысы ресурстары" + "Wi-Fi желісіне кіру" + "Желіге кіру" + - "%1$s желісінің интернетті пайдалану мүмкіндігі шектеулі." - "Опциялар үшін түртіңіз" - "Мобильдік желі интернетке қосылмаған." - "Желі интернетке қосылмаған." - "Жеке DNS серверіне кіру мүмкін емес." - "%1$s желісінің қосылу мүмкіндігі шектеулі." - "Бәрібір жалғау үшін түртіңіз." - "%1$s желісіне ауысты" - "Құрылғы %2$s желісінде интернетпен байланыс жоғалған жағдайда %1$s желісін пайдаланады. Деректер ақысы алынуы мүмкін." - "%1$s желісінен %2$s желісіне ауысты" + "%1$s желісінің интернетті пайдалану мүмкіндігі шектеулі." + "Опциялар үшін түртіңіз" + "Мобильдік желі интернетке қосылмаған." + "Желі интернетке қосылмаған." + "Жеке DNS серверіне кіру мүмкін емес." + "%1$s желісінің қосылу мүмкіндігі шектеулі." + "Бәрібір жалғау үшін түртіңіз." + "%1$s желісіне ауысты" + "Құрылғы %2$s желісінде интернетпен байланыс жоғалған жағдайда %1$s желісін пайдаланады. Деректер ақысы алынуы мүмкін." + "%1$s желісінен %2$s желісіне ауысты" - "мобильдік деректер" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "мобильдік деректер" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "желі түрі белгісіз" + "желі түрі белгісіз" diff --git a/service/ServiceConnectivityResources/res/values-km/strings.xml b/service/ServiceConnectivityResources/res/values-km/strings.xml index bd778a1623..fa06c5b421 100644 --- a/service/ServiceConnectivityResources/res/values-km/strings.xml +++ b/service/ServiceConnectivityResources/res/values-km/strings.xml @@ -17,27 +17,27 @@ - "ធនធាន​តភ្ជាប់​ប្រព័ន្ធ" - "ចូល​បណ្ដាញ​វ៉ាយហ្វាយ" - "ចូលទៅបណ្តាញ" - + "ធនធាន​តភ្ជាប់​ប្រព័ន្ធ" + "ចូល​បណ្ដាញ​វ៉ាយហ្វាយ" + "ចូលទៅបណ្តាញ" + - "%1$s មិនមាន​ការតភ្ជាប់អ៊ីនធឺណិត​ទេ" - "ប៉ះសម្រាប់ជម្រើស" - "បណ្ដាញ​ទូរសព្ទ​ចល័ត​មិនមានការតភ្ជាប់​អ៊ីនធឺណិតទេ" - "បណ្ដាញ​មិនមាន​ការតភ្ជាប់​អ៊ីនធឺណិតទេ" - "មិនអាច​ចូលប្រើ​ម៉ាស៊ីនមេ DNS ឯកជន​បានទេ" - "%1$s មានការតភ្ជាប់​មានកម្រិត" - "មិន​អី​ទេ ចុច​​ភ្ជាប់​ចុះ" - "បានប្តូរទៅ %1$s" - "ឧបករណ៍​ប្រើ %1$s នៅ​ពេល​ដែល %2$s មិនមាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត។ អាច​គិតថ្លៃ​លើការ​ប្រើប្រាស់​ទិន្នន័យ។" - "បានប្តូរពី %1$s ទៅ %2$s" + "%1$s មិនមាន​ការតភ្ជាប់អ៊ីនធឺណិត​ទេ" + "ប៉ះសម្រាប់ជម្រើស" + "បណ្ដាញ​ទូរសព្ទ​ចល័ត​មិនមានការតភ្ជាប់​អ៊ីនធឺណិតទេ" + "បណ្ដាញ​មិនមាន​ការតភ្ជាប់​អ៊ីនធឺណិតទេ" + "មិនអាច​ចូលប្រើ​ម៉ាស៊ីនមេ DNS ឯកជន​បានទេ" + "%1$s មានការតភ្ជាប់​មានកម្រិត" + "មិន​អី​ទេ ចុច​​ភ្ជាប់​ចុះ" + "បានប្តូរទៅ %1$s" + "ឧបករណ៍​ប្រើ %1$s នៅ​ពេល​ដែល %2$s មិនមាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត។ អាច​គិតថ្លៃ​លើការ​ប្រើប្រាស់​ទិន្នន័យ។" + "បានប្តូរពី %1$s ទៅ %2$s" - "ទិន្នន័យ​ទូរសព្ទចល័ត" - "Wi-Fi" - "ប៊្លូធូស" - "អ៊ីសឺរណិត" - "VPN" + "ទិន្នន័យ​ទូរសព្ទចល័ត" + "Wi-Fi" + "ប៊្លូធូស" + "អ៊ីសឺរណិត" + "VPN" - "ប្រភេទបណ្តាញដែលមិនស្គាល់" + "ប្រភេទបណ្តាញដែលមិនស្គាល់" diff --git a/service/ServiceConnectivityResources/res/values-kn/strings.xml b/service/ServiceConnectivityResources/res/values-kn/strings.xml index 7f3a420dac..cde8facd83 100644 --- a/service/ServiceConnectivityResources/res/values-kn/strings.xml +++ b/service/ServiceConnectivityResources/res/values-kn/strings.xml @@ -17,27 +17,27 @@ - "ಸಿಸ್ಟಂ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆ ಮಾಹಿತಿಯ ಮೂಲಗಳು" - "ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" - "ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" - + "ಸಿಸ್ಟಂ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆ ಮಾಹಿತಿಯ ಮೂಲಗಳು" + "ವೈ-ಫೈ ನೆಟ್‍ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" + "ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ" + - "%1$s ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ" - "ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ" - "ಮೊಬೈಲ್ ನೆಟ್‌ವರ್ಕ್‌ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" - "ನೆಟ್‌ವರ್ಕ್‌ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" - "ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" - "%1$s ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ" - "ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ" - "%1$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" - "%2$s ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು %1$s ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು." - "%1$s ರಿಂದ %2$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" + "%1$s ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ" + "ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ" + "ಮೊಬೈಲ್ ನೆಟ್‌ವರ್ಕ್‌ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" + "ನೆಟ್‌ವರ್ಕ್‌ ಇಂಟರ್ನೆಟ್‌ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ" + "ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" + "%1$s ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ" + "ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ" + "%1$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" + "%2$s ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶ ಹೊಂದಿಲ್ಲದಿರುವಾಗ, ಸಾಧನವು %1$s ಬಳಸುತ್ತದೆ. ಶುಲ್ಕಗಳು ಅನ್ವಯವಾಗಬಹುದು." + "%1$s ರಿಂದ %2$s ಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ" - "ಮೊಬೈಲ್ ಡೇಟಾ" - "ವೈ-ಫೈ" - "ಬ್ಲೂಟೂತ್" - "ಇಥರ್ನೆಟ್" - "VPN" + "ಮೊಬೈಲ್ ಡೇಟಾ" + "ವೈ-ಫೈ" + "ಬ್ಲೂಟೂತ್" + "ಇಥರ್ನೆಟ್" + "VPN" - "ಅಪರಿಚಿತ ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ" + "ಅಪರಿಚಿತ ನೆಟ್‌ವರ್ಕ್ ಪ್ರಕಾರ" diff --git a/service/ServiceConnectivityResources/res/values-ko/strings.xml b/service/ServiceConnectivityResources/res/values-ko/strings.xml index a763cc5e9c..eef59a9289 100644 --- a/service/ServiceConnectivityResources/res/values-ko/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ko/strings.xml @@ -17,27 +17,27 @@ - "시스템 연결 리소스" - "Wi-Fi 네트워크에 로그인" - "네트워크에 로그인" - + "시스템 연결 리소스" + "Wi-Fi 네트워크에 로그인" + "네트워크에 로그인" + - "%1$s이(가) 인터넷에 액세스할 수 없습니다." - "탭하여 옵션 보기" - "모바일 네트워크에 인터넷이 연결되어 있지 않습니다." - "네트워크에 인터넷이 연결되어 있지 않습니다." - "비공개 DNS 서버에 액세스할 수 없습니다." - "%1$s에서 연결을 제한했습니다." - "계속 연결하려면 탭하세요." - "%1$s(으)로 전환" - "%2$s(으)로 인터넷에 연결할 수 없는 경우 기기에서 %1$s이(가) 사용됩니다. 요금이 부과될 수 있습니다." - "%1$s에서 %2$s(으)로 전환" + "%1$s이(가) 인터넷에 액세스할 수 없습니다." + "탭하여 옵션 보기" + "모바일 네트워크에 인터넷이 연결되어 있지 않습니다." + "네트워크에 인터넷이 연결되어 있지 않습니다." + "비공개 DNS 서버에 액세스할 수 없습니다." + "%1$s에서 연결을 제한했습니다." + "계속 연결하려면 탭하세요." + "%1$s(으)로 전환" + "%2$s(으)로 인터넷에 연결할 수 없는 경우 기기에서 %1$s이(가) 사용됩니다. 요금이 부과될 수 있습니다." + "%1$s에서 %2$s(으)로 전환" - "모바일 데이터" - "Wi-Fi" - "블루투스" - "이더넷" - "VPN" + "모바일 데이터" + "Wi-Fi" + "블루투스" + "이더넷" + "VPN" - "알 수 없는 네트워크 유형" + "알 수 없는 네트워크 유형" diff --git a/service/ServiceConnectivityResources/res/values-ky/strings.xml b/service/ServiceConnectivityResources/res/values-ky/strings.xml index 3550af80cd..0027c8a706 100644 --- a/service/ServiceConnectivityResources/res/values-ky/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ky/strings.xml @@ -17,27 +17,27 @@ - "Тутумдун байланыш булагы" - "Wi-Fi түйүнүнө кирүү" - "Тармакка кирүү" - + "Системанын байланыш булагы" + "Wi-Fi түйүнүнө кирүү" + "Тармакка кирүү" + - "%1$s Интернетке туташуусу жок" - "Параметрлерди ачуу үчүн таптап коюңуз" - "Мобилдик Интернет жок" - "Тармактын Интернет жок" - "Жеке DNS сервери жеткиликсиз" - "%1$s байланышы чектелген" - "Баары бир туташуу үчүн таптаңыз" - "%1$s тармагына которуштурулду" - "%2$s тармагы Интернетке туташпай турганда, түзмөгүңүз %1$s тармагын колдонот. Акы алынышы мүмкүн." - "%1$s дегенден %2$s тармагына которуштурулду" + "%1$s Интернетке туташуусу жок" + "Параметрлерди ачуу үчүн таптап коюңуз" + "Мобилдик Интернет жок" + "Тармактын Интернет жок" + "Жеке DNS сервери жеткиликсиз" + "%1$s байланышы чектелген" + "Баары бир туташуу үчүн таптаңыз" + "%1$s тармагына которуштурулду" + "%2$s тармагы Интернетке туташпай турганда, түзмөгүңүз %1$s тармагын колдонот. Акы алынышы мүмкүн." + "%1$s дегенден %2$s тармагына которуштурулду" - "мобилдик трафик" - "Wi‑Fi" - "Bluetooth" - "Ethernet" - "VPN" + "мобилдик трафик" + "Wi‑Fi" + "Bluetooth" + "Ethernet" + "VPN" - "белгисиз тармак түрү" + "белгисиз тармак түрү" diff --git a/service/ServiceConnectivityResources/res/values-lo/strings.xml b/service/ServiceConnectivityResources/res/values-lo/strings.xml index 4b3056f540..64419f9e96 100644 --- a/service/ServiceConnectivityResources/res/values-lo/strings.xml +++ b/service/ServiceConnectivityResources/res/values-lo/strings.xml @@ -17,27 +17,27 @@ - "ແຫຼ່ງຂໍ້ມູນການເຊື່ອມຕໍ່ລະບົບ" - "ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi" - "ລົງຊື່ເຂົ້າເຄືອຂ່າຍ" - + "ແຫຼ່ງຂໍ້ມູນການເຊື່ອມຕໍ່ລະບົບ" + "ເຂົ້າສູ່ລະບົບເຄືອຂ່າຍ Wi-Fi" + "ລົງຊື່ເຂົ້າເຄືອຂ່າຍ" + - "%1$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ" - "ແຕະເພື່ອເບິ່ງຕົວເລືອກ" - "ເຄືອຂ່າຍມືຖືບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" - "ເຄືອຂ່າຍບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" - "ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້" - "%1$s ມີການເຊື່ອມຕໍ່ທີ່ຈຳກັດ" - "ແຕະເພື່ອຢືນຢັນການເຊື່ອມຕໍ່" - "ສະຫຼັບໄປໃຊ້ %1$s ແລ້ວ" - "ອຸປະກອນຈະໃຊ້ %1$s ເມື່ອ %2$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ." - "ສະຫຼັບຈາກ %1$s ໄປໃຊ້ %2$s ແລ້ວ" + "%1$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ" + "ແຕະເພື່ອເບິ່ງຕົວເລືອກ" + "ເຄືອຂ່າຍມືຖືບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" + "ເຄືອຂ່າຍບໍ່ສາມາດເຂົ້າເຖິງອິນເຕີເນັດໄດ້" + "ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້" + "%1$s ມີການເຊື່ອມຕໍ່ທີ່ຈຳກັດ" + "ແຕະເພື່ອຢືນຢັນການເຊື່ອມຕໍ່" + "ສະຫຼັບໄປໃຊ້ %1$s ແລ້ວ" + "ອຸປະກອນຈະໃຊ້ %1$s ເມື່ອ %2$s ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ. ອາດມີການຮຽກເກັບຄ່າບໍລິການ." + "ສະຫຼັບຈາກ %1$s ໄປໃຊ້ %2$s ແລ້ວ" - "ອິນເຕີເນັດມືຖື" - "Wi-Fi" - "Bluetooth" - "ອີເທີເນັດ" - "VPN" + "ອິນເຕີເນັດມືຖື" + "Wi-Fi" + "Bluetooth" + "ອີເທີເນັດ" + "VPN" - "ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ" + "ບໍ່ຮູ້ຈັກປະເພດເຄືອຂ່າຍ" diff --git a/service/ServiceConnectivityResources/res/values-lt/strings.xml b/service/ServiceConnectivityResources/res/values-lt/strings.xml index 8eb41f1efa..f73f142766 100644 --- a/service/ServiceConnectivityResources/res/values-lt/strings.xml +++ b/service/ServiceConnectivityResources/res/values-lt/strings.xml @@ -17,27 +17,27 @@ - "System Connectivity Resources" - "Prisijungti prie „Wi-Fi“ tinklo" - "Prisijungti prie tinklo" - + "System Connectivity Resources" + "Prisijungti prie „Wi-Fi“ tinklo" + "Prisijungti prie tinklo" + - "„%1$s“ negali pasiekti interneto" - "Palieskite, kad būtų rodomos parinktys." - "Mobiliojo ryšio tinkle nėra prieigos prie interneto" - "Tinkle nėra prieigos prie interneto" - "Privataus DNS serverio negalima pasiekti" - "„%1$s“ ryšys apribotas" - "Palieskite, jei vis tiek norite prisijungti" - "Perjungta į tinklą %1$s" - "Įrenginyje naudojamas kitas tinklas (%1$s), kai dabartiniame tinkle (%2$s) nėra interneto ryšio. Gali būti taikomi mokesčiai." - "Perjungta iš tinklo %1$s į tinklą %2$s" + "„%1$s“ negali pasiekti interneto" + "Palieskite, kad būtų rodomos parinktys." + "Mobiliojo ryšio tinkle nėra prieigos prie interneto" + "Tinkle nėra prieigos prie interneto" + "Privataus DNS serverio negalima pasiekti" + "„%1$s“ ryšys apribotas" + "Palieskite, jei vis tiek norite prisijungti" + "Perjungta į tinklą %1$s" + "Įrenginyje naudojamas kitas tinklas (%1$s), kai dabartiniame tinkle (%2$s) nėra interneto ryšio. Gali būti taikomi mokesčiai." + "Perjungta iš tinklo %1$s į tinklą %2$s" - "mobiliojo ryšio duomenys" - "Wi-Fi" - "Bluetooth" - "Eternetas" - "VPN" + "mobiliojo ryšio duomenys" + "Wi-Fi" + "Bluetooth" + "Eternetas" + "VPN" - "nežinomas tinklo tipas" + "nežinomas tinklo tipas" diff --git a/service/ServiceConnectivityResources/res/values-lv/strings.xml b/service/ServiceConnectivityResources/res/values-lv/strings.xml index 0647a4fb07..ce063a54b0 100644 --- a/service/ServiceConnectivityResources/res/values-lv/strings.xml +++ b/service/ServiceConnectivityResources/res/values-lv/strings.xml @@ -17,27 +17,27 @@ - "Sistēmas savienojamības resursi" - "Pierakstieties Wi-Fi tīklā" - "Pierakstīšanās tīklā" - + "Sistēmas savienojamības resursi" + "Pierakstieties Wi-Fi tīklā" + "Pierakstīšanās tīklā" + - "Tīklā %1$s nav piekļuves internetam" - "Pieskarieties, lai skatītu iespējas." - "Mobilajā tīklā nav piekļuves internetam." - "Tīklā nav piekļuves internetam." - "Nevar piekļūt privātam DNS serverim." - "Tīklā %1$s ir ierobežota savienojamība" - "Lai tik un tā izveidotu savienojumu, pieskarieties" - "Pārslēdzās uz tīklu %1$s" - "Kad vienā tīklā (%2$s) nav piekļuves internetam, ierīcē tiek izmantots cits tīkls (%1$s). Var tikt piemērota maksa." - "Pārslēdzās no tīkla %1$s uz tīklu %2$s" + "Tīklā %1$s nav piekļuves internetam" + "Pieskarieties, lai skatītu opcijas." + "Mobilajā tīklā nav piekļuves internetam." + "Tīklā nav piekļuves internetam." + "Nevar piekļūt privātam DNS serverim." + "Tīklā %1$s ir ierobežota savienojamība" + "Lai tik un tā izveidotu savienojumu, pieskarieties" + "Pārslēdzās uz tīklu %1$s" + "Kad vienā tīklā (%2$s) nav piekļuves internetam, ierīcē tiek izmantots cits tīkls (%1$s). Var tikt piemērota maksa." + "Pārslēdzās no tīkla %1$s uz tīklu %2$s" - "mobilie dati" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobilie dati" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "nezināms tīkla veids" + "nezināms tīkla veids" diff --git a/service/ServiceConnectivityResources/res/values-mk/strings.xml b/service/ServiceConnectivityResources/res/values-mk/strings.xml index b0024e296c..fb105e0f79 100644 --- a/service/ServiceConnectivityResources/res/values-mk/strings.xml +++ b/service/ServiceConnectivityResources/res/values-mk/strings.xml @@ -17,27 +17,27 @@ - "System Connectivity Resources" - "Најавете се на мрежа на Wi-Fi" - "Најавете се на мрежа" - + "System Connectivity Resources" + "Најавете се на мрежа на Wi-Fi" + "Најавете се на мрежа" + - "%1$s нема интернет-пристап" - "Допрете за опции" - "Мобилната мрежа нема интернет-пристап" - "Мрежата нема интернет-пристап" - "Не може да се пристапи до приватниот DNS-сервер" - "%1$s има ограничена поврзливост" - "Допрете за да се поврзете и покрај тоа" - "Префрлено на %1$s" - "Уредот користи %1$s кога %2$s нема пристап до интернет. Може да се наплатат трошоци." - "Префрлено од %1$s на %2$s" + "%1$s нема интернет-пристап" + "Допрете за опции" + "Мобилната мрежа нема интернет-пристап" + "Мрежата нема интернет-пристап" + "Не може да се пристапи до приватниот DNS-сервер" + "%1$s има ограничена поврзливост" + "Допрете за да се поврзете и покрај тоа" + "Префрлено на %1$s" + "Уредот користи %1$s кога %2$s нема пристап до интернет. Може да се наплатат трошоци." + "Префрлено од %1$s на %2$s" - "мобилен интернет" - "Wi-Fi" - "Bluetooth" - "Етернет" - "VPN" + "мобилен интернет" + "Wi-Fi" + "Bluetooth" + "Етернет" + "VPN" - "непознат тип мрежа" + "непознат тип мрежа" diff --git a/service/ServiceConnectivityResources/res/values-ml/strings.xml b/service/ServiceConnectivityResources/res/values-ml/strings.xml index 8ce7667fbf..9a512389c1 100644 --- a/service/ServiceConnectivityResources/res/values-ml/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ml/strings.xml @@ -17,27 +17,27 @@ - "സിസ്‌റ്റം കണക്‌റ്റിവിറ്റി ഉറവിടങ്ങൾ" - "വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" - "നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" - + "സിസ്‌റ്റം കണക്‌റ്റിവിറ്റി ഉറവിടങ്ങൾ" + "വൈഫൈ നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" + "നെറ്റ്‌വർക്കിലേക്ക് സൈൻ ഇൻ ചെയ്യുക" + - "%1$s എന്നതിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" - "ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക" - "മൊബെെൽ നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" - "നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" - "സ്വകാര്യ DNS സെർവർ ആക്‌സസ് ചെയ്യാനാവില്ല" - "%1$s എന്നതിന് പരിമിതമായ കണക്റ്റിവിറ്റി ഉണ്ട്" - "ഏതുവിധേനയും കണക്‌റ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക" - "%1$s എന്നതിലേക്ക് മാറി" - "%2$s-ന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം %1$s ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം." - "%1$s നെറ്റ്‌വർക്കിൽ നിന്ന് %2$s നെറ്റ്‌വർക്കിലേക്ക് മാറി" + "%1$s എന്നതിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക" + "മൊബെെൽ നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "നെറ്റ്‌വർക്കിന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ല" + "സ്വകാര്യ DNS സെർവർ ആക്‌സസ് ചെയ്യാനാവില്ല" + "%1$s എന്നതിന് പരിമിതമായ കണക്റ്റിവിറ്റി ഉണ്ട്" + "ഏതുവിധേനയും കണക്‌റ്റ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക" + "%1$s എന്നതിലേക്ക് മാറി" + "%2$s-ന് ഇന്റർനെറ്റ് ആക്‌സസ് ഇല്ലാത്തപ്പോൾ ഉപകരണം %1$s ഉപയോഗിക്കുന്നു. നിരക്കുകൾ ബാധകമായേക്കാം." + "%1$s നെറ്റ്‌വർക്കിൽ നിന്ന് %2$s നെറ്റ്‌വർക്കിലേക്ക് മാറി" - "മൊബൈൽ ഡാറ്റ" - "വൈഫൈ" - "Bluetooth" - "ഇതർനെറ്റ്" - "VPN" + "മൊബൈൽ ഡാറ്റ" + "വൈഫൈ" + "Bluetooth" + "ഇതർനെറ്റ്" + "VPN" - "അജ്ഞാതമായ നെറ്റ്‌വർക്ക് തരം" + "അജ്ഞാതമായ നെറ്റ്‌വർക്ക് തരം" diff --git a/service/ServiceConnectivityResources/res/values-mn/strings.xml b/service/ServiceConnectivityResources/res/values-mn/strings.xml index be8b59202b..83725330a8 100644 --- a/service/ServiceConnectivityResources/res/values-mn/strings.xml +++ b/service/ServiceConnectivityResources/res/values-mn/strings.xml @@ -17,27 +17,27 @@ - "Системийн холболтын нөөцүүд" - "Wi-Fi сүлжээнд нэвтэрнэ үү" - "Сүлжээнд нэвтэрнэ үү" - + "Системийн холболтын нөөцүүд" + "Wi-Fi сүлжээнд нэвтэрнэ үү" + "Сүлжээнд нэвтэрнэ үү" + - "%1$s-д интернэтийн хандалт алга" - "Сонголт хийхийн тулд товшино уу" - "Мобайл сүлжээнд интернэт хандалт байхгүй байна" - "Сүлжээнд интернэт хандалт байхгүй байна" - "Хувийн DNS серверт хандах боломжгүй байна" - "%1$s зарим үйлчилгээнд хандах боломжгүй байна" - "Ямар ч тохиолдолд холбогдохын тулд товших" - "%1$s руу шилжүүлсэн" - "%2$s интернет холболтгүй үед төхөөрөмж %1$s-г ашигладаг. Төлбөр гарч болзошгүй." - "%1$s-с %2$s руу шилжүүлсэн" + "%1$s-д интернэтийн хандалт алга" + "Сонголт хийхийн тулд товшино уу" + "Мобайл сүлжээнд интернэт хандалт байхгүй байна" + "Сүлжээнд интернэт хандалт байхгүй байна" + "Хувийн DNS серверт хандах боломжгүй байна" + "%1$s зарим үйлчилгээнд хандах боломжгүй байна" + "Ямар ч тохиолдолд холбогдохын тулд товших" + "%1$s руу шилжүүлсэн" + "%2$s интернет холболтгүй үед төхөөрөмж %1$s-г ашигладаг. Төлбөр гарч болзошгүй." + "%1$s-с %2$s руу шилжүүлсэн" - "мобайл дата" - "Wi-Fi" - "Bluetooth" - "Этернэт" - "VPN" + "мобайл дата" + "Wi-Fi" + "Bluetooth" + "Этернэт" + "VPN" - "үл мэдэгдэх сүлжээний төрөл" + "үл мэдэгдэх сүлжээний төрөл" diff --git a/service/ServiceConnectivityResources/res/values-mr/strings.xml b/service/ServiceConnectivityResources/res/values-mr/strings.xml index fe7df841b1..658b19b8e9 100644 --- a/service/ServiceConnectivityResources/res/values-mr/strings.xml +++ b/service/ServiceConnectivityResources/res/values-mr/strings.xml @@ -17,27 +17,27 @@ - "सिस्टम कनेक्टिव्हिटी चे स्रोत" - "वाय-फाय नेटवर्कमध्‍ये साइन इन करा" - "नेटवर्कवर साइन इन करा" - + "सिस्टम कनेक्टिव्हिटी चे स्रोत" + "वाय-फाय नेटवर्कमध्‍ये साइन इन करा" + "नेटवर्कवर साइन इन करा" + - "%1$s ला इंटरनेट अ‍ॅक्सेस नाही" - "पर्यायांसाठी टॅप करा" - "मोबाइल नेटवर्कला इंटरनेट ॲक्सेस नाही" - "नेटवर्कला इंटरनेट ॲक्सेस नाही" - "खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही" - "%1$s ला मर्यादित कनेक्टिव्हिटी आहे" - "तरीही कनेक्ट करण्यासाठी टॅप करा" - "%1$s वर स्विच केले" - "%2$s कडे इंटरनेटचा अ‍ॅक्सेस नसताना डिव्हाइस %1$s वापरते. शुल्क लागू शकते." - "%1$s वरून %2$s वर स्विच केले" + "%1$s ला इंटरनेट अ‍ॅक्सेस नाही" + "पर्यायांसाठी टॅप करा" + "मोबाइल नेटवर्कला इंटरनेट ॲक्सेस नाही" + "नेटवर्कला इंटरनेट ॲक्सेस नाही" + "खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही" + "%1$s ला मर्यादित कनेक्टिव्हिटी आहे" + "तरीही कनेक्ट करण्यासाठी टॅप करा" + "%1$s वर स्विच केले" + "%2$s कडे इंटरनेटचा अ‍ॅक्सेस नसताना डिव्हाइस %1$s वापरते. शुल्क लागू शकते." + "%1$s वरून %2$s वर स्विच केले" - "मोबाइल डेटा" - "वाय-फाय" - "ब्लूटूथ" - "इथरनेट" - "VPN" + "मोबाइल डेटा" + "वाय-फाय" + "ब्लूटूथ" + "इथरनेट" + "VPN" - "अज्ञात नेटवर्क प्रकार" + "अज्ञात नेटवर्क प्रकार" diff --git a/service/ServiceConnectivityResources/res/values-ms/strings.xml b/service/ServiceConnectivityResources/res/values-ms/strings.xml index 54b49a20f7..84b242c674 100644 --- a/service/ServiceConnectivityResources/res/values-ms/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ms/strings.xml @@ -17,27 +17,27 @@ - "Sumber Kesambungan Sistem" - "Log masuk ke rangkaian Wi-Fi" - "Log masuk ke rangkaian" - + "Sumber Kesambungan Sistem" + "Log masuk ke rangkaian Wi-Fi" + "Log masuk ke rangkaian" + - "%1$s tiada akses Internet" - "Ketik untuk mendapatkan pilihan" - "Rangkaian mudah alih tiada akses Internet" - "Rangkaian tiada akses Internet" - "Pelayan DNS peribadi tidak boleh diakses" - "%1$s mempunyai kesambungan terhad" - "Ketik untuk menyambung juga" - "Beralih kepada %1$s" - "Peranti menggunakan %1$s apabila %2$s tiada akses Internet. Bayaran mungkin dikenakan." - "Beralih daripada %1$s kepada %2$s" + "%1$s tiada akses Internet" + "Ketik untuk mendapatkan pilihan" + "Rangkaian mudah alih tiada akses Internet" + "Rangkaian tiada akses Internet" + "Pelayan DNS peribadi tidak boleh diakses" + "%1$s mempunyai kesambungan terhad" + "Ketik untuk menyambung juga" + "Beralih kepada %1$s" + "Peranti menggunakan %1$s apabila %2$s tiada akses Internet. Bayaran mungkin dikenakan." + "Beralih daripada %1$s kepada %2$s" - "data mudah alih" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "data mudah alih" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "jenis rangkaian tidak diketahui" + "jenis rangkaian tidak diketahui" diff --git a/service/ServiceConnectivityResources/res/values-my/strings.xml b/service/ServiceConnectivityResources/res/values-my/strings.xml index 15b75f0fc3..683226365c 100644 --- a/service/ServiceConnectivityResources/res/values-my/strings.xml +++ b/service/ServiceConnectivityResources/res/values-my/strings.xml @@ -17,27 +17,27 @@ - "စနစ်ချိတ်ဆက်နိုင်မှု ရင်းမြစ်များ" - "ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ" - "ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်" - + "စနစ်ချိတ်ဆက်နိုင်မှု ရင်းမြစ်များ" + "ဝိုင်ဖိုင်ကွန်ရက်သို့ လက်မှတ်ထိုးဝင်ပါ" + "ကွန်ယက်သို့ လက်မှတ်ထိုးဝင်ရန်" + - "%1$s တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" - "အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ" - "မိုဘိုင်းကွန်ရက်တွင် အင်တာနက်ချိတ်ဆက်မှု မရှိပါ" - "ကွန်ရက်တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" - "သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။" - "%1$s တွင် ချိတ်ဆက်မှုကို ကန့်သတ်ထားသည်" - "မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန် တို့ပါ" - "%1$s သို့ ပြောင်းလိုက်ပြီ" - "%2$s ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် စက်ပစ္စည်းသည် %1$s ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။" - "%1$s မှ %2$s သို့ ပြောင်းလိုက်ပြီ" + "%1$s တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" + "အခြားရွေးချယ်စရာများကိုကြည့်ရန် တို့ပါ" + "မိုဘိုင်းကွန်ရက်တွင် အင်တာနက်ချိတ်ဆက်မှု မရှိပါ" + "ကွန်ရက်တွင် အင်တာနက်အသုံးပြုခွင့် မရှိပါ" + "သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။" + "%1$s တွင် ချိတ်ဆက်မှုကို ကန့်သတ်ထားသည်" + "မည်သို့ပင်ဖြစ်စေ ချိတ်ဆက်ရန် တို့ပါ" + "%1$s သို့ ပြောင်းလိုက်ပြီ" + "%2$s ဖြင့် အင်တာနက် အသုံးမပြုနိုင်သည့်အချိန်တွင် စက်ပစ္စည်းသည် %1$s ကို သုံးပါသည်။ ဒေတာသုံးစွဲခ ကျသင့်နိုင်ပါသည်။" + "%1$s မှ %2$s သို့ ပြောင်းလိုက်ပြီ" - "မိုဘိုင်းဒေတာ" - "Wi-Fi" - "ဘလူးတုသ်" - "အီသာနက်" - "VPN" + "မိုဘိုင်းဒေတာ" + "Wi-Fi" + "ဘလူးတုသ်" + "အီသာနက်" + "VPN" - "အမည်မသိကွန်ရက်အမျိုးအစား" + "အမည်မသိကွန်ရက်အမျိုးအစား" diff --git a/service/ServiceConnectivityResources/res/values-nb/strings.xml b/service/ServiceConnectivityResources/res/values-nb/strings.xml index a561def65c..00a0728d2f 100644 --- a/service/ServiceConnectivityResources/res/values-nb/strings.xml +++ b/service/ServiceConnectivityResources/res/values-nb/strings.xml @@ -17,27 +17,27 @@ - "Ressurser for systemtilkobling" - "Logg på Wi-Fi-nettverket" - "Logg på nettverk" - + "Ressurser for systemtilkobling" + "Logg på Wi-Fi-nettverket" + "Logg på nettverk" + - "%1$s har ingen internettilkobling" - "Trykk for å få alternativer" - "Mobilnettverket har ingen internettilgang" - "Nettverket har ingen internettilgang" - "Den private DNS-tjeneren kan ikke nås" - "%1$s har begrenset tilkobling" - "Trykk for å koble til likevel" - "Byttet til %1$s" - "Enheten bruker %1$s når %2$s ikke har Internett-tilgang. Avgifter kan påløpe." - "Byttet fra %1$s til %2$s" + "%1$s har ingen internettilkobling" + "Trykk for å få alternativer" + "Mobilnettverket har ingen internettilgang" + "Nettverket har ingen internettilgang" + "Den private DNS-tjeneren kan ikke nås" + "%1$s har begrenset tilkobling" + "Trykk for å koble til likevel" + "Byttet til %1$s" + "Enheten bruker %1$s når %2$s ikke har Internett-tilgang. Avgifter kan påløpe." + "Byttet fra %1$s til %2$s" - "mobildata" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobildata" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "en ukjent nettverkstype" + "en ukjent nettverkstype" diff --git a/service/ServiceConnectivityResources/res/values-ne/strings.xml b/service/ServiceConnectivityResources/res/values-ne/strings.xml index f74542d942..2eaf16276e 100644 --- a/service/ServiceConnectivityResources/res/values-ne/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ne/strings.xml @@ -17,27 +17,27 @@ - "सिस्टम कनेक्टिभिटीका स्रोतहरू" - "Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्" - "सञ्जालमा साइन इन गर्नुहोस्" - + "सिस्टम कनेक्टिभिटीका स्रोतहरू" + "Wi-Fi नेटवर्कमा साइन इन गर्नुहोस्" + "सञ्जालमा साइन इन गर्नुहोस्" + - "%1$s को इन्टरनेटमाथि पहुँच छैन" - "विकल्पहरूका लागि ट्याप गर्नुहोस्" - "मोबाइल नेटवर्कको इन्टरनेटमाथि पहुँच छैन" - "नेटवर्कको इन्टरनेटमाथि पहुँच छैन" - "निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन" - "%1$s को जडान सीमित छ" - "जसरी भए पनि जडान गर्न ट्याप गर्नुहोस्" - "%1$s मा बदल्नुहोस्" - "%2$s मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले %1$s प्रयोग गर्दछ। शुल्क लाग्न सक्छ।" - "%1$s बाट %2$s मा परिवर्तन गरियो" + "%1$s को इन्टरनेटमाथि पहुँच छैन" + "विकल्पहरूका लागि ट्याप गर्नुहोस्" + "मोबाइल नेटवर्कको इन्टरनेटमाथि पहुँच छैन" + "नेटवर्कको इन्टरनेटमाथि पहुँच छैन" + "निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन" + "%1$s को जडान सीमित छ" + "जसरी भए पनि जडान गर्न ट्याप गर्नुहोस्" + "%1$s मा बदल्नुहोस्" + "%2$s मार्फत इन्टरनेटमाथि पहुँच राख्न नसकेको अवस्थामा यन्त्रले %1$s प्रयोग गर्दछ। शुल्क लाग्न सक्छ।" + "%1$s बाट %2$s मा परिवर्तन गरियो" - "मोबाइल डेटा" - "Wi-Fi" - "ब्लुटुथ" - "इथरनेट" - "VPN" + "मोबाइल डेटा" + "Wi-Fi" + "ब्लुटुथ" + "इथरनेट" + "VPN" - "नेटवर्कको कुनै अज्ञात प्रकार" + "नेटवर्कको कुनै अज्ञात प्रकार" diff --git a/service/ServiceConnectivityResources/res/values-nl/strings.xml b/service/ServiceConnectivityResources/res/values-nl/strings.xml index 0f3203beb5..394c552ae3 100644 --- a/service/ServiceConnectivityResources/res/values-nl/strings.xml +++ b/service/ServiceConnectivityResources/res/values-nl/strings.xml @@ -17,27 +17,27 @@ - "Resources voor systeemconnectiviteit" - "Inloggen bij wifi-netwerk" - "Inloggen bij netwerk" - + "Resources voor systeemconnectiviteit" + "Inloggen bij wifi-netwerk" + "Inloggen bij netwerk" + - "%1$s heeft geen internettoegang" - "Tik voor opties" - "Mobiel netwerk heeft geen internettoegang" - "Netwerk heeft geen internettoegang" - "Geen toegang tot privé-DNS-server" - "%1$s heeft beperkte connectiviteit" - "Tik om toch verbinding te maken" - "Overgeschakeld naar %1$s" - "Apparaat gebruikt %1$s wanneer %2$s geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht." - "Overgeschakeld van %1$s naar %2$s" + "%1$s heeft geen internettoegang" + "Tik voor opties" + "Mobiel netwerk heeft geen internettoegang" + "Netwerk heeft geen internettoegang" + "Geen toegang tot privé-DNS-server" + "%1$s heeft beperkte connectiviteit" + "Tik om toch verbinding te maken" + "Overgeschakeld naar %1$s" + "Apparaat gebruikt %1$s wanneer %2$s geen internetverbinding heeft. Er kunnen kosten in rekening worden gebracht." + "Overgeschakeld van %1$s naar %2$s" - "mobiele data" - "Wifi" - "Bluetooth" - "Ethernet" - "VPN" + "mobiele data" + "Wifi" + "Bluetooth" + "Ethernet" + "VPN" - "een onbekend netwerktype" + "een onbekend netwerktype" diff --git a/service/ServiceConnectivityResources/res/values-or/strings.xml b/service/ServiceConnectivityResources/res/values-or/strings.xml index ecf4d694d0..8b85884fe9 100644 --- a/service/ServiceConnectivityResources/res/values-or/strings.xml +++ b/service/ServiceConnectivityResources/res/values-or/strings.xml @@ -17,27 +17,27 @@ - "ସିଷ୍ଟମର ସଂଯୋଗ ସମ୍ବନ୍ଧିତ ରିସୋର୍ସଗୁଡ଼ିକ" - "ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍‍-ଇନ୍‍ କରନ୍ତୁ" - "ନେଟ୍‌ୱର୍କରେ ସାଇନ୍‍ ଇନ୍‍ କରନ୍ତୁ" - + "ସିଷ୍ଟମର ସଂଯୋଗ ସମ୍ବନ୍ଧିତ ରିସୋର୍ସଗୁଡ଼ିକ" + "ୱାଇ-ଫାଇ ନେଟୱର୍କରେ ସାଇନ୍‍-ଇନ୍‍ କରନ୍ତୁ" + "ନେଟ୍‌ୱର୍କରେ ସାଇନ୍‍ ଇନ୍‍ କରନ୍ତୁ" + - "%1$sର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" - "ବିକଳ୍ପ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ" - "ମୋବାଇଲ୍ ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" - "ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" - "ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ" - "%1$sର ସୀମିତ ସଂଯୋଗ ଅଛି" - "ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ" - "%1$sକୁ ବଦଳାଗଲା" - "%2$sର ଇଣ୍ଟରନେଟ୍‍ ଆକ୍ସେସ୍ ନଥିବାବେଳେ ଡିଭାଇସ୍‍ %1$s ବ୍ୟବହାର କରିଥାଏ। ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ।" - "%1$s ରୁ %2$sକୁ ବଦଳାଗଲା" + "%1$sର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ବିକଳ୍ପ ପାଇଁ ଟାପ୍‍ କରନ୍ତୁ" + "ମୋବାଇଲ୍ ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ନେଟ୍‌ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ" + "ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ" + "%1$sର ସୀମିତ ସଂଯୋଗ ଅଛି" + "ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ" + "%1$sକୁ ବଦଳାଗଲା" + "%2$sର ଇଣ୍ଟରନେଟ୍‍ ଆକ୍ସେସ୍ ନଥିବାବେଳେ ଡିଭାଇସ୍‍ %1$s ବ୍ୟବହାର କରିଥାଏ। ଶୁଳ୍କ ଲାଗୁ ହୋଇପାରେ।" + "%1$s ରୁ %2$sକୁ ବଦଳାଗଲା" - "ମୋବାଇଲ ଡାଟା" - "ୱାଇ-ଫାଇ" - "ବ୍ଲୁଟୁଥ୍" - "ଇଥରନେଟ୍" - "VPN" + "ମୋବାଇଲ ଡାଟା" + "ୱାଇ-ଫାଇ" + "ବ୍ଲୁଟୁଥ୍" + "ଇଥରନେଟ୍" + "VPN" - "ଏକ ଅଜଣା ନେଟୱାର୍କ ପ୍ରକାର" + "ଏକ ଅଜଣା ନେଟୱାର୍କ ପ୍ରକାର" diff --git a/service/ServiceConnectivityResources/res/values-pa/strings.xml b/service/ServiceConnectivityResources/res/values-pa/strings.xml index 43280549e7..9f71cac55a 100644 --- a/service/ServiceConnectivityResources/res/values-pa/strings.xml +++ b/service/ServiceConnectivityResources/res/values-pa/strings.xml @@ -17,27 +17,27 @@ - "ਸਿਸਟਮ ਕਨੈਕਟੀਵਿਟੀ ਸਰੋਤ" - "ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" - "ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" - + "ਸਿਸਟਮ ਕਨੈਕਟੀਵਿਟੀ ਸਰੋਤ" + "ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" + "ਨੈੱਟਵਰਕ \'ਤੇ ਸਾਈਨ-ਇਨ ਕਰੋ" + - "%1$s ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" - "ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ" - "ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" - "ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" - "ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ" - "%1$s ਕੋਲ ਸੀਮਤ ਕਨੈਕਟੀਵਿਟੀ ਹੈ" - "ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" - "ਬਦਲਕੇ %1$s ਲਿਆਂਦਾ ਗਿਆ" - "%2$s ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ %1$s ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।" - "%1$s ਤੋਂ ਬਦਲਕੇ %2$s \'ਤੇ ਕੀਤਾ ਗਿਆ" + "%1$s ਕੋਲ ਇੰਟਰਨੈੱਟ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਵਿਕਲਪਾਂ ਲਈ ਟੈਪ ਕਰੋ" + "ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਨੈੱਟਵਰਕ ਕੋਲ ਇੰਟਰਨੈੱਟ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਹੈ" + "ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ" + "%1$s ਕੋਲ ਸੀਮਤ ਕਨੈਕਟੀਵਿਟੀ ਹੈ" + "ਫਿਰ ਵੀ ਕਨੈਕਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" + "ਬਦਲਕੇ %1$s ਲਿਆਂਦਾ ਗਿਆ" + "%2$s ਦੀ ਇੰਟਰਨੈੱਟ \'ਤੇ ਪਹੁੰਚ ਨਾ ਹੋਣ \'ਤੇ ਡੀਵਾਈਸ %1$s ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਖਰਚੇ ਲਾਗੂ ਹੋ ਸਕਦੇ ਹਨ।" + "%1$s ਤੋਂ ਬਦਲਕੇ %2$s \'ਤੇ ਕੀਤਾ ਗਿਆ" - "ਮੋਬਾਈਲ ਡਾਟਾ" - "ਵਾਈ-ਫਾਈ" - "ਬਲੂਟੁੱਥ" - "ਈਥਰਨੈੱਟ" - "VPN" + "ਮੋਬਾਈਲ ਡਾਟਾ" + "ਵਾਈ-ਫਾਈ" + "ਬਲੂਟੁੱਥ" + "ਈਥਰਨੈੱਟ" + "VPN" - "ਕੋਈ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ" + "ਕੋਈ ਅਗਿਆਤ ਨੈੱਟਵਰਕ ਦੀ ਕਿਸਮ" diff --git a/service/ServiceConnectivityResources/res/values-pl/strings.xml b/service/ServiceConnectivityResources/res/values-pl/strings.xml index e6b3a0cff6..cc84e29a44 100644 --- a/service/ServiceConnectivityResources/res/values-pl/strings.xml +++ b/service/ServiceConnectivityResources/res/values-pl/strings.xml @@ -17,27 +17,27 @@ - "Zasoby systemowe dotyczące łączności" - "Zaloguj się w sieci Wi-Fi" - "Zaloguj się do sieci" - + "Zasoby systemowe dotyczące łączności" + "Zaloguj się w sieci Wi-Fi" + "Zaloguj się do sieci" + - "%1$s nie ma dostępu do internetu" - "Kliknij, by wyświetlić opcje" - "Sieć komórkowa nie ma dostępu do internetu" - "Sieć nie ma dostępu do internetu" - "Brak dostępu do prywatnego serwera DNS" - "%1$s ma ograniczoną łączność" - "Kliknij, by mimo to nawiązać połączenie" - "Zmieniono na połączenie typu %1$s" - "Urządzenie korzysta z połączenia typu %1$s, gdy %2$s nie dostępu do internetu. Mogą zostać naliczone opłaty." - "Przełączono z połączenia typu %1$s na %2$s." + "%1$s nie ma dostępu do internetu" + "Kliknij, by wyświetlić opcje" + "Sieć komórkowa nie ma dostępu do internetu" + "Sieć nie ma dostępu do internetu" + "Brak dostępu do prywatnego serwera DNS" + "%1$s ma ograniczoną łączność" + "Kliknij, by mimo to nawiązać połączenie" + "Zmieniono na połączenie typu %1$s" + "Urządzenie korzysta z połączenia typu %1$s, gdy %2$s nie dostępu do internetu. Mogą zostać naliczone opłaty." + "Przełączono z połączenia typu %1$s na %2$s." - "mobilna transmisja danych" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobilna transmisja danych" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "nieznany typ sieci" + "nieznany typ sieci" diff --git a/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml b/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml index f1d0bc0b0c..3c15a7682d 100644 --- a/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml +++ b/service/ServiceConnectivityResources/res/values-pt-rBR/strings.xml @@ -17,27 +17,27 @@ - "Recursos de conectividade do sistema" - "Fazer login na rede Wi-Fi" - "Fazer login na rede" - + "Recursos de conectividade do sistema" + "Fazer login na rede Wi-Fi" + "Fazer login na rede" + - "%1$s não tem acesso à Internet" - "Toque para ver opções" - "A rede móvel não tem acesso à Internet" - "A rede não tem acesso à Internet" - "Não é possível acessar o servidor DNS privado" - "%1$s tem conectividade limitada" - "Toque para conectar mesmo assim" - "Alternado para %1$s" - "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." - "Alternado de %1$s para %2$s" + "%1$s não tem acesso à Internet" + "Toque para ver opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível acessar o servidor DNS privado" + "%1$s tem conectividade limitada" + "Toque para conectar mesmo assim" + "Alternado para %1$s" + "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." + "Alternado de %1$s para %2$s" - "dados móveis" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "um tipo de rede desconhecido" + "um tipo de rede desconhecido" diff --git a/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml b/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml index 163d70b081..48dde754b7 100644 --- a/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml +++ b/service/ServiceConnectivityResources/res/values-pt-rPT/strings.xml @@ -17,27 +17,27 @@ - "Recursos de conetividade do sistema" - "Iniciar sessão na rede Wi-Fi" - "Início de sessão na rede" - + "Recursos de conetividade do sistema" + "Iniciar sessão na rede Wi-Fi" + "Início de sessão na rede" + - "%1$s não tem acesso à Internet" - "Toque para obter mais opções" - "A rede móvel não tem acesso à Internet" - "A rede não tem acesso à Internet" - "Não é possível aceder ao servidor DNS." - "%1$s tem conetividade limitada." - "Toque para ligar mesmo assim." - "Mudou para %1$s" - "O dispositivo utiliza %1$s quando %2$s não tem acesso à Internet. Podem aplicar-se custos." - "Mudou de %1$s para %2$s" + "%1$s não tem acesso à Internet" + "Toque para obter mais opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível aceder ao servidor DNS." + "%1$s tem conetividade limitada." + "Toque para ligar mesmo assim." + "Mudou para %1$s" + "O dispositivo utiliza %1$s quando %2$s não tem acesso à Internet. Podem aplicar-se custos." + "Mudou de %1$s para %2$s" - "dados móveis" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "um tipo de rede desconhecido" + "um tipo de rede desconhecido" diff --git a/service/ServiceConnectivityResources/res/values-pt/strings.xml b/service/ServiceConnectivityResources/res/values-pt/strings.xml index f1d0bc0b0c..3c15a7682d 100644 --- a/service/ServiceConnectivityResources/res/values-pt/strings.xml +++ b/service/ServiceConnectivityResources/res/values-pt/strings.xml @@ -17,27 +17,27 @@ - "Recursos de conectividade do sistema" - "Fazer login na rede Wi-Fi" - "Fazer login na rede" - + "Recursos de conectividade do sistema" + "Fazer login na rede Wi-Fi" + "Fazer login na rede" + - "%1$s não tem acesso à Internet" - "Toque para ver opções" - "A rede móvel não tem acesso à Internet" - "A rede não tem acesso à Internet" - "Não é possível acessar o servidor DNS privado" - "%1$s tem conectividade limitada" - "Toque para conectar mesmo assim" - "Alternado para %1$s" - "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." - "Alternado de %1$s para %2$s" + "%1$s não tem acesso à Internet" + "Toque para ver opções" + "A rede móvel não tem acesso à Internet" + "A rede não tem acesso à Internet" + "Não é possível acessar o servidor DNS privado" + "%1$s tem conectividade limitada" + "Toque para conectar mesmo assim" + "Alternado para %1$s" + "O dispositivo usa %1$s quando %2$s não tem acesso à Internet. Esse serviço pode ser cobrado." + "Alternado de %1$s para %2$s" - "dados móveis" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "dados móveis" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "um tipo de rede desconhecido" + "um tipo de rede desconhecido" diff --git a/service/ServiceConnectivityResources/res/values-ro/strings.xml b/service/ServiceConnectivityResources/res/values-ro/strings.xml index 221261c66c..fa5848fe56 100644 --- a/service/ServiceConnectivityResources/res/values-ro/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ro/strings.xml @@ -17,27 +17,27 @@ - "Resurse pentru conectivitatea sistemului" - "Conectați-vă la rețeaua Wi-Fi" - "Conectați-vă la rețea" - + "Resurse pentru conectivitatea sistemului" + "Conectați-vă la rețeaua Wi-Fi" + "Conectați-vă la rețea" + - "%1$s nu are acces la internet" - "Atingeți pentru opțiuni" - "Rețeaua mobilă nu are acces la internet" - "Rețeaua nu are acces la internet" - "Serverul DNS privat nu poate fi accesat" - "%1$s are conectivitate limitată" - "Atingeți pentru a vă conecta oricum" - "S-a comutat la %1$s" - "Dispozitivul folosește %1$s când %2$s nu are acces la internet. Se pot aplica taxe." - "S-a comutat de la %1$s la %2$s" + "%1$s nu are acces la internet" + "Atingeți pentru opțiuni" + "Rețeaua mobilă nu are acces la internet" + "Rețeaua nu are acces la internet" + "Serverul DNS privat nu poate fi accesat" + "%1$s are conectivitate limitată" + "Atingeți pentru a vă conecta oricum" + "S-a comutat la %1$s" + "Dispozitivul folosește %1$s când %2$s nu are acces la internet. Se pot aplica taxe." + "S-a comutat de la %1$s la %2$s" - "date mobile" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "date mobile" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "un tip de rețea necunoscut" + "un tip de rețea necunoscut" diff --git a/service/ServiceConnectivityResources/res/values-ru/strings.xml b/service/ServiceConnectivityResources/res/values-ru/strings.xml index ba179b7394..2e074ed5d4 100644 --- a/service/ServiceConnectivityResources/res/values-ru/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ru/strings.xml @@ -17,27 +17,27 @@ - "System Connectivity Resources" - "Подключение к Wi-Fi" - "Регистрация в сети" - + "System Connectivity Resources" + "Подключение к Wi-Fi" + "Регистрация в сети" + - "Сеть \"%1$s\" не подключена к Интернету" - "Нажмите, чтобы показать варианты." - "Мобильная сеть не подключена к Интернету" - "Сеть не подключена к Интернету" - "Доступа к частному DNS-серверу нет." - "Подключение к сети \"%1$s\" ограничено" - "Нажмите, чтобы подключиться" - "Новое подключение: %1$s" - "Устройство использует %1$s, если подключение к сети %2$s недоступно. Может взиматься плата за передачу данных." - "Устройство отключено от сети %2$s и теперь использует %1$s" + "Сеть \"%1$s\" не подключена к Интернету" + "Нажмите, чтобы показать варианты." + "Мобильная сеть не подключена к Интернету" + "Сеть не подключена к Интернету" + "Доступа к частному DNS-серверу нет." + "Подключение к сети \"%1$s\" ограничено" + "Нажмите, чтобы подключиться" + "Новое подключение: %1$s" + "Устройство использует %1$s, если подключение к сети %2$s недоступно. Может взиматься плата за передачу данных." + "Устройство отключено от сети %2$s и теперь использует %1$s" - "мобильный интернет" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "мобильный интернет" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "неизвестный тип сети" + "неизвестный тип сети" diff --git a/service/ServiceConnectivityResources/res/values-si/strings.xml b/service/ServiceConnectivityResources/res/values-si/strings.xml index 1c493a78dc..a4f720a205 100644 --- a/service/ServiceConnectivityResources/res/values-si/strings.xml +++ b/service/ServiceConnectivityResources/res/values-si/strings.xml @@ -17,27 +17,27 @@ - "පද්ධති සබැඳුම් හැකියා සම්පත්" - "Wi-Fi ජාලයට පුරනය වන්න" - "ජාලයට පුරනය වන්න" - + "පද්ධති සබැඳුම් හැකියා සම්පත්" + "Wi-Fi ජාලයට පුරනය වන්න" + "ජාලයට පුරනය වන්න" + - "%1$s හට අන්තර්ජාල ප්‍රවේශය නැත" - "විකල්ප සඳහා තට්ටු කරන්න" - "ජංගම ජාලවලට අන්තර්ජාල ප්‍රවේශය නැත" - "ජාලයට අන්තර්ජාල ප්‍රවේශය නැත" - "පුද්ගලික DNS සේවාදායකයට ප්‍රවේශ වීමට නොහැකිය" - "%1$s හට සීමිත සබැඳුම් හැකියාවක් ඇත" - "කෙසේ වෙතත් ඉදිරියට යාමට තට්ටු කරන්න" - "%1$s වෙත මාරු විය" - "උපාංගය %1$s %2$s සඳහා අන්තර්ජාල ප්‍රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය." - "%1$s සිට %2$s වෙත මාරු විය" + "%1$s හට අන්තර්ජාල ප්‍රවේශය නැත" + "විකල්ප සඳහා තට්ටු කරන්න" + "ජංගම ජාලවලට අන්තර්ජාල ප්‍රවේශය නැත" + "ජාලයට අන්තර්ජාල ප්‍රවේශය නැත" + "පුද්ගලික DNS සේවාදායකයට ප්‍රවේශ වීමට නොහැකිය" + "%1$s හට සීමිත සබැඳුම් හැකියාවක් ඇත" + "කෙසේ වෙතත් ඉදිරියට යාමට තට්ටු කරන්න" + "%1$s වෙත මාරු විය" + "උපාංගය %1$s %2$s සඳහා අන්තර්ජාල ප්‍රවේශය නැති විට භාවිත කරයි. ගාස්තු අදාළ විය හැකිය." + "%1$s සිට %2$s වෙත මාරු විය" - "ජංගම දත්ත" - "Wi-Fi" - "බ්ලූටූත්" - "ඊතර්නෙට්" - "VPN" + "ජංගම දත්ත" + "Wi-Fi" + "බ්ලූටූත්" + "ඊතර්නෙට්" + "VPN" - "නොදන්නා ජාල වර්ගයකි" + "නොදන්නා ජාල වර්ගයකි" diff --git a/service/ServiceConnectivityResources/res/values-sk/strings.xml b/service/ServiceConnectivityResources/res/values-sk/strings.xml index 1b9313af17..432b67040b 100644 --- a/service/ServiceConnectivityResources/res/values-sk/strings.xml +++ b/service/ServiceConnectivityResources/res/values-sk/strings.xml @@ -17,27 +17,27 @@ - "Zdroje možností pripojenia systému" - "Prihlásiť sa do siete Wi‑Fi" - "Prihlásenie do siete" - + "Zdroje možností pripojenia systému" + "Prihlásiť sa do siete Wi‑Fi" + "Prihlásenie do siete" + - "%1$s nemá prístup k internetu" - "Klepnutím získate možnosti" - "Mobilná sieť nemá prístup k internetu" - "Sieť nemá prístup k internetu" - "K súkromnému serveru DNS sa nepodarilo získať prístup" - "%1$s má obmedzené pripojenie" - "Ak sa chcete aj napriek tomu pripojiť, klepnite" - "Prepnuté na sieť: %1$s" - "Keď %2$s nemá prístup k internetu, zariadenie používa %1$s. Môžu sa účtovať poplatky." - "Prepnuté zo siete %1$s na sieť %2$s" + "%1$s nemá prístup k internetu" + "Klepnutím získate možnosti" + "Mobilná sieť nemá prístup k internetu" + "Sieť nemá prístup k internetu" + "K súkromnému serveru DNS sa nepodarilo získať prístup" + "%1$s má obmedzené pripojenie" + "Ak sa chcete aj napriek tomu pripojiť, klepnite" + "Prepnuté na sieť: %1$s" + "Keď %2$s nemá prístup k internetu, zariadenie používa %1$s. Môžu sa účtovať poplatky." + "Prepnuté zo siete %1$s na sieť %2$s" - "mobilné dáta" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobilné dáta" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "neznámy typ siete" + "neznámy typ siete" diff --git a/service/ServiceConnectivityResources/res/values-sl/strings.xml b/service/ServiceConnectivityResources/res/values-sl/strings.xml index 739fb8e491..b727614095 100644 --- a/service/ServiceConnectivityResources/res/values-sl/strings.xml +++ b/service/ServiceConnectivityResources/res/values-sl/strings.xml @@ -17,27 +17,27 @@ - "Viri povezljivosti sistema" - "Prijavite se v omrežje Wi-Fi" - "Prijava v omrežje" - + "Viri povezljivosti sistema" + "Prijavite se v omrežje Wi-Fi" + "Prijava v omrežje" + - "Omrežje %1$s nima dostopa do interneta" - "Dotaknite se za možnosti" - "Mobilno omrežje nima dostopa do interneta" - "Omrežje nima dostopa do interneta" - "Do zasebnega strežnika DNS ni mogoče dostopati" - "Povezljivost omrežja %1$s je omejena" - "Dotaknite se, da kljub temu vzpostavite povezavo" - "Preklopljeno na omrežje vrste %1$s" - "Naprava uporabi omrežje vrste %1$s, ko omrežje vrste %2$s nima dostopa do interneta. Prenos podatkov se lahko zaračuna." - "Preklopljeno z omrežja vrste %1$s na omrežje vrste %2$s" + "Omrežje %1$s nima dostopa do interneta" + "Dotaknite se za možnosti" + "Mobilno omrežje nima dostopa do interneta" + "Omrežje nima dostopa do interneta" + "Do zasebnega strežnika DNS ni mogoče dostopati" + "Povezljivost omrežja %1$s je omejena" + "Dotaknite se, da kljub temu vzpostavite povezavo" + "Preklopljeno na omrežje vrste %1$s" + "Naprava uporabi omrežje vrste %1$s, ko omrežje vrste %2$s nima dostopa do interneta. Prenos podatkov se lahko zaračuna." + "Preklopljeno z omrežja vrste %1$s na omrežje vrste %2$s" - "prenos podatkov v mobilnem omrežju" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "prenos podatkov v mobilnem omrežju" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "neznana vrsta omrežja" + "neznana vrsta omrežja" diff --git a/service/ServiceConnectivityResources/res/values-sq/strings.xml b/service/ServiceConnectivityResources/res/values-sq/strings.xml index cf8cf3b40e..385c75c65e 100644 --- a/service/ServiceConnectivityResources/res/values-sq/strings.xml +++ b/service/ServiceConnectivityResources/res/values-sq/strings.xml @@ -17,27 +17,27 @@ - "Burimet e lidhshmërisë së sistemit" - "Identifikohu në rrjetin Wi-Fi" - "Identifikohu në rrjet" - + "Burimet e lidhshmërisë së sistemit" + "Identifikohu në rrjetin Wi-Fi" + "Identifikohu në rrjet" + - "%1$s nuk ka qasje në internet" - "Trokit për opsionet" - "Rrjeti celular nuk ka qasje në internet" - "Rrjeti nuk ka qasje në internet" - "Serveri privat DNS nuk mund të qaset" - "%1$s ka lidhshmëri të kufizuar" - "Trokit për t\'u lidhur gjithsesi" - "Kaloi te %1$s" - "Pajisja përdor %1$s kur %2$s nuk ka qasje në internet. Mund të zbatohen tarifa." - "Kaloi nga %1$s te %2$s" + "%1$s nuk ka qasje në internet" + "Trokit për opsionet" + "Rrjeti celular nuk ka qasje në internet" + "Rrjeti nuk ka qasje në internet" + "Serveri privat DNS nuk mund të qaset" + "%1$s ka lidhshmëri të kufizuar" + "Trokit për t\'u lidhur gjithsesi" + "Kaloi te %1$s" + "Pajisja përdor %1$s kur %2$s nuk ka qasje në internet. Mund të zbatohen tarifa." + "Kaloi nga %1$s te %2$s" - "të dhënat celulare" - "Wi-Fi" - "Bluetooth" - "Eternet" - "VPN" + "të dhënat celulare" + "Wi-Fi" + "Bluetooth" + "Eternet" + "VPN" - "një lloj rrjeti i panjohur" + "një lloj rrjeti i panjohur" diff --git a/service/ServiceConnectivityResources/res/values-sr/strings.xml b/service/ServiceConnectivityResources/res/values-sr/strings.xml index 1f7c95c94d..928dc798d3 100644 --- a/service/ServiceConnectivityResources/res/values-sr/strings.xml +++ b/service/ServiceConnectivityResources/res/values-sr/strings.xml @@ -17,27 +17,27 @@ - "Ресурси за повезивање са системом" - "Пријављивање на WiFi мрежу" - "Пријавите се на мрежу" - + "Ресурси за повезивање са системом" + "Пријављивање на WiFi мрежу" + "Пријавите се на мрежу" + - "%1$s нема приступ интернету" - "Додирните за опције" - "Мобилна мрежа нема приступ интернету" - "Мрежа нема приступ интернету" - "Приступ приватном DNS серверу није успео" - "%1$s има ограничену везу" - "Додирните да бисте се ипак повезали" - "Прешли сте на тип мреже %1$s" - "Уређај користи тип мреже %1$s када тип мреже %2$s нема приступ интернету. Можда ће се наплаћивати трошкови." - "Прешли сте са типа мреже %1$s на тип мреже %2$s" + "%1$s нема приступ интернету" + "Додирните за опције" + "Мобилна мрежа нема приступ интернету" + "Мрежа нема приступ интернету" + "Приступ приватном DNS серверу није успео" + "%1$s има ограничену везу" + "Додирните да бисте се ипак повезали" + "Прешли сте на тип мреже %1$s" + "Уређај користи тип мреже %1$s када тип мреже %2$s нема приступ интернету. Можда ће се наплаћивати трошкови." + "Прешли сте са типа мреже %1$s на тип мреже %2$s" - "мобилни подаци" - "WiFi" - "Bluetooth" - "Етернет" - "VPN" + "мобилни подаци" + "WiFi" + "Bluetooth" + "Етернет" + "VPN" - "непознат тип мреже" + "непознат тип мреже" diff --git a/service/ServiceConnectivityResources/res/values-sv/strings.xml b/service/ServiceConnectivityResources/res/values-sv/strings.xml index 57e74e95e9..d71412429a 100644 --- a/service/ServiceConnectivityResources/res/values-sv/strings.xml +++ b/service/ServiceConnectivityResources/res/values-sv/strings.xml @@ -17,27 +17,27 @@ - "Resurser för systemanslutning" - "Logga in på ett wifi-nätverk" - "Logga in på nätverket" - + "Resurser för systemanslutning" + "Logga in på ett wifi-nätverk" + "Logga in på nätverket" + - "%1$s har ingen internetanslutning" - "Tryck för alternativ" - "Mobilnätverket har ingen internetanslutning" - "Nätverket har ingen internetanslutning" - "Det går inte att komma åt den privata DNS-servern." - "%1$s har begränsad anslutning" - "Tryck för att ansluta ändå" - "Byte av nätverk till %1$s" - "%1$s används på enheten när det inte finns internetåtkomst via %2$s. Avgifter kan tillkomma." - "Byte av nätverk från %1$s till %2$s" + "%1$s har ingen internetanslutning" + "Tryck för alternativ" + "Mobilnätverket har ingen internetanslutning" + "Nätverket har ingen internetanslutning" + "Det går inte att komma åt den privata DNS-servern." + "%1$s har begränsad anslutning" + "Tryck för att ansluta ändå" + "Byte av nätverk till %1$s" + "%1$s används på enheten när det inte finns internetåtkomst via %2$s. Avgifter kan tillkomma." + "Byte av nätverk från %1$s till %2$s" - "mobildata" - "Wifi" - "Bluetooth" - "Ethernet" - "VPN" + "mobildata" + "Wifi" + "Bluetooth" + "Ethernet" + "VPN" - "en okänd nätverkstyp" + "en okänd nätverkstyp" diff --git a/service/ServiceConnectivityResources/res/values-sw/strings.xml b/service/ServiceConnectivityResources/res/values-sw/strings.xml index 5c4d59410d..15d6cab3d6 100644 --- a/service/ServiceConnectivityResources/res/values-sw/strings.xml +++ b/service/ServiceConnectivityResources/res/values-sw/strings.xml @@ -17,27 +17,27 @@ - "Nyenzo za Muunganisho wa Mfumo" - "Ingia kwa mtandao wa Wi-Fi" - "Ingia katika mtandao" - + "Nyenzo za Muunganisho wa Mfumo" + "Ingia kwa mtandao wa Wi-Fi" + "Ingia katika mtandao" + - "%1$s haina uwezo wa kufikia intaneti" - "Gusa ili upate chaguo" - "Mtandao wa simu hauna uwezo wa kufikia intaneti" - "Mtandao hauna uwezo wa kufikia intaneti" - "Seva ya faragha ya DNS haiwezi kufikiwa" - "%1$s ina muunganisho unaofikia huduma chache." - "Gusa ili uunganishe tu" - "Sasa inatumia %1$s" - "Kifaa hutumia %1$s wakati %2$s haina intaneti. Huenda ukalipishwa." - "Imebadilisha mtandao kutoka %1$s na sasa inatumia %2$s" + "%1$s haina uwezo wa kufikia intaneti" + "Gusa ili upate chaguo" + "Mtandao wa simu hauna uwezo wa kufikia intaneti" + "Mtandao hauna uwezo wa kufikia intaneti" + "Seva ya faragha ya DNS haiwezi kufikiwa" + "%1$s ina muunganisho unaofikia huduma chache." + "Gusa ili uunganishe tu" + "Sasa inatumia %1$s" + "Kifaa hutumia %1$s wakati %2$s haina intaneti. Huenda ukalipishwa." + "Imebadilisha mtandao kutoka %1$s na sasa inatumia %2$s" - "data ya mtandao wa simu" - "Wi-Fi" - "Bluetooth" - "Ethaneti" - "VPN" + "data ya mtandao wa simu" + "Wi-Fi" + "Bluetooth" + "Ethaneti" + "VPN" - "aina ya mtandao isiyojulikana" + "aina ya mtandao isiyojulikana" diff --git a/service/ServiceConnectivityResources/res/values-ta/strings.xml b/service/ServiceConnectivityResources/res/values-ta/strings.xml index 90f89c988e..9850a35869 100644 --- a/service/ServiceConnectivityResources/res/values-ta/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ta/strings.xml @@ -17,27 +17,27 @@ - "சிஸ்டம் இணைப்பு மூலங்கள்" - "வைஃபை நெட்வொர்க்கில் உள்நுழையவும்" - "நெட்வொர்க்கில் உள்நுழையவும்" - + "சிஸ்டம் இணைப்பு தகவல்கள்" + "வைஃபை நெட்வொர்க்கில் உள்நுழையவும்" + "நெட்வொர்க்கில் உள்நுழையவும்" + - "%1$s நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" - "விருப்பங்களுக்கு, தட்டவும்" - "மொபைல் நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" - "நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" - "தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது" - "%1$s வரம்பிற்கு உட்பட்ட இணைப்புநிலையைக் கொண்டுள்ளது" - "எப்படியேனும் இணைப்பதற்குத் தட்டவும்" - "%1$sக்கு மாற்றப்பட்டது" - "%2$s நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது %1$s நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்." - "%1$s இலிருந்து %2$sக்கு மாற்றப்பட்டது" + "%1$s நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "விருப்பங்களுக்கு, தட்டவும்" + "மொபைல் நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "நெட்வொர்க்கிற்கு இணைய அணுகல் இல்லை" + "தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது" + "%1$s வரம்பிற்கு உட்பட்ட இணைப்புநிலையைக் கொண்டுள்ளது" + "எப்படியேனும் இணைப்பதற்குத் தட்டவும்" + "%1$sக்கு மாற்றப்பட்டது" + "%2$s நெட்வொர்க்கில் இண்டர்நெட் அணுகல் இல்லாததால், சாதனமானது %1$s நெட்வொர்க்கைப் பயன்படுத்துகிறது. கட்டணங்கள் விதிக்கப்படலாம்." + "%1$s இலிருந்து %2$sக்கு மாற்றப்பட்டது" - "மொபைல் டேட்டா" - "வைஃபை" - "புளூடூத்" - "ஈதர்நெட்" - "VPN" + "மொபைல் டேட்டா" + "வைஃபை" + "புளூடூத்" + "ஈதர்நெட்" + "VPN" - "தெரியாத நெட்வொர்க் வகை" + "தெரியாத நெட்வொர்க் வகை" diff --git a/service/ServiceConnectivityResources/res/values-te/strings.xml b/service/ServiceConnectivityResources/res/values-te/strings.xml index c69b599e19..f7182a8de6 100644 --- a/service/ServiceConnectivityResources/res/values-te/strings.xml +++ b/service/ServiceConnectivityResources/res/values-te/strings.xml @@ -17,27 +17,27 @@ - "సిస్టమ్ కనెక్టివిటీ రిసోర్స్‌లు" - "Wi-Fi నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" - "నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" - + "సిస్టమ్ కనెక్టివిటీ రిసోర్స్‌లు" + "Wi-Fi నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" + "నెట్‌వర్క్‌కి సైన్ ఇన్ చేయండి" + - "%1$sకి ఇంటర్నెట్ యాక్సెస్ లేదు" - "ఎంపికల కోసం నొక్కండి" - "మొబైల్ నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" - "నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" - "ప్రైవేట్ DNS సర్వర్‌ను యాక్సెస్ చేయడం సాధ్యపడదు" - "%1$s పరిమిత కనెక్టివిటీని కలిగి ఉంది" - "ఏదేమైనా కనెక్ట్ చేయడానికి నొక్కండి" - "%1$sకి మార్చబడింది" - "పరికరం %2$sకి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు %1$sని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు." - "%1$s నుండి %2$sకి మార్చబడింది" + "%1$sకి ఇంటర్నెట్ యాక్సెస్ లేదు" + "ఎంపికల కోసం నొక్కండి" + "మొబైల్ నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" + "నెట్‌వర్క్‌కు ఇంటర్నెట్ యాక్సెస్ లేదు" + "ప్రైవేట్ DNS సర్వర్‌ను యాక్సెస్ చేయడం సాధ్యపడదు" + "%1$s పరిమిత కనెక్టివిటీని కలిగి ఉంది" + "ఏదేమైనా కనెక్ట్ చేయడానికి నొక్కండి" + "%1$sకి మార్చబడింది" + "పరికరం %2$sకి ఇంటర్నెట్ యాక్సెస్ లేనప్పుడు %1$sని ఉపయోగిస్తుంది. ఛార్జీలు వర్తించవచ్చు." + "%1$s నుండి %2$sకి మార్చబడింది" - "మొబైల్ డేటా" - "Wi-Fi" - "బ్లూటూత్" - "ఈథర్‌నెట్" - "VPN" + "మొబైల్ డేటా" + "Wi-Fi" + "బ్లూటూత్" + "ఈథర్‌నెట్" + "VPN" - "తెలియని నెట్‌వర్క్ రకం" + "తెలియని నెట్‌వర్క్ రకం" diff --git a/service/ServiceConnectivityResources/res/values-th/strings.xml b/service/ServiceConnectivityResources/res/values-th/strings.xml index eee5a3520d..7049309d6f 100644 --- a/service/ServiceConnectivityResources/res/values-th/strings.xml +++ b/service/ServiceConnectivityResources/res/values-th/strings.xml @@ -17,27 +17,27 @@ - "ทรัพยากรการเชื่อมต่อของระบบ" - "ลงชื่อเข้าใช้เครือข่าย WiFi" - "ลงชื่อเข้าใช้เครือข่าย" - + "ทรัพยากรการเชื่อมต่อของระบบ" + "ลงชื่อเข้าใช้เครือข่าย WiFi" + "ลงชื่อเข้าใช้เครือข่าย" + - "%1$s เข้าถึงอินเทอร์เน็ตไม่ได้" - "แตะเพื่อดูตัวเลือก" - "เครือข่ายมือถือไม่มีการเข้าถึงอินเทอร์เน็ต" - "เครือข่ายไม่มีการเข้าถึงอินเทอร์เน็ต" - "เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้" - "%1$s มีการเชื่อมต่อจำกัด" - "แตะเพื่อเชื่อมต่อ" - "เปลี่ยนเป็น %1$s" - "อุปกรณ์จะใช้ %1$s เมื่อ %2$s เข้าถึงอินเทอร์เน็ตไม่ได้ โดยอาจมีค่าบริการ" - "เปลี่ยนจาก %1$s เป็น %2$s" + "%1$s เข้าถึงอินเทอร์เน็ตไม่ได้" + "แตะเพื่อดูตัวเลือก" + "เครือข่ายมือถือไม่มีการเข้าถึงอินเทอร์เน็ต" + "เครือข่ายไม่มีการเข้าถึงอินเทอร์เน็ต" + "เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้" + "%1$s มีการเชื่อมต่อจำกัด" + "แตะเพื่อเชื่อมต่อ" + "เปลี่ยนเป็น %1$s" + "อุปกรณ์จะใช้ %1$s เมื่อ %2$s เข้าถึงอินเทอร์เน็ตไม่ได้ โดยอาจมีค่าบริการ" + "เปลี่ยนจาก %1$s เป็น %2$s" - "อินเทอร์เน็ตมือถือ" - "Wi-Fi" - "บลูทูธ" - "อีเทอร์เน็ต" - "VPN" + "อินเทอร์เน็ตมือถือ" + "Wi-Fi" + "บลูทูธ" + "อีเทอร์เน็ต" + "VPN" - "ประเภทเครือข่ายที่ไม่รู้จัก" + "ประเภทเครือข่ายที่ไม่รู้จัก" diff --git a/service/ServiceConnectivityResources/res/values-tl/strings.xml b/service/ServiceConnectivityResources/res/values-tl/strings.xml index 8d665fe5f9..c866fd413b 100644 --- a/service/ServiceConnectivityResources/res/values-tl/strings.xml +++ b/service/ServiceConnectivityResources/res/values-tl/strings.xml @@ -17,27 +17,27 @@ - "Mga Resource ng Pagkakonekta ng System" - "Mag-sign in sa Wi-Fi network" - "Mag-sign in sa network" - + "Mga Resource ng Pagkakonekta ng System" + "Mag-sign in sa Wi-Fi network" + "Mag-sign in sa network" + - "Walang access sa internet ang %1$s" - "I-tap para sa mga opsyon" - "Walang access sa internet ang mobile network" - "Walang access sa internet ang network" - "Hindi ma-access ang pribadong DNS server" - "Limitado ang koneksyon ng %1$s" - "I-tap para kumonekta pa rin" - "Lumipat sa %1$s" - "Ginagamit ng device ang %1$s kapag walang access sa internet ang %2$s. Maaaring may mga malapat na singilin." - "Lumipat sa %2$s mula sa %1$s" + "Walang access sa internet ang %1$s" + "I-tap para sa mga opsyon" + "Walang access sa internet ang mobile network" + "Walang access sa internet ang network" + "Hindi ma-access ang pribadong DNS server" + "Limitado ang koneksyon ng %1$s" + "I-tap para kumonekta pa rin" + "Lumipat sa %1$s" + "Ginagamit ng device ang %1$s kapag walang access sa internet ang %2$s. Maaaring may mga malapat na singilin." + "Lumipat sa %2$s mula sa %1$s" - "mobile data" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobile data" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "isang hindi kilalang uri ng network" + "isang hindi kilalang uri ng network" diff --git a/service/ServiceConnectivityResources/res/values-tr/strings.xml b/service/ServiceConnectivityResources/res/values-tr/strings.xml index cfb76323ed..c4930a851a 100644 --- a/service/ServiceConnectivityResources/res/values-tr/strings.xml +++ b/service/ServiceConnectivityResources/res/values-tr/strings.xml @@ -17,27 +17,27 @@ - "Sistem Bağlantı Kaynakları" - "Kablosuz ağda oturum açın" - "Ağda oturum açın" - + "Sistem Bağlantı Kaynakları" + "Kablosuz ağda oturum açın" + "Ağda oturum açın" + - "%1$s ağının internet bağlantısı yok" - "Seçenekler için dokunun" - "Mobil ağın internet bağlantısı yok" - "Ağın internet bağlantısı yok" - "Gizli DNS sunucusuna erişilemiyor" - "%1$s sınırlı bağlantıya sahip" - "Yine de bağlanmak için dokunun" - "%1$s ağına geçildi" - "%2$s ağının internet erişimi olmadığında cihaz %1$s ağını kullanır. Bunun için ödeme alınabilir." - "%1$s ağından %2$s ağına geçildi" + "%1$s ağının internet bağlantısı yok" + "Seçenekler için dokunun" + "Mobil ağın internet bağlantısı yok" + "Ağın internet bağlantısı yok" + "Gizli DNS sunucusuna erişilemiyor" + "%1$s sınırlı bağlantıya sahip" + "Yine de bağlanmak için dokunun" + "%1$s ağına geçildi" + "%2$s ağının internet erişimi olmadığında cihaz %1$s ağını kullanır. Bunun için ödeme alınabilir." + "%1$s ağından %2$s ağına geçildi" - "mobil veri" - "Kablosuz" - "Bluetooth" - "Ethernet" - "VPN" + "mobil veri" + "Kablosuz" + "Bluetooth" + "Ethernet" + "VPN" - "bilinmeyen ağ türü" + "bilinmeyen ağ türü" diff --git a/service/ServiceConnectivityResources/res/values-uk/strings.xml b/service/ServiceConnectivityResources/res/values-uk/strings.xml index c5da7460b3..88112638bd 100644 --- a/service/ServiceConnectivityResources/res/values-uk/strings.xml +++ b/service/ServiceConnectivityResources/res/values-uk/strings.xml @@ -17,27 +17,27 @@ - "Ресурси для підключення системи" - "Вхід у мережу Wi-Fi" - "Вхід у мережу" - + "Ресурси для підключення системи" + "Вхід у мережу Wi-Fi" + "Вхід у мережу" + - "Мережа %1$s не має доступу до Інтернету" - "Торкніться, щоб відкрити опції" - "Мобільна мережа не має доступу до Інтернету" - "Мережа не має доступу до Інтернету" - "Немає доступу до приватного DNS-сервера" - "Підключення до мережі %1$s обмежено" - "Натисніть, щоб усе одно підключитися" - "Пристрій перейшов на мережу %1$s" - "Коли мережа %2$s не має доступу до Інтернету, використовується %1$s. Може стягуватися плата." - "Пристрій перейшов з мережі %1$s на мережу %2$s" + "Мережа %1$s не має доступу до Інтернету" + "Торкніться, щоб відкрити опції" + "Мобільна мережа не має доступу до Інтернету" + "Мережа не має доступу до Інтернету" + "Немає доступу до приватного DNS-сервера" + "Підключення до мережі %1$s обмежено" + "Натисніть, щоб усе одно підключитися" + "Пристрій перейшов на мережу %1$s" + "Коли мережа %2$s не має доступу до Інтернету, використовується %1$s. Може стягуватися плата." + "Пристрій перейшов з мережі %1$s на мережу %2$s" - "мобільний Інтернет" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "мобільний Інтернет" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "невідомий тип мережі" + "невідомий тип мережі" diff --git a/service/ServiceConnectivityResources/res/values-ur/strings.xml b/service/ServiceConnectivityResources/res/values-ur/strings.xml index bd2a228ab4..8f9656c725 100644 --- a/service/ServiceConnectivityResources/res/values-ur/strings.xml +++ b/service/ServiceConnectivityResources/res/values-ur/strings.xml @@ -17,27 +17,27 @@ - "سسٹم کنیکٹوٹی کے وسائل" - "‏Wi-Fi نیٹ ورک میں سائن ان کریں" - "نیٹ ورک میں سائن ان کریں" - + "سسٹم کنیکٹوٹی کے وسائل" + "‏Wi-Fi نیٹ ورک میں سائن ان کریں" + "نیٹ ورک میں سائن ان کریں" + - "%1$s کو انٹرنیٹ تک رسائی حاصل نہیں ہے" - "اختیارات کیلئے تھپتھپائیں" - "موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" - "نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" - "‏نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی" - "%1$s کی کنیکٹوٹی محدود ہے" - "بہر حال منسلک کرنے کے لیے تھپتھپائیں" - "%1$s پر سوئچ ہو گیا" - "جب %2$s کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ %1$s کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔" - "%1$s سے %2$s پر سوئچ ہو گیا" + "%1$s کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "اختیارات کیلئے تھپتھپائیں" + "موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے" + "‏نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی" + "%1$s کی کنیکٹوٹی محدود ہے" + "بہر حال منسلک کرنے کے لیے تھپتھپائیں" + "%1$s پر سوئچ ہو گیا" + "جب %2$s کو انٹرنیٹ تک رسائی نہیں ہوتی ہے تو آلہ %1$s کا استعمال کرتا ہے۔ چارجز لاگو ہو سکتے ہیں۔" + "%1$s سے %2$s پر سوئچ ہو گیا" - "موبائل ڈیٹا" - "Wi-Fi" - "بلوٹوتھ" - "ایتھرنیٹ" - "VPN" + "موبائل ڈیٹا" + "Wi-Fi" + "بلوٹوتھ" + "ایتھرنیٹ" + "VPN" - "نامعلوم نیٹ ورک کی قسم" + "نامعلوم نیٹ ورک کی قسم" diff --git a/service/ServiceConnectivityResources/res/values-uz/strings.xml b/service/ServiceConnectivityResources/res/values-uz/strings.xml index 567aa886b4..d7285ad7d8 100644 --- a/service/ServiceConnectivityResources/res/values-uz/strings.xml +++ b/service/ServiceConnectivityResources/res/values-uz/strings.xml @@ -17,27 +17,27 @@ - "Tizim aloqa resurslari" - "Wi-Fi tarmoqqa kirish" - "Tarmoqqa kirish" - + "Tizim aloqa resurslari" + "Wi-Fi tarmoqqa kirish" + "Tarmoqqa kirish" + - "%1$s nomli tarmoqda internetga ruxsati yoʻq" - "Variantlarni ko‘rsatish uchun bosing" - "Mobil tarmoq internetga ulanmagan" - "Tarmoq internetga ulanmagan" - "Xususiy DNS server ishlamayapti" - "%1$s nomli tarmoqda aloqa cheklangan" - "Baribir ulash uchun bosing" - "Yangi ulanish: %1$s" - "Agar %2$s tarmoqda internet uzilsa, qurilma %1$sga ulanadi. Sarflangan trafik uchun haq olinishi mumkin." - "%1$s tarmog‘idan %2$s tarmog‘iga o‘tildi" + "%1$s nomli tarmoqda internetga ruxsati yoʻq" + "Variantlarni ko‘rsatish uchun bosing" + "Mobil tarmoq internetga ulanmagan" + "Tarmoq internetga ulanmagan" + "Xususiy DNS server ishlamayapti" + "%1$s nomli tarmoqda aloqa cheklangan" + "Baribir ulash uchun bosing" + "Yangi ulanish: %1$s" + "Agar %2$s tarmoqda internet uzilsa, qurilma %1$sga ulanadi. Sarflangan trafik uchun haq olinishi mumkin." + "%1$s tarmog‘idan %2$s tarmog‘iga o‘tildi" - "mobil internet" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "mobil internet" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "nomaʼlum tarmoq turi" + "nomaʼlum tarmoq turi" diff --git a/service/ServiceConnectivityResources/res/values-vi/strings.xml b/service/ServiceConnectivityResources/res/values-vi/strings.xml index 590b388c96..239fb81b8d 100644 --- a/service/ServiceConnectivityResources/res/values-vi/strings.xml +++ b/service/ServiceConnectivityResources/res/values-vi/strings.xml @@ -17,27 +17,27 @@ - "Tài nguyên kết nối hệ thống" - "Đăng nhập vào mạng Wi-Fi" - "Đăng nhập vào mạng" - + "Tài nguyên kết nối hệ thống" + "Đăng nhập vào mạng Wi-Fi" + "Đăng nhập vào mạng" + - "%1$s không có quyền truy cập Internet" - "Nhấn để biết tùy chọn" - "Mạng di động không có quyền truy cập Internet" - "Mạng không có quyền truy cập Internet" - "Không thể truy cập máy chủ DNS riêng tư" - "%1$s có khả năng kết nối giới hạn" - "Nhấn để tiếp tục kết nối" - "Đã chuyển sang %1$s" - "Thiết bị sử dụng %1$s khi %2$s không có quyền truy cập Internet. Bạn có thể phải trả phí." - "Đã chuyển từ %1$s sang %2$s" + "%1$s không có quyền truy cập Internet" + "Nhấn để biết tùy chọn" + "Mạng di động không có quyền truy cập Internet" + "Mạng không có quyền truy cập Internet" + "Không thể truy cập máy chủ DNS riêng tư" + "%1$s có khả năng kết nối giới hạn" + "Nhấn để tiếp tục kết nối" + "Đã chuyển sang %1$s" + "Thiết bị sử dụng %1$s khi %2$s không có quyền truy cập Internet. Bạn có thể phải trả phí." + "Đã chuyển từ %1$s sang %2$s" - "dữ liệu di động" - "Wi-Fi" - "Bluetooth" - "Ethernet" - "VPN" + "dữ liệu di động" + "Wi-Fi" + "Bluetooth" + "Ethernet" + "VPN" - "loại mạng không xác định" + "loại mạng không xác định" diff --git a/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml index 9d6cff90e2..e318c0ba44 100644 --- a/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml +++ b/service/ServiceConnectivityResources/res/values-zh-rCN/strings.xml @@ -17,27 +17,27 @@ - "系统网络连接资源" - "登录到WLAN网络" - "登录到网络" - + "系统网络连接资源" + "登录到WLAN网络" + "登录到网络" + - "%1$s 无法访问互联网" - "点按即可查看相关选项" - "此移动网络无法访问互联网" - "此网络无法访问互联网" - "无法访问私人 DNS 服务器" - "%1$s 的连接受限" - "点按即可继续连接" - "已切换至%1$s" - "设备会在%2$s无法访问互联网时使用%1$s(可能需要支付相应的费用)。" - "已从%1$s切换至%2$s" + "%1$s 无法访问互联网" + "点按即可查看相关选项" + "此移动网络无法访问互联网" + "此网络无法访问互联网" + "无法访问私人 DNS 服务器" + "%1$s 的连接受限" + "点按即可继续连接" + "已切换至%1$s" + "设备会在%2$s无法访问互联网时使用%1$s(可能需要支付相应的费用)。" + "已从%1$s切换至%2$s" - "移动数据" - "WLAN" - "蓝牙" - "以太网" - "VPN" + "移动数据" + "WLAN" + "蓝牙" + "以太网" + "VPN" - "未知网络类型" + "未知网络类型" diff --git a/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml index c84241c896..af3dccd1f4 100644 --- a/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml +++ b/service/ServiceConnectivityResources/res/values-zh-rHK/strings.xml @@ -17,27 +17,27 @@ - "系統連線資源" - "登入 Wi-Fi 網絡" - "登入網絡" - + "系統連線資源" + "登入 Wi-Fi 網絡" + "登入網絡" + - "%1$s未有連接至互聯網" - "輕按即可查看選項" - "流動網絡並未連接互聯網" - "網絡並未連接互聯網" - "無法存取私人 DNS 伺服器" - "%1$s連線受限" - "仍要輕按以連結至此網絡" - "已切換至%1$s" - "裝置會在 %2$s 無法連線至互聯網時使用%1$s (可能需要支付相關費用)。" - "已從%1$s切換至%2$s" + "%1$s未有連接至互聯網" + "輕按即可查看選項" + "流動網絡並未連接互聯網" + "網絡並未連接互聯網" + "無法存取私人 DNS 伺服器" + "%1$s連線受限" + "仍要輕按以連結至此網絡" + "已切換至%1$s" + "裝置會在 %2$s 無法連線至互聯網時使用%1$s (可能需要支付相關費用)。" + "已從%1$s切換至%2$s" - "流動數據" - "Wi-Fi" - "藍牙" - "以太網絡" - "VPN" + "流動數據" + "Wi-Fi" + "藍牙" + "以太網絡" + "VPN" - "不明網絡類型" + "不明網絡類型" diff --git a/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml b/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml index 07540d18c0..644170760e 100644 --- a/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml +++ b/service/ServiceConnectivityResources/res/values-zh-rTW/strings.xml @@ -17,27 +17,27 @@ - "系統連線資源" - "登入 Wi-Fi 網路" - "登入網路" - + "系統連線資源" + "登入 Wi-Fi 網路" + "登入網路" + - "%1$s 沒有網際網路連線" - "輕觸即可查看選項" - "這個行動網路沒有網際網路連線" - "這個網路沒有網際網路連線" - "無法存取私人 DNS 伺服器" - "%1$s 的連線能力受限" - "輕觸即可繼續連線" - "已切換至%1$s" - "裝置會在無法連上「%2$s」時切換至「%1$s」(可能需要支付相關費用)。" - "已從 %1$s 切換至%2$s" + "%1$s 沒有網際網路連線" + "輕觸即可查看選項" + "這個行動網路沒有網際網路連線" + "這個網路沒有網際網路連線" + "無法存取私人 DNS 伺服器" + "%1$s 的連線能力受限" + "輕觸即可繼續連線" + "已切換至%1$s" + "裝置會在無法連上「%2$s」時切換至「%1$s」(可能需要支付相關費用)。" + "已從 %1$s 切換至%2$s" - "行動數據" - "Wi-Fi" - "藍牙" - "乙太網路" - "VPN" + "行動數據" + "Wi-Fi" + "藍牙" + "乙太網路" + "VPN" - "不明的網路類型" + "不明的網路類型" diff --git a/service/ServiceConnectivityResources/res/values-zu/strings.xml b/service/ServiceConnectivityResources/res/values-zu/strings.xml index 19f390ba61..b59f0d1b74 100644 --- a/service/ServiceConnectivityResources/res/values-zu/strings.xml +++ b/service/ServiceConnectivityResources/res/values-zu/strings.xml @@ -17,27 +17,27 @@ - "Izinsiza Zokuxhumeka Zesistimu" - "Ngena ngemvume kunethiwekhi ye-Wi-Fi" - "Ngena ngemvume kunethiwekhi" - + "Izinsiza Zokuxhumeka Zesistimu" + "Ngena ngemvume kunethiwekhi ye-Wi-Fi" + "Ngena ngemvume kunethiwekhi" + - "I-%1$s ayinakho ukufinyelela kwe-inthanethi" - "Thepha ukuze uthole izinketho" - "Inethiwekhi yeselula ayinakho ukufinyelela kwe-inthanethi" - "Inethiwekhi ayinakho ukufinyelela kwenethiwekhi" - "Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa" - "I-%1$s inokuxhumeka okukhawulelwe" - "Thepha ukuze uxhume noma kunjalo" - "Kushintshelwe ku-%1$s" - "Idivayisi isebenzisa i-%1$s uma i-%2$s inganakho ukufinyelela kwe-inthanethi. Kungasebenza izindleko." - "Kushintshelewe kusuka ku-%1$s kuya ku-%2$s" + "I-%1$s ayinakho ukufinyelela kwe-inthanethi" + "Thepha ukuze uthole izinketho" + "Inethiwekhi yeselula ayinakho ukufinyelela kwe-inthanethi" + "Inethiwekhi ayinakho ukufinyelela kwenethiwekhi" + "Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa" + "I-%1$s inokuxhumeka okukhawulelwe" + "Thepha ukuze uxhume noma kunjalo" + "Kushintshelwe ku-%1$s" + "Idivayisi isebenzisa i-%1$s uma i-%2$s inganakho ukufinyelela kwe-inthanethi. Kungasebenza izindleko." + "Kushintshelewe kusuka ku-%1$s kuya ku-%2$s" - "idatha yeselula" - "I-Wi-Fi" - "I-Bluetooth" - "I-Ethernet" - "I-VPN" + "idatha yeselula" + "I-Wi-Fi" + "I-Bluetooth" + "I-Ethernet" + "I-VPN" - "uhlobo olungaziwa lwenethiwekhi" + "uhlobo olungaziwa lwenethiwekhi" From 2f9d68861361a14c210e5b7c51dd8f3f36fe97fe Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 30 Mar 2022 18:51:41 +0900 Subject: [PATCH 881/881] Remove connectivity-tiramisu-updatable-sources The filegroup is now unnecessary as files are all in the service-t/src directory. This change allows building all sources including ethernet by referencing src/**. This is done by using a general filegroup service-connectivity-tiramisu-sources, so that branches that cannot build the T+ code can change its contents without introducing merge conflicts in the rest of the build rules. Also change visibility rules to allow building the moved ethernet code, and add a filegroup to allow building its tests. Bug: 222234190 Test: TH Ignore-AOSP-First: Move with history done per-branch Merged-In: I06e2568e5e01d855783383552d1b0d7732cefbe0 Change-Id: I8f23a45800b1086cc5a765fd24d734ca82c339a8 --- service-t/Android.bp | 30 ++++++++++++++++++--- service-t/Sources.bp | 56 --------------------------------------- tests/ethernet/Android.bp | 3 +-- 3 files changed, 28 insertions(+), 61 deletions(-) diff --git a/service-t/Android.bp b/service-t/Android.bp index 50dd995ef4..0beb4c822c 100644 --- a/service-t/Android.bp +++ b/service-t/Android.bp @@ -22,6 +22,17 @@ package { // Include build rules from Sources.bp build = ["Sources.bp"] +filegroup { + name: "service-connectivity-tiramisu-sources", + srcs: [ + "src/**/*.java", + ], + visibility: ["//visibility:private"], +} +// The above filegroup can be used to specify different sources depending +// on the branch, while minimizing merge conflicts in the rest of the +// build rules. + // This builds T+ services depending on framework-connectivity-t // hidden symbols separately from the S+ services, to ensure that S+ // services cannot accidentally depend on T+ hidden symbols from @@ -32,9 +43,7 @@ java_library { // TODO(b/210962470): Bump this to at least S, and then T. min_sdk_version: "30", srcs: [ - "src/**/*.java", - ":ethernet-service-updatable-sources", - ":services.connectivity-tiramisu-updatable-sources", + ":service-connectivity-tiramisu-sources", ], libs: [ "framework-annotations-lib", @@ -63,3 +72,18 @@ java_library { "//packages/modules/IPsec/tests/iketests", ], } + +// Ethernet related libraries. +// TODO: remove when ethernet tests are merged into connectivity tests +filegroup { + name: "ethernet-service-test-sources", + srcs: [ + "src/com/android/server/ethernet/**/*.java", + "src/com/android/server/net/DelayedDiskWrite.java", + "src/com/android/server/net/IpConfigStore.java", + ], + path: "src", + visibility: [ + "//packages/modules/Connectivity/tests:__subpackages__", + ], +} diff --git a/service-t/Sources.bp b/service-t/Sources.bp index 04866fb9cc..4e669b655a 100644 --- a/service-t/Sources.bp +++ b/service-t/Sources.bp @@ -59,48 +59,6 @@ filegroup { ], } -// Nsd related libraries. - -filegroup { - name: "services.connectivity-nsd-sources", - srcs: [ - "src/com/android/server/INativeDaemon*.java", - "src/com/android/server/NativeDaemon*.java", - "src/com/android/server/Nsd*.java", - ], - path: "src", - visibility: [ - "//visibility:private", - ], -} - -// IpSec related libraries. - -filegroup { - name: "services.connectivity-ipsec-sources", - srcs: [ - "src/com/android/server/IpSecService.java", - ], - path: "src", - visibility: [ - "//visibility:private", - ], -} - -// Ethernet related libraries. - -filegroup { - name: "services.connectivity-ethernet-sources", - srcs: [ - "src/com/android/server/net/DelayedDiskWrite.java", - "src/com/android/server/net/IpConfigStore.java", - ], - path: "src", - visibility: [ - "//frameworks/opt/net/ethernet/tests", - ], -} - // Connectivity-T common libraries. // TODO: remove this empty filegroup. @@ -111,20 +69,6 @@ filegroup { visibility: ["//frameworks/base/services/core"], } -filegroup { - name: "services.connectivity-tiramisu-updatable-sources", - srcs: [ - ":services.connectivity-ethernet-sources", - ":services.connectivity-ipsec-sources", - ":services.connectivity-netstats-sources", - ":services.connectivity-nsd-sources", - ], - path: "src", - visibility: [ - "//packages/modules/Connectivity:__subpackages__", - ], -} - cc_library_shared { name: "libcom_android_net_module_util_jni", min_sdk_version: "30", diff --git a/tests/ethernet/Android.bp b/tests/ethernet/Android.bp index 6cfebdcc83..834249012e 100644 --- a/tests/ethernet/Android.bp +++ b/tests/ethernet/Android.bp @@ -24,8 +24,7 @@ android_test { name: "EthernetServiceTests", srcs: [ - ":ethernet-service-updatable-sources", - ":services.connectivity-ethernet-sources", + ":ethernet-service-test-sources", "java/**/*.java", ],