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