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