From 0592b920cbabc2e228adc507aeb0222722ac15bd Mon Sep 17 00:00:00 2001 From: junyulai Date: Sat, 23 Jan 2021 09:46:34 +0800 Subject: [PATCH] [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