• 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 static com.android.net.module.util.BitUtils.packBitList;
48 import static com.android.net.module.util.BitUtils.unpackBits;
49 
50 import android.annotation.NonNull;
51 import android.net.NetworkCapabilities;
52 
53 import com.android.internal.annotations.VisibleForTesting;
54 
55 /**
56  * Utilities to examine {@link android.net.NetworkCapabilities}.
57  * @hide
58  */
59 public final class NetworkCapabilitiesUtils {
60     // Transports considered to classify networks in UI, in order of which transport should be
61     // surfaced when there are multiple transports. Transports not in this list do not have
62     // an ordering preference (in practice they will have a deterministic order based on the
63     // transport int itself).
64     private static final int[] DISPLAY_TRANSPORT_PRIORITIES = new int[] {
65         // Users think of their VPNs as VPNs, not as any of the underlying nets
66         TRANSPORT_VPN,
67         // If the network has cell, prefer showing that because it's usually metered.
68         TRANSPORT_CELLULAR,
69         // If the network has WiFi aware, prefer showing that as it's a more specific use case.
70         // Ethernet can masquerade as other transports, where the device uses ethernet to connect to
71         // a box providing cell or wifi. Today this is represented by only the masqueraded type for
72         // backward compatibility, but these networks should morally have Ethernet & the masqueraded
73         // type. Because of this, prefer other transports instead of Ethernet.
74         TRANSPORT_WIFI_AWARE,
75         TRANSPORT_BLUETOOTH,
76         TRANSPORT_WIFI,
77         TRANSPORT_ETHERNET,
78         TRANSPORT_USB
79 
80         // Notably, TRANSPORT_TEST is not in this list as any network that has TRANSPORT_TEST and
81         // one of the above transports should be counted as that transport, to keep tests as
82         // realistic as possible.
83     };
84 
85     /**
86      * Capabilities that suggest that a network is restricted.
87      * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted},
88       * and {@code FORCE_RESTRICTED_CAPABILITIES}.
89      */
90     @VisibleForTesting
91     public static final long RESTRICTED_CAPABILITIES = packBitList(
92             NET_CAPABILITY_BIP,
93             NET_CAPABILITY_CBS,
94             NET_CAPABILITY_DUN,
95             NET_CAPABILITY_EIMS,
96             NET_CAPABILITY_ENTERPRISE,
97             NET_CAPABILITY_FOTA,
98             NET_CAPABILITY_IA,
99             NET_CAPABILITY_IMS,
100             NET_CAPABILITY_MCX,
101             NET_CAPABILITY_RCS,
102             NET_CAPABILITY_VEHICLE_INTERNAL,
103             NET_CAPABILITY_VSIM,
104             NET_CAPABILITY_XCAP,
105             NET_CAPABILITY_MMTEL);
106 
107     /**
108      * Capabilities that force network to be restricted.
109      * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted}.
110      */
111     private static final long FORCE_RESTRICTED_CAPABILITIES = packBitList(
112             NET_CAPABILITY_ENTERPRISE,
113             NET_CAPABILITY_OEM_PAID,
114             NET_CAPABILITY_OEM_PRIVATE);
115 
116     /**
117      * Capabilities that suggest that a network is unrestricted.
118      * See {@code NetworkCapabilities#maybeMarkCapabilitiesRestricted}.
119      */
120     @VisibleForTesting
121     public static final long UNRESTRICTED_CAPABILITIES = packBitList(
122             NET_CAPABILITY_INTERNET,
123             NET_CAPABILITY_MMS,
124             NET_CAPABILITY_SUPL,
125             NET_CAPABILITY_WIFI_P2P);
126 
127     /**
128      * Get a transport that can be used to classify a network when displaying its info to users.
129      *
130      * While networks can have multiple transports, users generally think of them as "wifi",
131      * "mobile data", "vpn" and expect them to be classified as such in UI such as settings.
132      * @param transports Non-empty array of transports on a network
133      * @return A single transport
134      * @throws IllegalArgumentException The array is empty
135      */
getDisplayTransport(@onNull int[] transports)136     public static int getDisplayTransport(@NonNull int[] transports) {
137         for (int transport : DISPLAY_TRANSPORT_PRIORITIES) {
138             if (CollectionUtils.contains(transports, transport)) {
139                 return transport;
140             }
141         }
142 
143         if (transports.length < 1) {
144             // All NetworkCapabilities representing a network have at least one transport, so an
145             // empty transport array would be created by the caller instead of extracted from
146             // NetworkCapabilities.
147             throw new IllegalArgumentException("No transport in the provided array");
148         }
149         return transports[0];
150     }
151 
152 
153     /**
154      * Infers that all the capabilities it provides are typically provided by restricted networks
155      * or not.
156      *
157      * @param nc the {@link NetworkCapabilities} to infer the restricted capabilities.
158      *
159      * @return {@code true} if the network should be restricted.
160      */
161     // TODO: Use packBits(nc.getCapabilities()) to check more easily using bit masks.
inferRestrictedCapability(NetworkCapabilities nc)162     public static boolean inferRestrictedCapability(NetworkCapabilities nc) {
163         // Check if we have any capability that forces the network to be restricted.
164         for (int capability : unpackBits(FORCE_RESTRICTED_CAPABILITIES)) {
165             if (nc.hasCapability(capability)) {
166                 return true;
167             }
168         }
169 
170         // Verify there aren't any unrestricted capabilities.  If there are we say
171         // the whole thing is unrestricted unless it is forced to be restricted.
172         for (int capability : unpackBits(UNRESTRICTED_CAPABILITIES)) {
173             if (nc.hasCapability(capability)) {
174                 return false;
175             }
176         }
177 
178         // Must have at least some restricted capabilities.
179         for (int capability : unpackBits(RESTRICTED_CAPABILITIES)) {
180             if (nc.hasCapability(capability)) {
181                 return true;
182             }
183         }
184         return false;
185     }
186 
187 }
188