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