Stop accessing VPNs in getAllVpnInfo.

This is only used for NetworkStatsService and only called on the
handler thread, so it can be replaced by a simple scan over
mNetworkAgentInfos without having to take any locks.

Bug: 173331190
Test: passes existing tests in ConnectivityServiceTest
Change-Id: I194e0cc55603a0f59f7138f38329f505b55da132
This commit is contained in:
Lorenzo Colitti
2020-11-17 15:58:21 +09:00
parent 8000e03ec9
commit fee5e4e34c

View File

@@ -4730,10 +4730,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (mLockdownEnabled) { if (mLockdownEnabled) {
return new VpnInfo[0]; return new VpnInfo[0];
} }
List<VpnInfo> infoList = new ArrayList<>(); List<VpnInfo> infoList = new ArrayList<>();
for (int i = 0; i < mVpns.size(); i++) { for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
VpnInfo info = createVpnInfo(mVpns.valueAt(i)); VpnInfo info = createVpnInfo(nai);
if (info != null) { if (info != null) {
infoList.add(info); infoList.add(info);
} }
@@ -4746,13 +4745,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
* @return VPN information for accounting, or null if we can't retrieve all required * @return VPN information for accounting, or null if we can't retrieve all required
* information, e.g underlying ifaces. * information, e.g underlying ifaces.
*/ */
@Nullable private VpnInfo createVpnInfo(NetworkAgentInfo nai) {
private VpnInfo createVpnInfo(Vpn vpn) { if (!nai.isVPN()) return null;
VpnInfo info = vpn.getVpnInfo();
if (info == null) { Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
return null;
}
Network[] underlyingNetworks = vpn.getUnderlyingNetworks();
// see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret // see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
// the underlyingNetworks list. // the underlyingNetworks list.
if (underlyingNetworks == null) { if (underlyingNetworks == null) {
@@ -4761,23 +4757,33 @@ public class ConnectivityService extends IConnectivityManager.Stub
underlyingNetworks = new Network[] { defaultNai.network }; underlyingNetworks = new Network[] { defaultNai.network };
} }
} }
if (underlyingNetworks != null && underlyingNetworks.length > 0) {
if (ArrayUtils.isEmpty(underlyingNetworks)) return null;
List<String> interfaces = new ArrayList<>(); List<String> interfaces = new ArrayList<>();
for (Network network : underlyingNetworks) { for (Network network : underlyingNetworks) {
LinkProperties lp = getLinkProperties(network); NetworkAgentInfo underlyingNai = getNetworkAgentInfoForNetwork(network);
if (lp != null) { if (underlyingNai == null) continue;
LinkProperties lp = underlyingNai.linkProperties;
for (String iface : lp.getAllInterfaceNames()) { for (String iface : lp.getAllInterfaceNames()) {
if (!TextUtils.isEmpty(iface)) { if (!TextUtils.isEmpty(iface)) {
interfaces.add(iface); interfaces.add(iface);
} }
} }
} }
}
if (!interfaces.isEmpty()) { if (interfaces.isEmpty()) return null;
info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
} VpnInfo info = new VpnInfo();
} info.ownerUid = nai.networkCapabilities.getOwnerUid();
return info.underlyingIfaces == null ? null : info; info.vpnIface = nai.linkProperties.getInterfaceName();
// Must be non-null or NetworkStatsService will crash.
// Cannot happen in production code because Vpn only registers the NetworkAgent after the
// tun or ipsec interface is created.
if (info.vpnIface == null) return null;
info.underlyingIfaces = interfaces.toArray(new String[0]);
return info;
} }
/** /**