• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.net.module.util;
18 
19 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
20 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
21 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
22 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOTA;
23 import static android.net.NetworkCapabilities.NET_CAPABILITY_IA;
24 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
25 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
26 import static android.net.NetworkCapabilities.NET_CAPABILITY_MCX;
27 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
28 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
29 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
30 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
31 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
32 import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
33 import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
34 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
35 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
36 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
37 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
38 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
39 
40 import android.annotation.NonNull;
41 import android.net.NetworkCapabilities;
42 
43 import com.android.internal.annotations.VisibleForTesting;
44 
45 /**
46  * Utilities to examine {@link android.net.NetworkCapabilities}.
47  * @hide
48  */
49 public final class NetworkCapabilitiesUtils {
50     /**
51      * See android.net.NetworkCapabilities.TRANSPORT_USB
52      * TODO: Use API constant when all downstream branches are S-based
53      */
54     public static final int TRANSPORT_USB = 8;
55 
56     // Transports considered to classify networks in UI, in order of which transport should be
57     // surfaced when there are multiple transports. Transports not in this list do not have
58     // an ordering preference (in practice they will have a deterministic order based on the
59     // transport int itself).
60     private static final int[] DISPLAY_TRANSPORT_PRIORITIES = new int[] {
61         // Users think of their VPNs as VPNs, not as any of the underlying nets
62         TRANSPORT_VPN,
63         // If the network has cell, prefer showing that because it's usually metered.
64         TRANSPORT_CELLULAR,
65         // If the network has WiFi aware, prefer showing that as it's a more specific use case.
66         // Ethernet can masquerade as other transports, where the device uses ethernet to connect to
67         // a box providing cell or wifi. Today this is represented by only the masqueraded type for
68         // backward compatibility, but these networks should morally have Ethernet & the masqueraded
69         // type. Because of this, prefer other transports instead of Ethernet.
70         TRANSPORT_WIFI_AWARE,
71         TRANSPORT_BLUETOOTH,
72         TRANSPORT_WIFI,
73         TRANSPORT_ETHERNET,
74         TRANSPORT_USB
75 
76         // Notably, TRANSPORT_TEST is not in this list as any network that has TRANSPORT_TEST and
77         // one of the above transports should be counted as that transport, to keep tests as
78         // realistic as possible.
79     };
80 
81     /**
82      * See android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE
83      * TODO: Use API constant when all downstream branches are S-based
84      */
85     public static final int NET_CAPABILITY_OEM_PRIVATE = 26;
86 
87     /**
88      * See android.net.NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL
89      * TODO: Use API constant when all downstream branches are S-based
90      */
91     public static final int NET_CAPABILITY_VEHICLE_INTERNAL = 27;
92 
93     /**
94      * See android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
95      * TODO: Use API constant when all downstream branches are S-based
96      */
97     public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
98 
99     /**
100      * See android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE
101      * TODO: Use API constant when all downstream branches are S-based
102      */
103     public static final int NET_CAPABILITY_ENTERPRISE = 29;
104 
105     /**
106      * See android.net.NetworkCapabilities.NET_CAPABILITY_VSIM
107      * TODO: Use API constant when all downstream branches are S-based
108      */
109     public static final int NET_CAPABILITY_VSIM = 30;
110 
111     /**
112      * See android.net.NetworkCapabilities.NET_CAPABILITY_BIP
113      * TODO: Use API constant when all downstream branches are S-based
114      */
115     public static final int NET_CAPABILITY_BIP = 31;
116 
117 
118     /**
119      * Capabilities that suggest that a network is restricted.
120      * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted},
121       * and {@code FORCE_RESTRICTED_CAPABILITIES}.
122      */
123     @VisibleForTesting
124     static final long RESTRICTED_CAPABILITIES =
125             (1 << NET_CAPABILITY_BIP)
126             | (1 << NET_CAPABILITY_CBS)
127             | (1 << NET_CAPABILITY_DUN)
128             | (1 << NET_CAPABILITY_EIMS)
129             | (1 << NET_CAPABILITY_ENTERPRISE)
130             | (1 << NET_CAPABILITY_FOTA)
131             | (1 << NET_CAPABILITY_IA)
132             | (1 << NET_CAPABILITY_IMS)
133             | (1 << NET_CAPABILITY_MCX)
134             | (1 << NET_CAPABILITY_RCS)
135             | (1 << NET_CAPABILITY_VEHICLE_INTERNAL)
136             | (1 << NET_CAPABILITY_VSIM)
137             | (1 << NET_CAPABILITY_XCAP);
138 
139     /**
140      * Capabilities that force network to be restricted.
141      * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted}.
142      */
143     private static final long FORCE_RESTRICTED_CAPABILITIES =
144             (1 << NET_CAPABILITY_ENTERPRISE)
145             | (1 << NET_CAPABILITY_OEM_PAID)
146             | (1 << NET_CAPABILITY_OEM_PRIVATE);
147 
148     /**
149      * Capabilities that suggest that a network is unrestricted.
150      * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted}.
151      */
152     @VisibleForTesting
153     static final long UNRESTRICTED_CAPABILITIES =
154             (1 << NET_CAPABILITY_INTERNET)
155             | (1 << NET_CAPABILITY_MMS)
156             | (1 << NET_CAPABILITY_SUPL)
157             | (1 << NET_CAPABILITY_WIFI_P2P);
158 
159     /**
160      * Get a transport that can be used to classify a network when displaying its info to users.
161      *
162      * While networks can have multiple transports, users generally think of them as "wifi",
163      * "mobile data", "vpn" and expect them to be classified as such in UI such as settings.
164      * @param transports Non-empty array of transports on a network
165      * @return A single transport
166      * @throws IllegalArgumentException The array is empty
167      */
getDisplayTransport(@onNull int[] transports)168     public static int getDisplayTransport(@NonNull int[] transports) {
169         for (int transport : DISPLAY_TRANSPORT_PRIORITIES) {
170             if (CollectionUtils.contains(transports, transport)) {
171                 return transport;
172             }
173         }
174 
175         if (transports.length < 1) {
176             // All NetworkCapabilities representing a network have at least one transport, so an
177             // empty transport array would be created by the caller instead of extracted from
178             // NetworkCapabilities.
179             throw new IllegalArgumentException("No transport in the provided array");
180         }
181         return transports[0];
182     }
183 
184 
185     /**
186      * Infers that all the capabilities it provides are typically provided by restricted networks
187      * or not.
188      *
189      * @param nc the {@link NetworkCapabilities} to infer the restricted capabilities.
190      *
191      * @return {@code true} if the network should be restricted.
192      */
193     // TODO: Use packBits(nc.getCapabilities()) to check more easily using bit masks.
inferRestrictedCapability(NetworkCapabilities nc)194     public static boolean inferRestrictedCapability(NetworkCapabilities nc) {
195         // Check if we have any capability that forces the network to be restricted.
196         for (int capability : unpackBits(FORCE_RESTRICTED_CAPABILITIES)) {
197             if (nc.hasCapability(capability)) {
198                 return true;
199             }
200         }
201 
202         // Verify there aren't any unrestricted capabilities.  If there are we say
203         // the whole thing is unrestricted unless it is forced to be restricted.
204         for (int capability : unpackBits(UNRESTRICTED_CAPABILITIES)) {
205             if (nc.hasCapability(capability)) {
206                 return false;
207             }
208         }
209 
210         // Must have at least some restricted capabilities.
211         for (int capability : unpackBits(RESTRICTED_CAPABILITIES)) {
212             if (nc.hasCapability(capability)) {
213                 return true;
214             }
215         }
216         return false;
217     }
218 
219     /**
220      * Unpacks long value into an array of bits.
221      */
unpackBits(long val)222     public static int[] unpackBits(long val) {
223         int size = Long.bitCount(val);
224         int[] result = new int[size];
225         int index = 0;
226         int bitPos = 0;
227         while (val != 0) {
228             if ((val & 1) == 1) result[index++] = bitPos;
229             val = val >>> 1;
230             bitPos++;
231         }
232         return result;
233     }
234 
235     /**
236      * Packs array of bits into a long value.
237      */
packBits(int[] bits)238     public static long packBits(int[] bits) {
239         long packed = 0;
240         for (int b : bits) {
241             packed |= (1L << b);
242         }
243         return packed;
244     }
245 }
246