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