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