WifiConfigManager.java revision 47678c136b1f88be3d04d89aa5898e77fa1862a3
1a0842b40441db5332a5290f941021636b1182761Sol Boucher/* 2a0842b40441db5332a5290f941021636b1182761Sol Boucher * Copyright (C) 2016 The Android Open Source Project 3a0842b40441db5332a5290f941021636b1182761Sol Boucher * 4a0842b40441db5332a5290f941021636b1182761Sol Boucher * Licensed under the Apache License, Version 2.0 (the "License"); 5a0842b40441db5332a5290f941021636b1182761Sol Boucher * you may not use this file except in compliance with the License. 6a0842b40441db5332a5290f941021636b1182761Sol Boucher * You may obtain a copy of the License at 7a0842b40441db5332a5290f941021636b1182761Sol Boucher * 8a0842b40441db5332a5290f941021636b1182761Sol Boucher * http://www.apache.org/licenses/LICENSE-2.0 9a0842b40441db5332a5290f941021636b1182761Sol Boucher * 10a0842b40441db5332a5290f941021636b1182761Sol Boucher * Unless required by applicable law or agreed to in writing, software 11a0842b40441db5332a5290f941021636b1182761Sol Boucher * distributed under the License is distributed on an "AS IS" BASIS, 12a0842b40441db5332a5290f941021636b1182761Sol Boucher * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a0842b40441db5332a5290f941021636b1182761Sol Boucher * See the License for the specific language governing permissions and 14a0842b40441db5332a5290f941021636b1182761Sol Boucher * limitations under the License. 15a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 16a0842b40441db5332a5290f941021636b1182761Sol Boucher 17a0842b40441db5332a5290f941021636b1182761Sol Boucherpackage com.android.server.wifi; 18a0842b40441db5332a5290f941021636b1182761Sol Boucher 19a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.app.ActivityManager; 20a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.app.admin.DeviceAdminInfo; 21de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.app.admin.DevicePolicyManagerInternal; 22f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucherimport android.content.ContentResolver; 23a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.content.Context; 24f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucherimport android.content.Intent; 25a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.content.pm.ApplicationInfo; 26a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.content.pm.PackageManager; 27a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.net.IpConfiguration; 28a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.net.ProxyInfo; 29a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.net.StaticIpConfiguration; 30a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.net.wifi.ScanResult; 31a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.net.wifi.WifiConfiguration; 32a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.net.wifi.WifiConfiguration.NetworkSelectionStatus; 33a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.net.wifi.WifiEnterpriseConfig; 34a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.net.wifi.WifiInfo; 35a97b7d1192e246a5f738991adca37cce282e1382Sol Boucherimport android.net.wifi.WifiManager; 36de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.net.wifi.WifiScanner; 37de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport android.os.Process; 38aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucherimport android.os.UserHandle; 39a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.os.UserManager; 40a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.provider.Settings; 41a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.telephony.TelephonyManager; 42a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.text.TextUtils; 43a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.util.ArraySet; 44a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.util.LocalLog; 45a0842b40441db5332a5290f941021636b1182761Sol Boucherimport android.util.Log; 46a0842b40441db5332a5290f941021636b1182761Sol Boucher 47de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.internal.R; 48a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.internal.annotations.VisibleForTesting; 49de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucherimport com.android.server.LocalServices; 50a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.server.wifi.WifiConfigStoreLegacy.WifiConfigStoreDataLegacy; 51a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.server.wifi.hotspot2.PasspointManager; 52a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.server.wifi.util.TelephonyUtil; 53a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.server.wifi.util.WifiPermissionsUtil; 54a0842b40441db5332a5290f941021636b1182761Sol Boucherimport com.android.server.wifi.util.WifiPermissionsWrapper; 55a0842b40441db5332a5290f941021636b1182761Sol Boucher 56a0842b40441db5332a5290f941021636b1182761Sol Boucherimport org.xmlpull.v1.XmlPullParserException; 57a0842b40441db5332a5290f941021636b1182761Sol Boucher 58a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.io.FileDescriptor; 59a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.io.IOException; 60a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.io.PrintWriter; 61a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.ArrayList; 62a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.BitSet; 63a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Calendar; 64a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Collection; 65a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Collections; 66a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.HashMap; 67aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucherimport java.util.HashSet; 68a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Iterator; 69a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.List; 70a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Map; 71a0842b40441db5332a5290f941021636b1182761Sol Boucherimport java.util.Set; 72a0842b40441db5332a5290f941021636b1182761Sol Boucher 73a0842b40441db5332a5290f941021636b1182761Sol Boucher/** 74a0842b40441db5332a5290f941021636b1182761Sol Boucher * This class provides the APIs to manage configured Wi-Fi networks. 75a0842b40441db5332a5290f941021636b1182761Sol Boucher * It deals with the following: 76a0842b40441db5332a5290f941021636b1182761Sol Boucher * - Maintaining a list of configured networks for quick access. 77a0842b40441db5332a5290f941021636b1182761Sol Boucher * - Persisting the configurations to store when required. 78a0842b40441db5332a5290f941021636b1182761Sol Boucher * - Supporting WifiManager Public API calls: 79a0842b40441db5332a5290f941021636b1182761Sol Boucher * > addOrUpdateNetwork() 80a0842b40441db5332a5290f941021636b1182761Sol Boucher * > removeNetwork() 81a0842b40441db5332a5290f941021636b1182761Sol Boucher * > enableNetwork() 82a0842b40441db5332a5290f941021636b1182761Sol Boucher * > disableNetwork() 83a0842b40441db5332a5290f941021636b1182761Sol Boucher * - Handle user switching on multi-user devices. 84a0842b40441db5332a5290f941021636b1182761Sol Boucher * 85a0842b40441db5332a5290f941021636b1182761Sol Boucher * All network configurations retrieved from this class are copies of the original configuration 86a0842b40441db5332a5290f941021636b1182761Sol Boucher * stored in the internal database. So, any updates to the retrieved configuration object are 87a0842b40441db5332a5290f941021636b1182761Sol Boucher * meaningless and will not be reflected in the original database. 88a0842b40441db5332a5290f941021636b1182761Sol Boucher * This is done on purpose to ensure that only WifiConfigManager can modify configurations stored 89a0842b40441db5332a5290f941021636b1182761Sol Boucher * in the internal database. Any configuration updates should be triggered with appropriate helper 90a0842b40441db5332a5290f941021636b1182761Sol Boucher * methods of this class using the configuration's unique networkId. 91a0842b40441db5332a5290f941021636b1182761Sol Boucher * 92a0842b40441db5332a5290f941021636b1182761Sol Boucher * NOTE: These API's are not thread safe and should only be used from WifiStateMachine thread. 93aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucher */ 94aa907a3b6637b4f95dbf572d0cf790a70ba3aeb0Sol Boucherpublic class WifiConfigManager { 95a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 96a0842b40441db5332a5290f941021636b1182761Sol Boucher * String used to mask passwords to public interface. 97a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 98a0842b40441db5332a5290f941021636b1182761Sol Boucher @VisibleForTesting 99a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final String PASSWORD_MASK = "*"; 100a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 101a0842b40441db5332a5290f941021636b1182761Sol Boucher * Package name for SysUI. This is used to lookup the UID of SysUI which is used to allow 102a0842b40441db5332a5290f941021636b1182761Sol Boucher * Quick settings to modify network configurations. 103a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 104a0842b40441db5332a5290f941021636b1182761Sol Boucher @VisibleForTesting 105a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final String SYSUI_PACKAGE_NAME = "com.android.systemui"; 106a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 107a0842b40441db5332a5290f941021636b1182761Sol Boucher * Network Selection disable reason thresholds. These numbers are used to debounce network 108a0842b40441db5332a5290f941021636b1182761Sol Boucher * failures before we disable them. 109a0842b40441db5332a5290f941021636b1182761Sol Boucher * These are indexed using the disable reason constants defined in 110a0842b40441db5332a5290f941021636b1182761Sol Boucher * {@link android.net.wifi.WifiConfiguration.NetworkSelectionStatus}. 111a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 112a0842b40441db5332a5290f941021636b1182761Sol Boucher @VisibleForTesting 113a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int[] NETWORK_SELECTION_DISABLE_THRESHOLD = { 114a0842b40441db5332a5290f941021636b1182761Sol Boucher -1, // threshold for NETWORK_SELECTION_ENABLE 115a0842b40441db5332a5290f941021636b1182761Sol Boucher 1, // threshold for DISABLED_BAD_LINK 116a0842b40441db5332a5290f941021636b1182761Sol Boucher 5, // threshold for DISABLED_ASSOCIATION_REJECTION 117a0842b40441db5332a5290f941021636b1182761Sol Boucher 5, // threshold for DISABLED_AUTHENTICATION_FAILURE 118a0842b40441db5332a5290f941021636b1182761Sol Boucher 5, // threshold for DISABLED_DHCP_FAILURE 119a0842b40441db5332a5290f941021636b1182761Sol Boucher 5, // threshold for DISABLED_DNS_FAILURE 120a0842b40441db5332a5290f941021636b1182761Sol Boucher 1, // threshold for DISABLED_WPS_START 121a0842b40441db5332a5290f941021636b1182761Sol Boucher 6, // threshold for DISABLED_TLS_VERSION_MISMATCH 122a0842b40441db5332a5290f941021636b1182761Sol Boucher 1, // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS 123a0842b40441db5332a5290f941021636b1182761Sol Boucher 1, // threshold for DISABLED_NO_INTERNET 124a0842b40441db5332a5290f941021636b1182761Sol Boucher 1, // threshold for DISABLED_BY_WIFI_MANAGER 125a0842b40441db5332a5290f941021636b1182761Sol Boucher 1, // threshold for DISABLED_BY_USER_SWITCH 126a0842b40441db5332a5290f941021636b1182761Sol Boucher 1 // threshold for DISABLED_BY_WRONG_PASSWORD 127a0842b40441db5332a5290f941021636b1182761Sol Boucher }; 128a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 129a0842b40441db5332a5290f941021636b1182761Sol Boucher * Network Selection disable timeout for each kind of error. After the timeout milliseconds, 130a0842b40441db5332a5290f941021636b1182761Sol Boucher * enable the network again. 131a0842b40441db5332a5290f941021636b1182761Sol Boucher * These are indexed using the disable reason constants defined in 132a0842b40441db5332a5290f941021636b1182761Sol Boucher * {@link android.net.wifi.WifiConfiguration.NetworkSelectionStatus}. 133a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 134a0842b40441db5332a5290f941021636b1182761Sol Boucher @VisibleForTesting 135a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int[] NETWORK_SELECTION_DISABLE_TIMEOUT_MS = { 136a0842b40441db5332a5290f941021636b1182761Sol Boucher Integer.MAX_VALUE, // threshold for NETWORK_SELECTION_ENABLE 137a0842b40441db5332a5290f941021636b1182761Sol Boucher 15 * 60 * 1000, // threshold for DISABLED_BAD_LINK 138a0842b40441db5332a5290f941021636b1182761Sol Boucher 5 * 60 * 1000, // threshold for DISABLED_ASSOCIATION_REJECTION 139a0842b40441db5332a5290f941021636b1182761Sol Boucher 5 * 60 * 1000, // threshold for DISABLED_AUTHENTICATION_FAILURE 140a0842b40441db5332a5290f941021636b1182761Sol Boucher 5 * 60 * 1000, // threshold for DISABLED_DHCP_FAILURE 141a0842b40441db5332a5290f941021636b1182761Sol Boucher 5 * 60 * 1000, // threshold for DISABLED_DNS_FAILURE 142a0842b40441db5332a5290f941021636b1182761Sol Boucher 0 * 60 * 1000, // threshold for DISABLED_WPS_START 143a0842b40441db5332a5290f941021636b1182761Sol Boucher Integer.MAX_VALUE, // threshold for DISABLED_TLS_VERSION 144a0842b40441db5332a5290f941021636b1182761Sol Boucher Integer.MAX_VALUE, // threshold for DISABLED_AUTHENTICATION_NO_CREDENTIALS 145a0842b40441db5332a5290f941021636b1182761Sol Boucher Integer.MAX_VALUE, // threshold for DISABLED_NO_INTERNET 146a0842b40441db5332a5290f941021636b1182761Sol Boucher Integer.MAX_VALUE, // threshold for DISABLED_BY_WIFI_MANAGER 147a0842b40441db5332a5290f941021636b1182761Sol Boucher Integer.MAX_VALUE, // threshold for DISABLED_BY_USER_SWITCH 148a0842b40441db5332a5290f941021636b1182761Sol Boucher Integer.MAX_VALUE // threshold for DISABLED_BY_WRONG_PASSWORD 149a0842b40441db5332a5290f941021636b1182761Sol Boucher }; 150a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 151a0842b40441db5332a5290f941021636b1182761Sol Boucher * Interface for other modules to listen to the saved network updated 152a0842b40441db5332a5290f941021636b1182761Sol Boucher * events. 153a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 154a0842b40441db5332a5290f941021636b1182761Sol Boucher public interface OnSavedNetworkUpdateListener { 155a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 156a0842b40441db5332a5290f941021636b1182761Sol Boucher * Invoked on saved network being added. 157a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 158a0842b40441db5332a5290f941021636b1182761Sol Boucher void onSavedNetworkAdded(int networkId); 159a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 160a0842b40441db5332a5290f941021636b1182761Sol Boucher * Invoked on saved network being enabled. 161a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 162de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher void onSavedNetworkEnabled(int networkId); 163bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala /** 164de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Invoked on saved network being permanently disabled. 165de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 166a0842b40441db5332a5290f941021636b1182761Sol Boucher void onSavedNetworkPermanentlyDisabled(int networkId); 167a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 168a0842b40441db5332a5290f941021636b1182761Sol Boucher * Invoked on saved network being removed. 169a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 170a0842b40441db5332a5290f941021636b1182761Sol Boucher void onSavedNetworkRemoved(int networkId); 171a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 172a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Invoked on saved network being temporarily disabled. 173a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 174a0842b40441db5332a5290f941021636b1182761Sol Boucher void onSavedNetworkTemporarilyDisabled(int networkId); 175de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 176a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Invoked on saved network being updated. 177de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 178a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher void onSavedNetworkUpdated(int networkId); 179a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 180a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 181a0842b40441db5332a5290f941021636b1182761Sol Boucher * Max size of scan details to cache in {@link #mScanDetailCaches}. 182a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 183a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @VisibleForTesting 184a0842b40441db5332a5290f941021636b1182761Sol Boucher public static final int SCAN_CACHE_ENTRIES_MAX_SIZE = 192; 185a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 186a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Once the size of the scan details in the cache {@link #mScanDetailCaches} exceeds 187de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * {@link #SCAN_CACHE_ENTRIES_MAX_SIZE}, trim it down to this value so that we have some 188a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * buffer time before the next eviction. 189a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 190a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher @VisibleForTesting 191a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher public static final int SCAN_CACHE_ENTRIES_TRIM_SIZE = 128; 192a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 193a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Link networks only if they have less than this number of scan cache entries. 194a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 195de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher @VisibleForTesting 196de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public static final int LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES = 6; 197de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 198a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Link networks only if the bssid in scan results for the networks match in the first 199a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * 16 ASCII chars in the bssid string. For example = "af:de:56;34:15:7" 200a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 201984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher @VisibleForTesting 202984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public static final int LINK_CONFIGURATION_BSSID_MATCH_LENGTH = 16; 203984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 204a0842b40441db5332a5290f941021636b1182761Sol Boucher * Flags to be passed in for |canModifyNetwork| to decide if the change is minor and can 205a0842b40441db5332a5290f941021636b1182761Sol Boucher * bypass the lockdown checks. 206a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 207a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final boolean ALLOW_LOCKDOWN_CHECK_BYPASS = true; 208a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final boolean DISALLOW_LOCKDOWN_CHECK_BYPASS = false; 209a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 210a0842b40441db5332a5290f941021636b1182761Sol Boucher * Log tag for this class. 211a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 212a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final String TAG = "WifiConfigManager"; 213a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 214a0842b40441db5332a5290f941021636b1182761Sol Boucher * Maximum age of scan results that can be used for averaging out RSSI value. 215a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 216a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final int SCAN_RESULT_MAXIMUM_AGE_MS = 40000; 217a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 218772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher * General sorting algorithm of all networks for scanning purposes: 219a0842b40441db5332a5290f941021636b1182761Sol Boucher * Place the configurations in descending order of their |numAssociation| values. If networks 220a0842b40441db5332a5290f941021636b1182761Sol Boucher * have the same |numAssociation|, place the configurations with 221a0842b40441db5332a5290f941021636b1182761Sol Boucher * |lastSeenInQualifiedNetworkSelection| set first. 222a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 223a0842b40441db5332a5290f941021636b1182761Sol Boucher private static final WifiConfigurationUtil.WifiConfigurationComparator sScanListComparator = 224a0842b40441db5332a5290f941021636b1182761Sol Boucher new WifiConfigurationUtil.WifiConfigurationComparator() { 225a0842b40441db5332a5290f941021636b1182761Sol Boucher @Override 226a0842b40441db5332a5290f941021636b1182761Sol Boucher public int compareNetworksWithSameStatus(WifiConfiguration a, WifiConfiguration b) { 22750f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher if (a.numAssociation != b.numAssociation) { 22850f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher return Long.compare(b.numAssociation, a.numAssociation); 229a0842b40441db5332a5290f941021636b1182761Sol Boucher } else { 230a0842b40441db5332a5290f941021636b1182761Sol Boucher boolean isConfigALastSeen = 231a0842b40441db5332a5290f941021636b1182761Sol Boucher a.getNetworkSelectionStatus() 232a0842b40441db5332a5290f941021636b1182761Sol Boucher .getSeenInLastQualifiedNetworkSelection(); 233a0842b40441db5332a5290f941021636b1182761Sol Boucher boolean isConfigBLastSeen = 234bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala b.getNetworkSelectionStatus() 235a0842b40441db5332a5290f941021636b1182761Sol Boucher .getSeenInLastQualifiedNetworkSelection(); 236a0842b40441db5332a5290f941021636b1182761Sol Boucher return Boolean.compare(isConfigBLastSeen, isConfigALastSeen); 237a0842b40441db5332a5290f941021636b1182761Sol Boucher } 238a0842b40441db5332a5290f941021636b1182761Sol Boucher } 239a0842b40441db5332a5290f941021636b1182761Sol Boucher }; 240a0842b40441db5332a5290f941021636b1182761Sol Boucher 241a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 242a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * List of external dependencies for WifiConfigManager. 243a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 244a0842b40441db5332a5290f941021636b1182761Sol Boucher private final Context mContext; 245a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private final Clock mClock; 246a0842b40441db5332a5290f941021636b1182761Sol Boucher private final UserManager mUserManager; 247a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private final BackupManagerProxy mBackupManagerProxy; 248a0842b40441db5332a5290f941021636b1182761Sol Boucher private final TelephonyManager mTelephonyManager; 249a0842b40441db5332a5290f941021636b1182761Sol Boucher private final WifiKeyStore mWifiKeyStore; 250a0842b40441db5332a5290f941021636b1182761Sol Boucher private final WifiConfigStore mWifiConfigStore; 251a0842b40441db5332a5290f941021636b1182761Sol Boucher private final WifiConfigStoreLegacy mWifiConfigStoreLegacy; 252a0842b40441db5332a5290f941021636b1182761Sol Boucher private final WifiPermissionsUtil mWifiPermissionsUtil; 253a0842b40441db5332a5290f941021636b1182761Sol Boucher private final WifiPermissionsWrapper mWifiPermissionsWrapper; 254de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 255a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Local log used for debugging any WifiConfigManager issues. 256a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 257a0842b40441db5332a5290f941021636b1182761Sol Boucher private final LocalLog mLocalLog = 258a0842b40441db5332a5290f941021636b1182761Sol Boucher new LocalLog(ActivityManager.isLowRamDeviceStatic() ? 128 : 256); 259a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 260a0842b40441db5332a5290f941021636b1182761Sol Boucher * Map of configured networks with network id as the key. 261de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 262de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private final ConfigurationMap mConfiguredNetworks; 263de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 264de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Stores a map of NetworkId to ScanDetailCache. 265a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 266a0842b40441db5332a5290f941021636b1182761Sol Boucher private final Map<Integer, ScanDetailCache> mScanDetailCaches; 267a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 268a0842b40441db5332a5290f941021636b1182761Sol Boucher * Framework keeps a list of ephemeral SSIDs that where deleted by user, 269984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * so as, framework knows not to autoconnect again those SSIDs based on scorer input. 270a0842b40441db5332a5290f941021636b1182761Sol Boucher * The list is never cleared up. 271a0842b40441db5332a5290f941021636b1182761Sol Boucher * The SSIDs are encoded in a String as per definition of WifiConfiguration.SSID field. 272a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 273a0842b40441db5332a5290f941021636b1182761Sol Boucher private final Set<String> mDeletedEphemeralSSIDs; 274a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 275a0842b40441db5332a5290f941021636b1182761Sol Boucher * Flag to indicate if only networks with the same psk should be linked. 276a0842b40441db5332a5290f941021636b1182761Sol Boucher * TODO(b/30706406): Remove this flag if unused. 277a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 278a0842b40441db5332a5290f941021636b1182761Sol Boucher private final boolean mOnlyLinkSameCredentialConfigurations; 279a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 280a0842b40441db5332a5290f941021636b1182761Sol Boucher * Number of channels to scan for during partial scans initiated while connected. 281a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 282a0842b40441db5332a5290f941021636b1182761Sol Boucher private final int mMaxNumActiveChannelsForPartialScans; 283a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 284a0842b40441db5332a5290f941021636b1182761Sol Boucher * Verbose logging flag. Toggled by developer options. 285a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 286a0842b40441db5332a5290f941021636b1182761Sol Boucher private boolean mVerboseLoggingEnabled = false; 287a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 288a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Current logged in user ID. 289a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 290a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private int mCurrentUserId = UserHandle.USER_SYSTEM; 291a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 292a0842b40441db5332a5290f941021636b1182761Sol Boucher * Flag to indicate that the new user's store has not yet been read since user switch. 293a0842b40441db5332a5290f941021636b1182761Sol Boucher * Initialize this flag to |true| to trigger a read on the first user unlock after 294a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * bootup. 295984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 296a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private boolean mPendingUnlockStoreRead = true; 297de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 298de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Flag to indicate if we have performed a read from store at all. This is used to gate 299de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * any user unlock/switch operations until we read the store (Will happen if wifi is disabled 300bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala * when user updates from N to O). 301a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 302a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private boolean mPendingStoreRead = true; 303984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 304a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Flag to indicate if the user unlock was deferred until the store load occurs. 305a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 306a0842b40441db5332a5290f941021636b1182761Sol Boucher private boolean mDeferredUserUnlockRead = false; 307a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 3082569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher * Flag to indicate if SIM is present. 3092569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher */ 3102569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher private boolean mSimPresent = false; 3112569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher /** 312a0842b40441db5332a5290f941021636b1182761Sol Boucher * This is keeping track of the next network ID to be assigned. Any new networks will be 313a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * assigned |mNextNetworkId| as network ID. 314a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 315a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private int mNextNetworkId = 0; 316a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 317a0842b40441db5332a5290f941021636b1182761Sol Boucher * UID of system UI. This uid is allowed to modify network configurations regardless of which 318a0842b40441db5332a5290f941021636b1182761Sol Boucher * user is logged in. 319a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 320984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private int mSystemUiUid = -1; 321a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 322a0842b40441db5332a5290f941021636b1182761Sol Boucher * This is used to remember which network was selected successfully last by an app. This is set 323a0842b40441db5332a5290f941021636b1182761Sol Boucher * when an app invokes {@link #enableNetwork(int, boolean, int)} with |disableOthers| flag set. 324a0842b40441db5332a5290f941021636b1182761Sol Boucher * This is the only way for an app to request connection to a specific network using the 325a0842b40441db5332a5290f941021636b1182761Sol Boucher * {@link WifiManager} API's. 326a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 327a0842b40441db5332a5290f941021636b1182761Sol Boucher private int mLastSelectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 328a0842b40441db5332a5290f941021636b1182761Sol Boucher private long mLastSelectedTimeStamp = 329a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration.NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 330a0842b40441db5332a5290f941021636b1182761Sol Boucher 331a0842b40441db5332a5290f941021636b1182761Sol Boucher // Store data for network list and deleted ephemeral SSID list. Used for serializing 332a0842b40441db5332a5290f941021636b1182761Sol Boucher // parsing data to/from the config store. 333a0842b40441db5332a5290f941021636b1182761Sol Boucher private final NetworkListStoreData mNetworkListStoreData; 334a0842b40441db5332a5290f941021636b1182761Sol Boucher private final DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData; 335a0842b40441db5332a5290f941021636b1182761Sol Boucher 336a0842b40441db5332a5290f941021636b1182761Sol Boucher // Store the saved network update listener. 337a0842b40441db5332a5290f941021636b1182761Sol Boucher private OnSavedNetworkUpdateListener mListener = null; 338a0842b40441db5332a5290f941021636b1182761Sol Boucher 339a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 340a0842b40441db5332a5290f941021636b1182761Sol Boucher * Create new instance of WifiConfigManager. 341a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 342a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfigManager( 343a0842b40441db5332a5290f941021636b1182761Sol Boucher Context context, Clock clock, UserManager userManager, 344a0842b40441db5332a5290f941021636b1182761Sol Boucher TelephonyManager telephonyManager, WifiKeyStore wifiKeyStore, 345a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfigStore wifiConfigStore, WifiConfigStoreLegacy wifiConfigStoreLegacy, 346a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiPermissionsUtil wifiPermissionsUtil, 347a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiPermissionsWrapper wifiPermissionsWrapper, 348a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkListStoreData networkListStoreData, 349a0842b40441db5332a5290f941021636b1182761Sol Boucher DeletedEphemeralSsidsStoreData deletedEphemeralSsidsStoreData) { 350a0842b40441db5332a5290f941021636b1182761Sol Boucher mContext = context; 351a0842b40441db5332a5290f941021636b1182761Sol Boucher mClock = clock; 352a0842b40441db5332a5290f941021636b1182761Sol Boucher mUserManager = userManager; 353a0842b40441db5332a5290f941021636b1182761Sol Boucher mBackupManagerProxy = new BackupManagerProxy(); 354a0842b40441db5332a5290f941021636b1182761Sol Boucher mTelephonyManager = telephonyManager; 355a0842b40441db5332a5290f941021636b1182761Sol Boucher mWifiKeyStore = wifiKeyStore; 356a0842b40441db5332a5290f941021636b1182761Sol Boucher mWifiConfigStore = wifiConfigStore; 357de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mWifiConfigStoreLegacy = wifiConfigStoreLegacy; 358a0842b40441db5332a5290f941021636b1182761Sol Boucher mWifiPermissionsUtil = wifiPermissionsUtil; 359a0842b40441db5332a5290f941021636b1182761Sol Boucher mWifiPermissionsWrapper = wifiPermissionsWrapper; 360a0842b40441db5332a5290f941021636b1182761Sol Boucher 361a0842b40441db5332a5290f941021636b1182761Sol Boucher mConfiguredNetworks = new ConfigurationMap(userManager); 362a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mScanDetailCaches = new HashMap<>(16, 0.75f); 363a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mDeletedEphemeralSSIDs = new HashSet<>(); 364a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 365a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Register store data for network list and deleted ephemeral SSIDs. 366a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mNetworkListStoreData = networkListStoreData; 367a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mDeletedEphemeralSsidsStoreData = deletedEphemeralSsidsStoreData; 368a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mWifiConfigStore.registerStoreData(mNetworkListStoreData); 369a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mWifiConfigStore.registerStoreData(mDeletedEphemeralSsidsStoreData); 370a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 371a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mOnlyLinkSameCredentialConfigurations = mContext.getResources().getBoolean( 372a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher R.bool.config_wifi_only_link_same_credential_configurations); 373a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mMaxNumActiveChannelsForPartialScans = mContext.getResources().getInteger( 374a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher R.integer.config_wifi_framework_associated_partial_scan_max_num_active_channels); 375a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 376a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher try { 377a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mSystemUiUid = mContext.getPackageManager().getPackageUidAsUser(SYSUI_PACKAGE_NAME, 378984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM); 379a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch (PackageManager.NameNotFoundException e) { 380a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Unable to resolve SystemUI's UID."); 381a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 382bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala } 383bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala 384984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 385984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Construct the string to be put in the |creationTime| & |updateTime| elements of 386984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * WifiConfiguration from the provided wall clock millis. 387984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 388984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param wallClockMillis Time in milliseconds to be converted to string. 389984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 390984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher @VisibleForTesting 391984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public static String createDebugTimeStampString(long wallClockMillis) { 392984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher StringBuilder sb = new StringBuilder(); 393a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher sb.append("time="); 394a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Calendar c = Calendar.getInstance(); 395a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher c.setTimeInMillis(wallClockMillis); 396a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher sb.append(String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)); 397984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return sb.toString(); 398984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 399984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 400984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 401984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Enable/disable verbose logging in WifiConfigManager & its helper classes. 402984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 403bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala public void enableVerboseLogging(int verbose) { 404984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (verbose > 0) { 405984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mVerboseLoggingEnabled = true; 406984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } else { 407984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mVerboseLoggingEnabled = false; 408984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 409bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala mWifiConfigStore.enableVerboseLogging(mVerboseLoggingEnabled); 410984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mWifiKeyStore.enableVerboseLogging(mVerboseLoggingEnabled); 411a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 412a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 413a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 414a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Helper method to mask all passwords/keys from the provided WifiConfiguration object. This 415a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * is needed when the network configurations are being requested via the public WifiManager 416a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * API's. 417a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * This currently masks the following elements: psk, wepKeys & enterprise config password. 418a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 419a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private void maskPasswordsInWifiConfiguration(WifiConfiguration configuration) { 420a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (!TextUtils.isEmpty(configuration.preSharedKey)) { 421a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher configuration.preSharedKey = PASSWORD_MASK; 422984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 423de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (configuration.wepKeys != null) { 424de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher for (int i = 0; i < configuration.wepKeys.length; i++) { 425de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!TextUtils.isEmpty(configuration.wepKeys[i])) { 426a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher configuration.wepKeys[i] = PASSWORD_MASK; 427a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 428de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 429de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 430de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!TextUtils.isEmpty(configuration.enterpriseConfig.getPassword())) { 431a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher configuration.enterpriseConfig.setPassword(PASSWORD_MASK); 432a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 433a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 434984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 435a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 436a0842b40441db5332a5290f941021636b1182761Sol Boucher * Helper method to create a copy of the provided internal WifiConfiguration object to be 437a0842b40441db5332a5290f941021636b1182761Sol Boucher * passed to external modules. 438a0842b40441db5332a5290f941021636b1182761Sol Boucher * 439a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param configuration provided WifiConfiguration object. 440a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param maskPasswords Mask passwords or not. 441a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @return Copy of the WifiConfiguration object. 442a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 443a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher private WifiConfiguration createExternalWifiConfiguration( 444a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher WifiConfiguration configuration, boolean maskPasswords) { 445a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher WifiConfiguration network = new WifiConfiguration(configuration); 446a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (maskPasswords) { 447a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher maskPasswordsInWifiConfiguration(network); 448984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 449de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return network; 450de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 451de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 452a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 453a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Fetch the list of currently configured networks maintained in WifiConfigManager. 454de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 455de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * This retrieves a copy of the internal configurations maintained by WifiConfigManager and 456de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * should be used for any public interfaces. 457a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * 458a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param savedOnly Retrieve only saved networks. 459a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param maskPasswords Mask passwords or not. 460984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @return List of WifiConfiguration objects representing the networks. 461a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 462a0842b40441db5332a5290f941021636b1182761Sol Boucher private List<WifiConfiguration> getConfiguredNetworks( 463a0842b40441db5332a5290f941021636b1182761Sol Boucher boolean savedOnly, boolean maskPasswords) { 464a0842b40441db5332a5290f941021636b1182761Sol Boucher List<WifiConfiguration> networks = new ArrayList<>(); 465a0842b40441db5332a5290f941021636b1182761Sol Boucher for (WifiConfiguration config : getInternalConfiguredNetworks()) { 466a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (savedOnly && config.ephemeral) { 467a0842b40441db5332a5290f941021636b1182761Sol Boucher continue; 468a0842b40441db5332a5290f941021636b1182761Sol Boucher } 469a0842b40441db5332a5290f941021636b1182761Sol Boucher networks.add(createExternalWifiConfiguration(config, maskPasswords)); 470a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 471a0842b40441db5332a5290f941021636b1182761Sol Boucher return networks; 472a0842b40441db5332a5290f941021636b1182761Sol Boucher } 473a0842b40441db5332a5290f941021636b1182761Sol Boucher 474a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 475a0842b40441db5332a5290f941021636b1182761Sol Boucher * Retrieves the list of all configured networks with passwords masked. 476a0842b40441db5332a5290f941021636b1182761Sol Boucher * 477a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return List of WifiConfiguration objects representing the networks. 478a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 479a0842b40441db5332a5290f941021636b1182761Sol Boucher public List<WifiConfiguration> getConfiguredNetworks() { 480a0842b40441db5332a5290f941021636b1182761Sol Boucher return getConfiguredNetworks(false, true); 481a0842b40441db5332a5290f941021636b1182761Sol Boucher } 482a0842b40441db5332a5290f941021636b1182761Sol Boucher 483a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 484a0842b40441db5332a5290f941021636b1182761Sol Boucher * Retrieves the list of all configured networks with the passwords in plaintext. 485a0842b40441db5332a5290f941021636b1182761Sol Boucher * 486a0842b40441db5332a5290f941021636b1182761Sol Boucher * WARNING: Don't use this to pass network configurations to external apps. Should only be 487a0842b40441db5332a5290f941021636b1182761Sol Boucher * sent to system apps/wifi stack, when there is a need for passwords in plaintext. 488a0842b40441db5332a5290f941021636b1182761Sol Boucher * TODO: Need to understand the current use case of this API. 489a0842b40441db5332a5290f941021636b1182761Sol Boucher * 490a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return List of WifiConfiguration objects representing the networks. 491a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 492de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public List<WifiConfiguration> getConfiguredNetworksWithPasswords() { 493a0842b40441db5332a5290f941021636b1182761Sol Boucher return getConfiguredNetworks(false, false); 494a0842b40441db5332a5290f941021636b1182761Sol Boucher } 495de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 496de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 497de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Retrieves the list of all configured networks with the passwords masked. 498de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 499a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return List of WifiConfiguration objects representing the networks. 500a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 501a0842b40441db5332a5290f941021636b1182761Sol Boucher public List<WifiConfiguration> getSavedNetworks() { 502a0842b40441db5332a5290f941021636b1182761Sol Boucher return getConfiguredNetworks(true, true); 503de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 504de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 505de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 506de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Retrieves the configured network corresponding to the provided networkId with password 507de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * masked. 508de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 509de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param networkId networkId of the requested network. 510de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @return WifiConfiguration object if found, null otherwise. 511de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 512de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public WifiConfiguration getConfiguredNetwork(int networkId) { 513de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher WifiConfiguration config = getInternalConfiguredNetwork(networkId); 514de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (config == null) { 515984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return null; 516984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 517984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Create a new configuration object with the passwords masked to send out to the external 518984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // world. 519984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return createExternalWifiConfiguration(config, true); 520984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 521984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 522984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 523984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Retrieves the configured network corresponding to the provided config key with password 524984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * masked. 525984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 526984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param configKey configKey of the requested network. 527984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @return WifiConfiguration object if found, null otherwise. 528984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 529984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public WifiConfiguration getConfiguredNetwork(String configKey) { 530de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher WifiConfiguration config = getInternalConfiguredNetwork(configKey); 531de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (config == null) { 532de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return null; 533de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 534de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Create a new configuration object with the passwords masked to send out to the external 535de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // world. 536de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return createExternalWifiConfiguration(config, true); 537de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 538984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 539de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 540de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Retrieves the configured network corresponding to the provided networkId with password 541984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * in plaintext. 542984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 543984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * WARNING: Don't use this to pass network configurations to external apps. Should only be 544984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * sent to system apps/wifi stack, when there is a need for passwords in plaintext. 545bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala * 546bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala * @param networkId networkId of the requested network. 547984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @return WifiConfiguration object if found, null otherwise. 548984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 549984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher public WifiConfiguration getConfiguredNetworkWithPassword(int networkId) { 550984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher WifiConfiguration config = getInternalConfiguredNetwork(networkId); 551984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (config == null) { 552984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return null; 553984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 554984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Create a new configuration object without the passwords masked to send out to the 555984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // external world. 556de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return createExternalWifiConfiguration(config, false); 557de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 558de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 559de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 560984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Helper method to retrieve all the internal WifiConfiguration objects corresponding to all 561984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * the networks in our database. 562984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 563984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private Collection<WifiConfiguration> getInternalConfiguredNetworks() { 564984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return mConfiguredNetworks.valuesForCurrentUser(); 565984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 566bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala 567984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 568984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Helper method to retrieve the internal WifiConfiguration object corresponding to the 569984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * provided configuration in our database. 570984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * This first attempts to find the network using the provided network ID in configuration, 571984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * else it attempts to find a matching configuration using the configKey. 572bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala */ 573984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private WifiConfiguration getInternalConfiguredNetwork(WifiConfiguration config) { 574de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(config.networkId); 575de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (internalConfig != null) { 576de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return internalConfig; 577de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 578de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher internalConfig = mConfiguredNetworks.getByConfigKeyForCurrentUser(config.configKey()); 579de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (internalConfig == null) { 580de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Cannot find network with networkId " + config.networkId 581de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher + " or configKey " + config.configKey()); 582de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 583de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return internalConfig; 584de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 585de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 586de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 587de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Helper method to retrieve the internal WifiConfiguration object corresponding to the 588de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * provided network ID in our database. 589de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 590de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private WifiConfiguration getInternalConfiguredNetwork(int networkId) { 591de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (networkId == WifiConfiguration.INVALID_NETWORK_ID) { 592de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.w(TAG, "Looking up network with invalid networkId -1"); 593de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return null; 594de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 595de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher WifiConfiguration internalConfig = mConfiguredNetworks.getForCurrentUser(networkId); 596de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (internalConfig == null) { 597de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Cannot find network with networkId " + networkId); 598de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 599a0842b40441db5332a5290f941021636b1182761Sol Boucher return internalConfig; 600de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 601a0842b40441db5332a5290f941021636b1182761Sol Boucher 602a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 603a0842b40441db5332a5290f941021636b1182761Sol Boucher * Helper method to retrieve the internal WifiConfiguration object corresponding to the 604a0842b40441db5332a5290f941021636b1182761Sol Boucher * provided configKey in our database. 605a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 606a0842b40441db5332a5290f941021636b1182761Sol Boucher private WifiConfiguration getInternalConfiguredNetwork(String configKey) { 607a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration internalConfig = 608a0842b40441db5332a5290f941021636b1182761Sol Boucher mConfiguredNetworks.getByConfigKeyForCurrentUser(configKey); 609a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (internalConfig == null) { 610a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Cannot find network with configKey " + configKey); 611a0842b40441db5332a5290f941021636b1182761Sol Boucher } 612a0842b40441db5332a5290f941021636b1182761Sol Boucher return internalConfig; 613a0842b40441db5332a5290f941021636b1182761Sol Boucher } 614a0842b40441db5332a5290f941021636b1182761Sol Boucher 615a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 616a0842b40441db5332a5290f941021636b1182761Sol Boucher * Method to send out the configured networks change broadcast when a single network 617a0842b40441db5332a5290f941021636b1182761Sol Boucher * configuration is changed. 618a0842b40441db5332a5290f941021636b1182761Sol Boucher * 619a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param network WifiConfiguration corresponding to the network that was changed. 620a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param reason The reason for the change, should be one of WifiManager.CHANGE_REASON_ADDED, 621a0842b40441db5332a5290f941021636b1182761Sol Boucher * WifiManager.CHANGE_REASON_REMOVED, or WifiManager.CHANGE_REASON_CHANGE. 622a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 623a0842b40441db5332a5290f941021636b1182761Sol Boucher private void sendConfiguredNetworkChangedBroadcast( 624a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration network, int reason) { 625a0842b40441db5332a5290f941021636b1182761Sol Boucher Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); 626a0842b40441db5332a5290f941021636b1182761Sol Boucher intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 627a0842b40441db5332a5290f941021636b1182761Sol Boucher intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, false); 628a0842b40441db5332a5290f941021636b1182761Sol Boucher // Create a new WifiConfiguration with passwords masked before we send it out. 629a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration broadcastNetwork = new WifiConfiguration(network); 630a0842b40441db5332a5290f941021636b1182761Sol Boucher maskPasswordsInWifiConfiguration(broadcastNetwork); 631a0842b40441db5332a5290f941021636b1182761Sol Boucher intent.putExtra(WifiManager.EXTRA_WIFI_CONFIGURATION, broadcastNetwork); 632a0842b40441db5332a5290f941021636b1182761Sol Boucher intent.putExtra(WifiManager.EXTRA_CHANGE_REASON, reason); 633a0842b40441db5332a5290f941021636b1182761Sol Boucher mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 634a0842b40441db5332a5290f941021636b1182761Sol Boucher } 635de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 636de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher /** 637de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * Method to send out the configured networks change broadcast when multiple network 638de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * configurations are changed. 639de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 640de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private void sendConfiguredNetworksChangedBroadcast() { 641de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); 642a0842b40441db5332a5290f941021636b1182761Sol Boucher intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 643a0842b40441db5332a5290f941021636b1182761Sol Boucher intent.putExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED, true); 644a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 645a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 646a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 647a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 648a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Checks if |uid| has permission to modify the provided configuration. 649a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * 650a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param config WifiConfiguration object corresponding to the network to be modified. 651a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param uid UID of the app requesting the modification. 652a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param ignoreLockdown Ignore the configuration lockdown checks for connection attempts. 653de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 654a0842b40441db5332a5290f941021636b1182761Sol Boucher private boolean canModifyNetwork(WifiConfiguration config, int uid, boolean ignoreLockdown) { 655de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // System internals can always update networks; they're typically only 656de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // making meteredHint or meteredOverride changes 657a0842b40441db5332a5290f941021636b1182761Sol Boucher if (uid == Process.SYSTEM_UID) { 658a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 659a0842b40441db5332a5290f941021636b1182761Sol Boucher } 660a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 661a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Passpoint configurations are generated and managed by PasspointManager. They can be 662a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // added by either PasspointNetworkEvaluator (for auto connection) or Settings app 663de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // (for manual connection), and need to be removed once the connection is completed. 664de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Since it is "owned" by us, so always allow us to modify them. 665de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (config.isPasspoint() && uid == Process.WIFI_UID) { 666bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala return true; 667a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 668a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 669a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // EAP-SIM/AKA/AKA' network needs framework to update the anonymous identity provided 670a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // by authenticator back to the WifiConfiguration object. 671a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Since it is "owned" by us, so always allow us to modify them. 672984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (config.enterpriseConfig != null 673a0842b40441db5332a5290f941021636b1182761Sol Boucher && uid == Process.WIFI_UID 674a0842b40441db5332a5290f941021636b1182761Sol Boucher && TelephonyUtil.isSimEapMethod(config.enterpriseConfig.getEapMethod())) { 675a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 676a0842b40441db5332a5290f941021636b1182761Sol Boucher } 677a0842b40441db5332a5290f941021636b1182761Sol Boucher 678a0842b40441db5332a5290f941021636b1182761Sol Boucher final DevicePolicyManagerInternal dpmi = LocalServices.getService( 679a0842b40441db5332a5290f941021636b1182761Sol Boucher DevicePolicyManagerInternal.class); 680a0842b40441db5332a5290f941021636b1182761Sol Boucher 681a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid, 682a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); 683a0842b40441db5332a5290f941021636b1182761Sol Boucher 684a0842b40441db5332a5290f941021636b1182761Sol Boucher // If |uid| corresponds to the device owner, allow all modifications. 685a0842b40441db5332a5290f941021636b1182761Sol Boucher if (isUidDeviceOwner) { 686a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 687a0842b40441db5332a5290f941021636b1182761Sol Boucher } 688a0842b40441db5332a5290f941021636b1182761Sol Boucher 689a0842b40441db5332a5290f941021636b1182761Sol Boucher final boolean isCreator = (config.creatorUid == uid); 690a0842b40441db5332a5290f941021636b1182761Sol Boucher 691a0842b40441db5332a5290f941021636b1182761Sol Boucher // Check if the |uid| holds the |NETWORK_SETTINGS| permission if the caller asks us to 692a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // bypass the lockdown checks. 693a0842b40441db5332a5290f941021636b1182761Sol Boucher if (ignoreLockdown) { 694a0842b40441db5332a5290f941021636b1182761Sol Boucher return mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); 695a0842b40441db5332a5290f941021636b1182761Sol Boucher } 696a0842b40441db5332a5290f941021636b1182761Sol Boucher 697a0842b40441db5332a5290f941021636b1182761Sol Boucher // Check if device has DPM capability. If it has and |dpmi| is still null, then we 698a0842b40441db5332a5290f941021636b1182761Sol Boucher // treat this case with suspicion and bail out. 699a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN) 700a0842b40441db5332a5290f941021636b1182761Sol Boucher && dpmi == null) { 701a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.w(TAG, "Error retrieving DPMI service."); 702a0842b40441db5332a5290f941021636b1182761Sol Boucher return false; 703de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 704de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 705de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // WiFi config lockdown related logic. At this point we know uid is NOT a Device Owner. 706de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher final boolean isConfigEligibleForLockdown = dpmi != null && dpmi.isActiveAdminWithPolicy( 707de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher config.creatorUid, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); 708de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!isConfigEligibleForLockdown) { 709a0842b40441db5332a5290f941021636b1182761Sol Boucher return isCreator || mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); 710a0842b40441db5332a5290f941021636b1182761Sol Boucher } 711de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 712de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher final ContentResolver resolver = mContext.getContentResolver(); 713bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala final boolean isLockdownFeatureEnabled = Settings.Global.getInt(resolver, 714a0842b40441db5332a5290f941021636b1182761Sol Boucher Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) != 0; 715a0842b40441db5332a5290f941021636b1182761Sol Boucher return !isLockdownFeatureEnabled 716a0842b40441db5332a5290f941021636b1182761Sol Boucher && mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); 717a0842b40441db5332a5290f941021636b1182761Sol Boucher } 718a0842b40441db5332a5290f941021636b1182761Sol Boucher 719a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 720a0842b40441db5332a5290f941021636b1182761Sol Boucher * Check if the given UID belongs to the current foreground user. This is 721a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * used to prevent apps running in background users from modifying network 722a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * configurations. 723a0842b40441db5332a5290f941021636b1182761Sol Boucher * <p> 724a0842b40441db5332a5290f941021636b1182761Sol Boucher * UIDs belonging to system internals (such as SystemUI) are always allowed, 725a0842b40441db5332a5290f941021636b1182761Sol Boucher * since they always run as {@link UserHandle#USER_SYSTEM}. 726984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 727984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param uid uid of the app. 728984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @return true if the given UID belongs to the current foreground user, 729984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * otherwise false. 730984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 731984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private boolean doesUidBelongToCurrentUser(int uid) { 732984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (uid == android.os.Process.SYSTEM_UID || uid == mSystemUiUid) { 733984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return true; 734bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala } else { 735984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher return WifiConfigurationUtil.doesUidBelongToAnyProfile( 736984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher uid, mUserManager.getProfiles(mCurrentUserId)); 737a0842b40441db5332a5290f941021636b1182761Sol Boucher } 738a0842b40441db5332a5290f941021636b1182761Sol Boucher } 739bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala 740bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala /** 741bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala * Copy over public elements from an external WifiConfiguration object to the internal 742a0842b40441db5332a5290f941021636b1182761Sol Boucher * configuration object if element has been set in the provided external WifiConfiguration. 743a0842b40441db5332a5290f941021636b1182761Sol Boucher * The only exception is the hidden |IpConfiguration| parameters, these need to be copied over 744a0842b40441db5332a5290f941021636b1182761Sol Boucher * for every update. 745a0842b40441db5332a5290f941021636b1182761Sol Boucher * 746a0842b40441db5332a5290f941021636b1182761Sol Boucher * This method updates all elements that are common to both network addition & update. 747a0842b40441db5332a5290f941021636b1182761Sol Boucher * The following fields of {@link WifiConfiguration} are not copied from external configs: 748a0842b40441db5332a5290f941021636b1182761Sol Boucher * > networkId - These are allocated by Wi-Fi stack internally for any new configurations. 749a0842b40441db5332a5290f941021636b1182761Sol Boucher * > status - The status needs to be explicitly updated using 750a0842b40441db5332a5290f941021636b1182761Sol Boucher * {@link WifiManager#enableNetwork(int, boolean)} or 751de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * {@link WifiManager#disableNetwork(int)}. 752a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * 753a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param internalConfig WifiConfiguration object in our internal map. 754de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param externalConfig WifiConfiguration object provided from the external API. 755de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 756de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher private void mergeWithInternalWifiConfiguration( 757984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher WifiConfiguration internalConfig, WifiConfiguration externalConfig) { 758a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.SSID != null) { 759a0842b40441db5332a5290f941021636b1182761Sol Boucher internalConfig.SSID = externalConfig.SSID; 760a0842b40441db5332a5290f941021636b1182761Sol Boucher } 761a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.BSSID != null) { 762a0842b40441db5332a5290f941021636b1182761Sol Boucher internalConfig.BSSID = externalConfig.BSSID.toLowerCase(); 763a0842b40441db5332a5290f941021636b1182761Sol Boucher } 764a0842b40441db5332a5290f941021636b1182761Sol Boucher internalConfig.hiddenSSID = externalConfig.hiddenSSID; 765a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.preSharedKey != null 766a0842b40441db5332a5290f941021636b1182761Sol Boucher && !externalConfig.preSharedKey.equals(PASSWORD_MASK)) { 767a0842b40441db5332a5290f941021636b1182761Sol Boucher internalConfig.preSharedKey = externalConfig.preSharedKey; 768a0842b40441db5332a5290f941021636b1182761Sol Boucher } 769a0842b40441db5332a5290f941021636b1182761Sol Boucher // Modify only wep keys are present in the provided configuration. This is a little tricky 770a0842b40441db5332a5290f941021636b1182761Sol Boucher // because there is no easy way to tell if the app is actually trying to null out the 771a0842b40441db5332a5290f941021636b1182761Sol Boucher // existing keys or not. 772a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.wepKeys != null) { 773a0842b40441db5332a5290f941021636b1182761Sol Boucher boolean hasWepKey = false; 774a0842b40441db5332a5290f941021636b1182761Sol Boucher for (int i = 0; i < internalConfig.wepKeys.length; i++) { 775a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.wepKeys[i] != null 776a0842b40441db5332a5290f941021636b1182761Sol Boucher && !externalConfig.wepKeys[i].equals(PASSWORD_MASK)) { 777a0842b40441db5332a5290f941021636b1182761Sol Boucher internalConfig.wepKeys[i] = externalConfig.wepKeys[i]; 778a0842b40441db5332a5290f941021636b1182761Sol Boucher hasWepKey = true; 779a0842b40441db5332a5290f941021636b1182761Sol Boucher } 780a0842b40441db5332a5290f941021636b1182761Sol Boucher } 781bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala if (hasWepKey) { 782bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala internalConfig.wepTxKeyIndex = externalConfig.wepTxKeyIndex; 783bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala } 784a0842b40441db5332a5290f941021636b1182761Sol Boucher } 785a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.FQDN != null) { 786a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher internalConfig.FQDN = externalConfig.FQDN; 787984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 788a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.providerFriendlyName != null) { 789a0842b40441db5332a5290f941021636b1182761Sol Boucher internalConfig.providerFriendlyName = externalConfig.providerFriendlyName; 790a0842b40441db5332a5290f941021636b1182761Sol Boucher } 791a0842b40441db5332a5290f941021636b1182761Sol Boucher if (externalConfig.roamingConsortiumIds != null) { 792a0842b40441db5332a5290f941021636b1182761Sol Boucher internalConfig.roamingConsortiumIds = externalConfig.roamingConsortiumIds.clone(); 793a0842b40441db5332a5290f941021636b1182761Sol Boucher } 794a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 795a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Copy over all the auth/protocol/key mgmt parameters if set. 796a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (externalConfig.allowedAuthAlgorithms != null 797a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher && !externalConfig.allowedAuthAlgorithms.isEmpty()) { 798a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher internalConfig.allowedAuthAlgorithms = 799a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher (BitSet) externalConfig.allowedAuthAlgorithms.clone(); 800a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 801a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (externalConfig.allowedProtocols != null 802a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher && !externalConfig.allowedProtocols.isEmpty()) { 803a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher internalConfig.allowedProtocols = (BitSet) externalConfig.allowedProtocols.clone(); 804a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 805bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala if (externalConfig.allowedKeyManagement != null 806bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala && !externalConfig.allowedKeyManagement.isEmpty()) { 807984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher internalConfig.allowedKeyManagement = 808984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher (BitSet) externalConfig.allowedKeyManagement.clone(); 809984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 810984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (externalConfig.allowedPairwiseCiphers != null 811984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher && !externalConfig.allowedPairwiseCiphers.isEmpty()) { 812bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala internalConfig.allowedPairwiseCiphers = 813bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala (BitSet) externalConfig.allowedPairwiseCiphers.clone(); 814bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala } 815a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (externalConfig.allowedGroupCiphers != null 816984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher && !externalConfig.allowedGroupCiphers.isEmpty()) { 817984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher internalConfig.allowedGroupCiphers = 818984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher (BitSet) externalConfig.allowedGroupCiphers.clone(); 819984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 820984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 821984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Copy over the |IpConfiguration| parameters if set. 822984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (externalConfig.getIpConfiguration() != null) { 823984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher IpConfiguration.IpAssignment ipAssignment = externalConfig.getIpAssignment(); 824a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (ipAssignment != IpConfiguration.IpAssignment.UNASSIGNED) { 825a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher internalConfig.setIpAssignment(ipAssignment); 826a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (ipAssignment == IpConfiguration.IpAssignment.STATIC) { 827a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher internalConfig.setStaticIpConfiguration( 828984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher new StaticIpConfiguration(externalConfig.getStaticIpConfiguration())); 829984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 830984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 831984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher IpConfiguration.ProxySettings proxySettings = externalConfig.getProxySettings(); 832984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher if (proxySettings != IpConfiguration.ProxySettings.UNASSIGNED) { 833a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher internalConfig.setProxySettings(proxySettings); 834a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (proxySettings == IpConfiguration.ProxySettings.PAC 835a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher || proxySettings == IpConfiguration.ProxySettings.STATIC) { 836984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher internalConfig.setHttpProxy(new ProxyInfo(externalConfig.getHttpProxy())); 837984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 838984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 839984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 840984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 841984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Copy over the |WifiEnterpriseConfig| parameters if set. 842a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (externalConfig.enterpriseConfig != null) { 843984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher internalConfig.enterpriseConfig.copyFromExternal( 844984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher externalConfig.enterpriseConfig, PASSWORD_MASK); 845984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 846984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 847984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Copy over any metered information. 848984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher internalConfig.meteredHint = externalConfig.meteredHint; 849984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher internalConfig.meteredOverride = externalConfig.meteredOverride; 850984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 851984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 852984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 853984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Set all the exposed defaults in the newly created WifiConfiguration object. 854984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * These fields have a default value advertised in our public documentation. The only exception 855984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * is the hidden |IpConfiguration| parameters, these have a default value even though they're 856984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * hidden. 857a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * 858a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @param configuration provided WifiConfiguration object. 859984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 860984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private void setDefaultsInWifiConfiguration(WifiConfiguration configuration) { 8617d71703202c2fba36653293eba2772745db46c00Sol Boucher configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); 8627d71703202c2fba36653293eba2772745db46c00Sol Boucher 8637d71703202c2fba36653293eba2772745db46c00Sol Boucher configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); 864984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher configuration.allowedProtocols.set(WifiConfiguration.Protocol.WPA); 865984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 866984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); 867984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); 868984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 869984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); 870984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP); 871984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 872984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); 873984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); 874a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40); 875a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104); 876a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 877a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher configuration.setIpAssignment(IpConfiguration.IpAssignment.DHCP); 878de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher configuration.setProxySettings(IpConfiguration.ProxySettings.NONE); 879de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 880de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher configuration.status = WifiConfiguration.Status.DISABLED; 881de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher configuration.getNetworkSelectionStatus().setNetworkSelectionStatus( 882984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); 883984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher } 884984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 885984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 8867d71703202c2fba36653293eba2772745db46c00Sol Boucher * Create a new internal WifiConfiguration object by copying over parameters from the provided 887984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * external configuration and set defaults for the appropriate parameters. 888984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 889984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param externalConfig WifiConfiguration object provided from the external API. 890984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @return New WifiConfiguration object with parameters merged from the provided external 891984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * configuration. 892984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher */ 893984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher private WifiConfiguration createNewInternalWifiConfigurationFromExternal( 8947d71703202c2fba36653293eba2772745db46c00Sol Boucher WifiConfiguration externalConfig, int uid) { 8957d71703202c2fba36653293eba2772745db46c00Sol Boucher WifiConfiguration newInternalConfig = new WifiConfiguration(); 8967d71703202c2fba36653293eba2772745db46c00Sol Boucher 897984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // First allocate a new network ID for the configuration. 898984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher newInternalConfig.networkId = mNextNetworkId++; 899984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 900984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // First set defaults in the new configuration created. 901de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher setDefaultsInWifiConfiguration(newInternalConfig); 902de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher 903984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Copy over all the public elements from the provided configuration. 904984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher mergeWithInternalWifiConfiguration(newInternalConfig, externalConfig); 905984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 906984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // Copy over the hidden configuration parameters. These are the only parameters used by 907984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher // system apps to indicate some property about the network being added. 908bb013aa3e197e881756be5ad13e6ad30bfb4aeffEino-Ville Talvala // These are only copied over for network additions and ignored for network updates. 909984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher newInternalConfig.requirePMF = externalConfig.requirePMF; 910984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher newInternalConfig.noInternetAccessExpected = externalConfig.noInternetAccessExpected; 911984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher newInternalConfig.ephemeral = externalConfig.ephemeral; 912984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher newInternalConfig.useExternalScores = externalConfig.useExternalScores; 913984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher newInternalConfig.shared = externalConfig.shared; 914984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 915de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Add debug information for network addition. 916984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher newInternalConfig.creatorUid = newInternalConfig.lastUpdateUid = uid; 917de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher newInternalConfig.creatorName = newInternalConfig.lastUpdateName = 918de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mContext.getPackageManager().getNameForUid(uid); 919de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher newInternalConfig.creationTime = newInternalConfig.updateTime = 920de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher createDebugTimeStampString(mClock.getWallClockMillis()); 921a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 922a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher return newInternalConfig; 923a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 924984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher 925984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher /** 926984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * Create a new internal WifiConfiguration object by copying over parameters from the provided 927984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * external configuration to a copy of the existing internal WifiConfiguration object. 928984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * 929984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param internalConfig WifiConfiguration object in our internal map. 930984a086412a94ebea1bd9af8cd8bbf4afab38034Sol Boucher * @param externalConfig WifiConfiguration object provided from the external API. 931a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * @return Copy of existing WifiConfiguration object with parameters merged from the provided 932a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * configuration. 933a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher */ 934a0842b40441db5332a5290f941021636b1182761Sol Boucher private WifiConfiguration updateExistingInternalWifiConfigurationFromExternal( 935a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration internalConfig, WifiConfiguration externalConfig, int uid) { 936a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration newInternalConfig = new WifiConfiguration(internalConfig); 937a0842b40441db5332a5290f941021636b1182761Sol Boucher 938a0842b40441db5332a5290f941021636b1182761Sol Boucher // Copy over all the public elements from the provided configuration. 939a0842b40441db5332a5290f941021636b1182761Sol Boucher mergeWithInternalWifiConfiguration(newInternalConfig, externalConfig); 940a0842b40441db5332a5290f941021636b1182761Sol Boucher 941a0842b40441db5332a5290f941021636b1182761Sol Boucher // Add debug information for network update. 94280cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher newInternalConfig.lastUpdateUid = uid; 943415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher newInternalConfig.lastUpdateName = mContext.getPackageManager().getNameForUid(uid); 944a0842b40441db5332a5290f941021636b1182761Sol Boucher newInternalConfig.updateTime = createDebugTimeStampString(mClock.getWallClockMillis()); 945a0842b40441db5332a5290f941021636b1182761Sol Boucher 946a0842b40441db5332a5290f941021636b1182761Sol Boucher return newInternalConfig; 947a0842b40441db5332a5290f941021636b1182761Sol Boucher } 948a0842b40441db5332a5290f941021636b1182761Sol Boucher 949a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 950a0842b40441db5332a5290f941021636b1182761Sol Boucher * Add a network or update a network configuration to our database. 951a0842b40441db5332a5290f941021636b1182761Sol Boucher * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty 95280cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher * network configuration. Otherwise, the networkId should refer to an existing configuration. 953415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher * 954a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param config provided WifiConfiguration object. 955a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param uid UID of the app requesting the network addition/deletion. 956a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return NetworkUpdateResult object representing status of the update. 957a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 958a0842b40441db5332a5290f941021636b1182761Sol Boucher private NetworkUpdateResult addOrUpdateNetworkInternal(WifiConfiguration config, int uid) { 959a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mVerboseLoggingEnabled) { 960a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.v(TAG, "Adding/Updating network " + config.getPrintableSsid()); 961a0842b40441db5332a5290f941021636b1182761Sol Boucher } 962a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration newInternalConfig = null; 963a0842b40441db5332a5290f941021636b1182761Sol Boucher 964a0842b40441db5332a5290f941021636b1182761Sol Boucher // First check if we already have a network with the provided network id or configKey. 965a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration existingInternalConfig = getInternalConfiguredNetwork(config); 966a0842b40441db5332a5290f941021636b1182761Sol Boucher // No existing network found. So, potentially a network add. 967a0842b40441db5332a5290f941021636b1182761Sol Boucher if (existingInternalConfig == null) { 968a0842b40441db5332a5290f941021636b1182761Sol Boucher if (!WifiConfigurationUtil.validate(config, WifiConfigurationUtil.VALIDATE_FOR_ADD)) { 969a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "Cannot add network with invalid config"); 970a0842b40441db5332a5290f941021636b1182761Sol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 971a0842b40441db5332a5290f941021636b1182761Sol Boucher } 972a0842b40441db5332a5290f941021636b1182761Sol Boucher newInternalConfig = createNewInternalWifiConfigurationFromExternal(config, uid); 973a0842b40441db5332a5290f941021636b1182761Sol Boucher // Since the original config provided may have had an empty 974a0842b40441db5332a5290f941021636b1182761Sol Boucher // {@link WifiConfiguration#allowedKeyMgmt} field, check again if we already have a 975a0842b40441db5332a5290f941021636b1182761Sol Boucher // network with the the same configkey. 976a0842b40441db5332a5290f941021636b1182761Sol Boucher existingInternalConfig = getInternalConfiguredNetwork(newInternalConfig.configKey()); 977a0842b40441db5332a5290f941021636b1182761Sol Boucher } 978a0842b40441db5332a5290f941021636b1182761Sol Boucher // Existing network found. So, a network update. 9792569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher if (existingInternalConfig != null) { 9802569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher if (!WifiConfigurationUtil.validate( 9812569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher config, WifiConfigurationUtil.VALIDATE_FOR_UPDATE)) { 9822569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher Log.e(TAG, "Cannot update network with invalid config"); 9832569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 9842569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher } 9852569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // Check for the app's permission before we let it update this network. 9862569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher if (!canModifyNetwork(existingInternalConfig, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) { 9872569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher Log.e(TAG, "UID " + uid + " does not have permission to update configuration " 9882569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher + config.configKey()); 9892569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 9902569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher } 9912569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher newInternalConfig = 9922569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher updateExistingInternalWifiConfigurationFromExternal( 9932569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher existingInternalConfig, config, uid); 9942569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher } 9952569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher 9962569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher // Only add networks with proxy settings if the user has permission to 9972569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher if (WifiConfigurationUtil.hasProxyChanged(existingInternalConfig, newInternalConfig) 9982569329d6cff25bfe9941df539df14a0aeb4c4f4Sol Boucher && !canModifyProxySettings(uid)) { 999a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "UID " + uid + " does not have permission to modify proxy Settings " 1000a0842b40441db5332a5290f941021636b1182761Sol Boucher + config.configKey() + ". Must have NETWORK_SETTINGS," 1001a0842b40441db5332a5290f941021636b1182761Sol Boucher + " or be device or profile owner."); 1002a0842b40441db5332a5290f941021636b1182761Sol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 1003a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1004a0842b40441db5332a5290f941021636b1182761Sol Boucher 1005a0842b40441db5332a5290f941021636b1182761Sol Boucher // Update the keys for non-Passpoint enterprise networks. For Passpoint, the certificates 1006a0842b40441db5332a5290f941021636b1182761Sol Boucher // and keys are installed at the time the provider is installed. 1007a0842b40441db5332a5290f941021636b1182761Sol Boucher if (config.enterpriseConfig != null 1008a0842b40441db5332a5290f941021636b1182761Sol Boucher && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE 1009a0842b40441db5332a5290f941021636b1182761Sol Boucher && !config.isPasspoint()) { 1010a0842b40441db5332a5290f941021636b1182761Sol Boucher if (!(mWifiKeyStore.updateNetworkKeys(newInternalConfig, existingInternalConfig))) { 1011a0842b40441db5332a5290f941021636b1182761Sol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 101250f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher } 101350f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher } 101450f5b019ba3f333a09a1beb9667fd7290082dc31Sol Boucher 1015a0842b40441db5332a5290f941021636b1182761Sol Boucher boolean newNetwork = (existingInternalConfig == null); 1016a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // This is needed to inform IpManager about any IP configuration changes. 1017a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher boolean hasIpChanged = 1018a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher newNetwork || WifiConfigurationUtil.hasIpChanged( 1019a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher existingInternalConfig, newInternalConfig); 1020a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher boolean hasProxyChanged = 1021a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher newNetwork || WifiConfigurationUtil.hasProxyChanged( 1022a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher existingInternalConfig, newInternalConfig); 1023a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Reset the |hasEverConnected| flag if the credential parameters changed in this update. 1024a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher boolean hasCredentialChanged = 1025a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher newNetwork || WifiConfigurationUtil.hasCredentialChanged( 1026a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher existingInternalConfig, newInternalConfig); 1027a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher if (hasCredentialChanged) { 1028a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher newInternalConfig.getNetworkSelectionStatus().setHasEverConnected(false); 1029a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1030a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1031a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Add it to our internal map. This will replace any existing network configuration for 1032a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // updates. 1033a0842b40441db5332a5290f941021636b1182761Sol Boucher try { 1034a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mConfiguredNetworks.put(newInternalConfig); 1035a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } catch (IllegalArgumentException e) { 1036a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher Log.e(TAG, "Failed to add network to config map", e); 1037a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 1038a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1039a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1040a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mDeletedEphemeralSSIDs.remove(config.SSID)) { 1041a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mVerboseLoggingEnabled) { 1042a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.v(TAG, "Removed from ephemeral blacklist: " + config.SSID); 1043a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1044a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1045a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1046a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher // Stage the backup of the SettingsProvider package which backs this up. 1047a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mBackupManagerProxy.notifyDataChanged(); 1048a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1049a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher NetworkUpdateResult result = 1050a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher new NetworkUpdateResult(hasIpChanged, hasProxyChanged, hasCredentialChanged); 1051a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher result.setIsNewNetwork(newNetwork); 1052a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher result.setNetworkId(newInternalConfig.networkId); 1053a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1054a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher localLog("addOrUpdateNetworkInternal: added/updated config." 1055a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher + " netId=" + newInternalConfig.networkId 1056a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher + " configKey=" + newInternalConfig.configKey() 1057a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher + " uid=" + Integer.toString(newInternalConfig.creatorUid) 1058a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher + " name=" + newInternalConfig.creatorName); 1059a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher return result; 1060a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1061a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1062a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher /** 1063a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * Add a network or update a network configuration to our database. 1064a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty 1065a0842b40441db5332a5290f941021636b1182761Sol Boucher * network configuration. Otherwise, the networkId should refer to an existing configuration. 1066a0842b40441db5332a5290f941021636b1182761Sol Boucher * 1067de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param config provided WifiConfiguration object. 1068de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param uid UID of the app requesting the network addition/modification. 1069a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return NetworkUpdateResult object representing status of the update. 1070a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1071de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher public NetworkUpdateResult addOrUpdateNetwork(WifiConfiguration config, int uid) { 1072de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!doesUidBelongToCurrentUser(uid)) { 1073de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "UID " + uid + " not visible to the current user"); 1074de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 1075de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1076de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (config == null) { 1077171362f843c1e7623f29db1781176f85b1f74815Eino-Ville Talvala Log.e(TAG, "Cannot add/update network with null config"); 1078de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 1079de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1080de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (mPendingStoreRead) { 1081de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Cannot add/update network before store is read!"); 1082415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher return new NetworkUpdateResult(WifiConfiguration.INVALID_NETWORK_ID); 1083415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher } 1084415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher NetworkUpdateResult result = addOrUpdateNetworkInternal(config, uid); 1085de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!result.isSuccess()) { 1086de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Failed to add/update network " + config.getPrintableSsid()); 1087de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return result; 1088de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1089a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration newConfig = getInternalConfiguredNetwork(result.getNetworkId()); 1090de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher sendConfiguredNetworkChangedBroadcast( 1091de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher newConfig, 1092de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher result.isNewNetwork() 1093de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher ? WifiManager.CHANGE_REASON_ADDED 1094de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher : WifiManager.CHANGE_REASON_CONFIG_CHANGE); 1095de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher // Unless the added network is ephemeral or Passpoint, persist the network update/addition. 1096de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!config.ephemeral && !config.isPasspoint()) { 1097de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher saveToStore(true); 1098de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (mListener != null) { 1099de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (result.isNewNetwork()) { 1100de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mListener.onSavedNetworkAdded(newConfig.networkId); 1101de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } else { 1102de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher mListener.onSavedNetworkUpdated(newConfig.networkId); 1103de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1104de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1105de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1106de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return result; 1107de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1108772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher 1109772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher /** 1110772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher * Removes the specified network configuration from our database. 1111de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * 1112de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @param config provided WifiConfiguration object. 1113de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher * @return true if successful, false otherwise. 1114de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher */ 1115a0842b40441db5332a5290f941021636b1182761Sol Boucher private boolean removeNetworkInternal(WifiConfiguration config) { 1116a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mVerboseLoggingEnabled) { 1117a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.v(TAG, "Removing network " + config.getPrintableSsid()); 1118a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1119a0842b40441db5332a5290f941021636b1182761Sol Boucher // Remove any associated enterprise keys for non-Passpoint networks. 1120a0842b40441db5332a5290f941021636b1182761Sol Boucher if (!config.isPasspoint() && config.enterpriseConfig != null 1121a0842b40441db5332a5290f941021636b1182761Sol Boucher && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) { 1122a0842b40441db5332a5290f941021636b1182761Sol Boucher mWifiKeyStore.removeKeys(config.enterpriseConfig); 1123a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1124a0842b40441db5332a5290f941021636b1182761Sol Boucher 1125a0842b40441db5332a5290f941021636b1182761Sol Boucher removeConnectChoiceFromAllNetworks(config.configKey()); 1126a0842b40441db5332a5290f941021636b1182761Sol Boucher mConfiguredNetworks.remove(config.networkId); 1127a0842b40441db5332a5290f941021636b1182761Sol Boucher mScanDetailCaches.remove(config.networkId); 1128a0842b40441db5332a5290f941021636b1182761Sol Boucher // Stage the backup of the SettingsProvider package which backs this up. 1129a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher mBackupManagerProxy.notifyDataChanged(); 1130a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher 1131a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher localLog("removeNetworkInternal: removed config." 1132a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher + " netId=" + config.networkId 1133a0842b40441db5332a5290f941021636b1182761Sol Boucher + " configKey=" + config.configKey()); 1134a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 1135a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1136a0842b40441db5332a5290f941021636b1182761Sol Boucher 1137a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 1138a0842b40441db5332a5290f941021636b1182761Sol Boucher * Removes the specified network configuration from our database. 1139a0842b40441db5332a5290f941021636b1182761Sol Boucher * 1140a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param networkId network ID of the provided network. 1141a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param uid UID of the app requesting the network deletion. 1142a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return true if successful, false otherwise. 1143a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1144a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean removeNetwork(int networkId, int uid) { 1145a0842b40441db5332a5290f941021636b1182761Sol Boucher if (!doesUidBelongToCurrentUser(uid)) { 1146a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "UID " + uid + " not visible to the current user"); 114780cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher return false; 114880cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher } 114980cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher WifiConfiguration config = getInternalConfiguredNetwork(networkId); 115080cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher if (config == null) { 1151a0842b40441db5332a5290f941021636b1182761Sol Boucher return false; 1152a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1153a0842b40441db5332a5290f941021636b1182761Sol Boucher if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) { 1154a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.e(TAG, "UID " + uid + " does not have permission to delete configuration " 1155de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher + config.configKey()); 1156de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return false; 1157de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1158de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (!removeNetworkInternal(config)) { 1159de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher Log.e(TAG, "Failed to remove network " + config.getPrintableSsid()); 1160de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher return false; 1161de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher } 1162de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher if (networkId == mLastSelectedNetworkId) { 1163de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher clearLastSelectedNetwork(); 1164772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher } 1165772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher sendConfiguredNetworkChangedBroadcast(config, WifiManager.CHANGE_REASON_REMOVED); 116680cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher // Unless the removed network is ephemeral or Passpoint, persist the network removal. 116780cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher if (!config.ephemeral && !config.isPasspoint()) { 116880cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher saveToStore(true); 116980cda8dae801f09c2ce928d0f3feb8a569939fc2Sol Boucher if (mListener != null) mListener.onSavedNetworkRemoved(networkId); 1170a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1171a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 1172415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher } 1173415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher 1174415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher /** 1175415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher * Remove all networks associated with an application. 1176415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher * 1177a0842b40441db5332a5290f941021636b1182761Sol Boucher * @param app Application info of the package of networks to remove. 1178a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return the {@link Set} of networks that were removed by this call. Networks which matched 1179a0842b40441db5332a5290f941021636b1182761Sol Boucher * but failed to remove are omitted from this set. 1180a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1181a0842b40441db5332a5290f941021636b1182761Sol Boucher public Set<Integer> removeNetworksForApp(ApplicationInfo app) { 1182a0842b40441db5332a5290f941021636b1182761Sol Boucher if (app == null || app.packageName == null) { 1183a0842b40441db5332a5290f941021636b1182761Sol Boucher return Collections.<Integer>emptySet(); 1184a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1185a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.d(TAG, "Remove all networks for app " + app); 1186a0842b40441db5332a5290f941021636b1182761Sol Boucher Set<Integer> removedNetworks = new ArraySet<>(); 1187a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration[] copiedConfigs = 1188a0842b40441db5332a5290f941021636b1182761Sol Boucher mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]); 1189a0842b40441db5332a5290f941021636b1182761Sol Boucher for (WifiConfiguration config : copiedConfigs) { 1190a0842b40441db5332a5290f941021636b1182761Sol Boucher if (app.uid != config.creatorUid || !app.packageName.equals(config.creatorName)) { 1191a0842b40441db5332a5290f941021636b1182761Sol Boucher continue; 1192a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1193a0842b40441db5332a5290f941021636b1182761Sol Boucher localLog("Removing network " + config.SSID 1194a0842b40441db5332a5290f941021636b1182761Sol Boucher + ", application \"" + app.packageName + "\" uninstalled" 1195a0842b40441db5332a5290f941021636b1182761Sol Boucher + " from user " + UserHandle.getUserId(app.uid)); 1196a0842b40441db5332a5290f941021636b1182761Sol Boucher if (removeNetwork(config.networkId, mSystemUiUid)) { 1197a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher removedNetworks.add(config.networkId); 1198a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1199a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher } 1200a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher return removedNetworks; 1201772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher } 1202772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher 1203772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher /** 1204a0842b40441db5332a5290f941021636b1182761Sol Boucher * Remove all networks associated with a user. 1205a0842b40441db5332a5290f941021636b1182761Sol Boucher * 1206772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher * @param userId The identifier of the user which is being removed. 1207a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return the {@link Set} of networks that were removed by this call. Networks which matched 1208772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher * but failed to remove are omitted from this set. 1209a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1210772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher Set<Integer> removeNetworksForUser(int userId) { 1211a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.d(TAG, "Remove all networks for user " + userId); 1212772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher Set<Integer> removedNetworks = new ArraySet<>(); 1213a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration[] copiedConfigs = 1214772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]); 1215a97b7d1192e246a5f738991adca37cce282e1382Sol Boucher for (WifiConfiguration config : copiedConfigs) { 1216772fcce3e51a9c7d33df6a9c278a908ac6902880Sol Boucher if (userId != UserHandle.getUserId(config.creatorUid)) { 1217a0842b40441db5332a5290f941021636b1182761Sol Boucher continue; 1218a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1219a0842b40441db5332a5290f941021636b1182761Sol Boucher localLog("Removing network " + config.SSID + ", user " + userId + " removed"); 1220a0842b40441db5332a5290f941021636b1182761Sol Boucher if (removeNetwork(config.networkId, mSystemUiUid)) { 1221a0842b40441db5332a5290f941021636b1182761Sol Boucher removedNetworks.add(config.networkId); 1222a0842b40441db5332a5290f941021636b1182761Sol Boucher } 12237e0d39bf7b6e0f0df606e3f6c15f673f70fed3f7Sol Boucher } 1224a0842b40441db5332a5290f941021636b1182761Sol Boucher return removedNetworks; 1225a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1226a0842b40441db5332a5290f941021636b1182761Sol Boucher 1227a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 1228a0842b40441db5332a5290f941021636b1182761Sol Boucher * Iterates through the internal list of configured networks and removes any ephemeral or 1229a0842b40441db5332a5290f941021636b1182761Sol Boucher * passpoint network configurations which are transient in nature. 1230a0842b40441db5332a5290f941021636b1182761Sol Boucher * 1231a0842b40441db5332a5290f941021636b1182761Sol Boucher * @return true if a network was removed, false otherwise. 1232a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1233a0842b40441db5332a5290f941021636b1182761Sol Boucher public boolean removeAllEphemeralOrPasspointConfiguredNetworks() { 1234a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mVerboseLoggingEnabled) { 1235a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.v(TAG, "Removing all passpoint or ephemeral configured networks"); 1236a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1237a0842b40441db5332a5290f941021636b1182761Sol Boucher boolean didRemove = false; 1238a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration[] copiedConfigs = 1239a0842b40441db5332a5290f941021636b1182761Sol Boucher mConfiguredNetworks.valuesForAllUsers().toArray(new WifiConfiguration[0]); 1240a0842b40441db5332a5290f941021636b1182761Sol Boucher for (WifiConfiguration config : copiedConfigs) { 1241a0842b40441db5332a5290f941021636b1182761Sol Boucher if (config.isPasspoint()) { 1242a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.d(TAG, "Removing passpoint network config " + config.configKey()); 1243a0842b40441db5332a5290f941021636b1182761Sol Boucher removeNetwork(config.networkId, mSystemUiUid); 1244a0842b40441db5332a5290f941021636b1182761Sol Boucher didRemove = true; 1245a0842b40441db5332a5290f941021636b1182761Sol Boucher } else if (config.ephemeral) { 1246a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.d(TAG, "Removing ephemeral network config " + config.configKey()); 1247a0842b40441db5332a5290f941021636b1182761Sol Boucher removeNetwork(config.networkId, mSystemUiUid); 1248a0842b40441db5332a5290f941021636b1182761Sol Boucher didRemove = true; 1249a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1250a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1251a0842b40441db5332a5290f941021636b1182761Sol Boucher return didRemove; 1252a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1253a0842b40441db5332a5290f941021636b1182761Sol Boucher 1254a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 1255a0842b40441db5332a5290f941021636b1182761Sol Boucher * Helper method to mark a network enabled for network selection. 1256a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1257a0842b40441db5332a5290f941021636b1182761Sol Boucher private void setNetworkSelectionEnabled(WifiConfiguration config) { 1258a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus status = config.getNetworkSelectionStatus(); 1259a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setNetworkSelectionStatus( 1260a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus.NETWORK_SELECTION_ENABLED); 1261a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setDisableTime( 1262a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); 1263a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setNetworkSelectionDisableReason(NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 1264a0842b40441db5332a5290f941021636b1182761Sol Boucher 1265a0842b40441db5332a5290f941021636b1182761Sol Boucher // Clear out all the disable reason counters. 1266a0842b40441db5332a5290f941021636b1182761Sol Boucher status.clearDisableReasonCounter(); 1267a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mListener != null) mListener.onSavedNetworkEnabled(config.networkId); 1268a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1269a0842b40441db5332a5290f941021636b1182761Sol Boucher 1270a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 1271a0842b40441db5332a5290f941021636b1182761Sol Boucher * Helper method to mark a network temporarily disabled for network selection. 1272a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1273a0842b40441db5332a5290f941021636b1182761Sol Boucher private void setNetworkSelectionTemporarilyDisabled( 1274a0842b40441db5332a5290f941021636b1182761Sol Boucher WifiConfiguration config, int disableReason) { 1275a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus status = config.getNetworkSelectionStatus(); 1276a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setNetworkSelectionStatus( 1277a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED); 1278a0842b40441db5332a5290f941021636b1182761Sol Boucher // Only need a valid time filled in for temporarily disabled networks. 1279a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setDisableTime(mClock.getElapsedSinceBootMillis()); 1280a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setNetworkSelectionDisableReason(disableReason); 1281a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mListener != null) mListener.onSavedNetworkTemporarilyDisabled(config.networkId); 1282a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1283a0842b40441db5332a5290f941021636b1182761Sol Boucher 1284a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 1285a0842b40441db5332a5290f941021636b1182761Sol Boucher * Helper method to mark a network permanently disabled for network selection. 1286a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1287a0842b40441db5332a5290f941021636b1182761Sol Boucher private void setNetworkSelectionPermanentlyDisabled( 1288de48004068f8c16f9a56c60b0ed2485a67687b4bSol Boucher WifiConfiguration config, int disableReason) { 1289a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus status = config.getNetworkSelectionStatus(); 1290a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setNetworkSelectionStatus( 1291a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED); 1292a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setDisableTime( 1293a0842b40441db5332a5290f941021636b1182761Sol Boucher NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); 1294a0842b40441db5332a5290f941021636b1182761Sol Boucher status.setNetworkSelectionDisableReason(disableReason); 1295a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mListener != null) mListener.onSavedNetworkPermanentlyDisabled(config.networkId); 1296a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1297a0842b40441db5332a5290f941021636b1182761Sol Boucher 1298a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 1299a0842b40441db5332a5290f941021636b1182761Sol Boucher * Helper method to set the publicly exposed status for the network and send out the network 1300a0842b40441db5332a5290f941021636b1182761Sol Boucher * status change broadcast. 1301a0842b40441db5332a5290f941021636b1182761Sol Boucher */ 1302a0842b40441db5332a5290f941021636b1182761Sol Boucher private void setNetworkStatus(WifiConfiguration config, int status) { 1303a0842b40441db5332a5290f941021636b1182761Sol Boucher config.status = status; 1304a0842b40441db5332a5290f941021636b1182761Sol Boucher sendConfiguredNetworkChangedBroadcast(config, WifiManager.CHANGE_REASON_CONFIG_CHANGE); 1305a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1306a0842b40441db5332a5290f941021636b1182761Sol Boucher 1307a0842b40441db5332a5290f941021636b1182761Sol Boucher /** 1308a0842b40441db5332a5290f941021636b1182761Sol Boucher * Sets a network's status (both internal and public) according to the update reason and 1309a0842b40441db5332a5290f941021636b1182761Sol Boucher * its current state. 1310a0842b40441db5332a5290f941021636b1182761Sol Boucher * 1311a0842b40441db5332a5290f941021636b1182761Sol Boucher * This updates the network's {@link WifiConfiguration#mNetworkSelectionStatus} field and the 1312a0842b40441db5332a5290f941021636b1182761Sol Boucher * public {@link WifiConfiguration#status} field if the network is either enabled or 1313f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * permanently disabled. 1314f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * 1315f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param config network to be updated. 1316f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param reason reason code for update. 1317f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @return true if the input configuration has been updated, false otherwise. 1318f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher */ 1319f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher private boolean setNetworkSelectionStatus(WifiConfiguration config, int reason) { 1320f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus(); 1321f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (reason < 0 || reason >= NetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX) { 1322f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher Log.e(TAG, "Invalid Network disable reason " + reason); 1323f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return false; 1324f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1325f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (reason == NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) { 1326f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher setNetworkSelectionEnabled(config); 1327f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher setNetworkStatus(config, WifiConfiguration.Status.ENABLED); 1328f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } else if (reason < NetworkSelectionStatus.DISABLED_TLS_VERSION_MISMATCH) { 1329f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher setNetworkSelectionTemporarilyDisabled(config, reason); 1330f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } else { 1331f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher setNetworkSelectionPermanentlyDisabled(config, reason); 1332f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher setNetworkStatus(config, WifiConfiguration.Status.DISABLED); 1333f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1334f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher localLog("setNetworkSelectionStatus: configKey=" + config.configKey() 1335f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher + " networkStatus=" + networkStatus.getNetworkStatusString() + " disableReason=" 1336a0842b40441db5332a5290f941021636b1182761Sol Boucher + networkStatus.getNetworkDisableReasonString() + " at=" 1337415cf3ee18640ad0799e5c9a738afd1d19c14883Sol Boucher + createDebugTimeStampString(mClock.getWallClockMillis())); 1338a0842b40441db5332a5290f941021636b1182761Sol Boucher saveToStore(false); 1339f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher return true; 1340f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher } 1341f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher 1342f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher /** 1343f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * Update a network's status (both internal and public) according to the update reason and 1344f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * its current state. 1345f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * 1346f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param config network to be updated. 1347f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @param reason reason code for update. 1348f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher * @return true if the input configuration has been updated, false otherwise. 1349f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher */ 1350f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher private boolean updateNetworkSelectionStatus(WifiConfiguration config, int reason) { 1351f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus(); 1352f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher if (reason != NetworkSelectionStatus.NETWORK_SELECTION_ENABLE) { 1353f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher networkStatus.incrementDisableReasonCounter(reason); 1354f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // For network disable reasons, we should only update the status if we cross the 1355f9feab9a826e5b33d811e757bdfdbfa0738fcfa5Sol Boucher // threshold. 1356a0842b40441db5332a5290f941021636b1182761Sol Boucher int disableReasonCounter = networkStatus.getDisableReasonCounter(reason); 1357a0842b40441db5332a5290f941021636b1182761Sol Boucher int disableReasonThreshold = NETWORK_SELECTION_DISABLE_THRESHOLD[reason]; 1358a0842b40441db5332a5290f941021636b1182761Sol Boucher if (disableReasonCounter < disableReasonThreshold) { 1359a0842b40441db5332a5290f941021636b1182761Sol Boucher if (mVerboseLoggingEnabled) { 1360a0842b40441db5332a5290f941021636b1182761Sol Boucher Log.v(TAG, "Disable counter for network " + config.getPrintableSsid() 1361a0842b40441db5332a5290f941021636b1182761Sol Boucher + " for reason " 1362a0842b40441db5332a5290f941021636b1182761Sol Boucher + NetworkSelectionStatus.getNetworkDisableReasonString(reason) + " is " 1363a0842b40441db5332a5290f941021636b1182761Sol Boucher + networkStatus.getDisableReasonCounter(reason) + " and threshold is " 1364a0842b40441db5332a5290f941021636b1182761Sol Boucher + disableReasonThreshold); 1365a0842b40441db5332a5290f941021636b1182761Sol Boucher } 1366a0842b40441db5332a5290f941021636b1182761Sol Boucher return true; 1367 } 1368 } 1369 return setNetworkSelectionStatus(config, reason); 1370 } 1371 1372 /** 1373 * Update a network's status (both internal and public) according to the update reason and 1374 * its current state. 1375 * 1376 * Each network has 2 status: 1377 * 1. NetworkSelectionStatus: This is internal selection status of the network. This is used 1378 * for temporarily disabling a network for Network Selector. 1379 * 2. Status: This is the exposed status for a network. This is mostly set by 1380 * the public API's {@link WifiManager#enableNetwork(int, boolean)} & 1381 * {@link WifiManager#disableNetwork(int)}. 1382 * 1383 * @param networkId network ID of the network that needs the update. 1384 * @param reason reason to update the network. 1385 * @return true if the input configuration has been updated, false otherwise. 1386 */ 1387 public boolean updateNetworkSelectionStatus(int networkId, int reason) { 1388 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1389 if (config == null) { 1390 return false; 1391 } 1392 return updateNetworkSelectionStatus(config, reason); 1393 } 1394 1395 /** 1396 * Update whether a network is currently not recommended by {@link RecommendedNetworkEvaluator}. 1397 * 1398 * @param networkId network ID of the network to be updated 1399 * @param notRecommended whether this network is not recommended 1400 * @return true if the network is updated, false otherwise 1401 */ 1402 public boolean updateNetworkNotRecommended(int networkId, boolean notRecommended) { 1403 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1404 if (config == null) { 1405 return false; 1406 } 1407 1408 config.getNetworkSelectionStatus().setNotRecommended(notRecommended); 1409 if (mVerboseLoggingEnabled) { 1410 localLog("updateNetworkRecommendation: configKey=" + config.configKey() 1411 + " notRecommended=" + notRecommended); 1412 } 1413 saveToStore(false); 1414 return true; 1415 } 1416 1417 /** 1418 * Attempt to re-enable a network for network selection, if this network was either: 1419 * a) Previously temporarily disabled, but its disable timeout has expired, or 1420 * b) Previously disabled because of a user switch, but is now visible to the current 1421 * user. 1422 * 1423 * @param config configuration for the network to be re-enabled for network selection. The 1424 * network corresponding to the config must be visible to the current user. 1425 * @return true if the network identified by {@param config} was re-enabled for qualified 1426 * network selection, false otherwise. 1427 */ 1428 private boolean tryEnableNetwork(WifiConfiguration config) { 1429 NetworkSelectionStatus networkStatus = config.getNetworkSelectionStatus(); 1430 if (networkStatus.isNetworkTemporaryDisabled()) { 1431 long timeDifferenceMs = 1432 mClock.getElapsedSinceBootMillis() - networkStatus.getDisableTime(); 1433 int disableReason = networkStatus.getNetworkSelectionDisableReason(); 1434 long disableTimeoutMs = NETWORK_SELECTION_DISABLE_TIMEOUT_MS[disableReason]; 1435 if (timeDifferenceMs >= disableTimeoutMs) { 1436 return updateNetworkSelectionStatus( 1437 config, NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 1438 } 1439 } else if (networkStatus.isDisabledByReason( 1440 NetworkSelectionStatus.DISABLED_DUE_TO_USER_SWITCH)) { 1441 return updateNetworkSelectionStatus( 1442 config, NetworkSelectionStatus.NETWORK_SELECTION_ENABLE); 1443 } 1444 return false; 1445 } 1446 1447 /** 1448 * Attempt to re-enable a network for network selection, if this network was either: 1449 * a) Previously temporarily disabled, but its disable timeout has expired, or 1450 * b) Previously disabled because of a user switch, but is now visible to the current 1451 * user. 1452 * 1453 * @param networkId the id of the network to be checked for possible unblock (due to timeout) 1454 * @return true if the network identified by {@param networkId} was re-enabled for qualified 1455 * network selection, false otherwise. 1456 */ 1457 public boolean tryEnableNetwork(int networkId) { 1458 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1459 if (config == null) { 1460 return false; 1461 } 1462 return tryEnableNetwork(config); 1463 } 1464 1465 /** 1466 * Enable a network using the public {@link WifiManager#enableNetwork(int, boolean)} API. 1467 * 1468 * @param networkId network ID of the network that needs the update. 1469 * @param disableOthers Whether to disable all other networks or not. This is used to indicate 1470 * that the app requested connection to a specific network. 1471 * @param uid uid of the app requesting the update. 1472 * @return true if it succeeds, false otherwise 1473 */ 1474 public boolean enableNetwork(int networkId, boolean disableOthers, int uid) { 1475 if (mVerboseLoggingEnabled) { 1476 Log.v(TAG, "Enabling network " + networkId + " (disableOthers " + disableOthers + ")"); 1477 } 1478 if (!doesUidBelongToCurrentUser(uid)) { 1479 Log.e(TAG, "UID " + uid + " not visible to the current user"); 1480 return false; 1481 } 1482 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1483 if (config == null) { 1484 return false; 1485 } 1486 if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) { 1487 Log.e(TAG, "UID " + uid + " does not have permission to update configuration " 1488 + config.configKey()); 1489 return false; 1490 } 1491 if (!updateNetworkSelectionStatus( 1492 networkId, WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLE)) { 1493 return false; 1494 } 1495 if (disableOthers) { 1496 setLastSelectedNetwork(networkId); 1497 } 1498 saveToStore(true); 1499 return true; 1500 } 1501 1502 /** 1503 * Disable a network using the public {@link WifiManager#disableNetwork(int)} API. 1504 * 1505 * @param networkId network ID of the network that needs the update. 1506 * @param uid uid of the app requesting the update. 1507 * @return true if it succeeds, false otherwise 1508 */ 1509 public boolean disableNetwork(int networkId, int uid) { 1510 if (mVerboseLoggingEnabled) { 1511 Log.v(TAG, "Disabling network " + networkId); 1512 } 1513 if (!doesUidBelongToCurrentUser(uid)) { 1514 Log.e(TAG, "UID " + uid + " not visible to the current user"); 1515 return false; 1516 } 1517 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1518 if (config == null) { 1519 return false; 1520 } 1521 if (!canModifyNetwork(config, uid, DISALLOW_LOCKDOWN_CHECK_BYPASS)) { 1522 Log.e(TAG, "UID " + uid + " does not have permission to update configuration " 1523 + config.configKey()); 1524 return false; 1525 } 1526 if (!updateNetworkSelectionStatus( 1527 networkId, NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER)) { 1528 return false; 1529 } 1530 if (networkId == mLastSelectedNetworkId) { 1531 clearLastSelectedNetwork(); 1532 } 1533 saveToStore(true); 1534 return true; 1535 } 1536 1537 /** 1538 * Checks if the |uid| has the necessary permission to force a connection to a network 1539 * and updates the last connected UID for the provided configuration. 1540 * 1541 * @param networkId network ID corresponding to the network. 1542 * @param uid uid of the app requesting the connection. 1543 * @return true if |uid| has the necessary permission to trigger explicit connection to the 1544 * network, false otherwise. 1545 * Note: This returns true only for the system settings/sysui app which holds the 1546 * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. We don't want to let 1547 * any other app force connection to a network. 1548 */ 1549 public boolean checkAndUpdateLastConnectUid(int networkId, int uid) { 1550 if (mVerboseLoggingEnabled) { 1551 Log.v(TAG, "Update network last connect UID for " + networkId); 1552 } 1553 if (!doesUidBelongToCurrentUser(uid)) { 1554 Log.e(TAG, "UID " + uid + " not visible to the current user"); 1555 return false; 1556 } 1557 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1558 if (config == null) { 1559 return false; 1560 } 1561 if (!canModifyNetwork(config, uid, ALLOW_LOCKDOWN_CHECK_BYPASS)) { 1562 Log.e(TAG, "UID " + uid + " does not have permission to update configuration " 1563 + config.configKey()); 1564 return false; 1565 } 1566 config.lastConnectUid = uid; 1567 return true; 1568 } 1569 1570 /** 1571 * Updates a network configuration after a successful connection to it. 1572 * 1573 * This method updates the following WifiConfiguration elements: 1574 * 1. Set the |lastConnected| timestamp. 1575 * 2. Increment |numAssociation| counter. 1576 * 3. Clear the disable reason counters in the associated |NetworkSelectionStatus|. 1577 * 4. Set the hasEverConnected| flag in the associated |NetworkSelectionStatus|. 1578 * 5. Sets the status of network as |CURRENT|. 1579 * 1580 * @param networkId network ID corresponding to the network. 1581 * @return true if the network was found, false otherwise. 1582 */ 1583 public boolean updateNetworkAfterConnect(int networkId) { 1584 if (mVerboseLoggingEnabled) { 1585 Log.v(TAG, "Update network after connect for " + networkId); 1586 } 1587 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1588 if (config == null) { 1589 return false; 1590 } 1591 config.lastConnected = mClock.getWallClockMillis(); 1592 config.numAssociation++; 1593 config.getNetworkSelectionStatus().clearDisableReasonCounter(); 1594 config.getNetworkSelectionStatus().setHasEverConnected(true); 1595 setNetworkStatus(config, WifiConfiguration.Status.CURRENT); 1596 saveToStore(false); 1597 return true; 1598 } 1599 1600 /** 1601 * Updates a network configuration after disconnection from it. 1602 * 1603 * This method updates the following WifiConfiguration elements: 1604 * 1. Set the |lastDisConnected| timestamp. 1605 * 2. Sets the status of network back to |ENABLED|. 1606 * 1607 * @param networkId network ID corresponding to the network. 1608 * @return true if the network was found, false otherwise. 1609 */ 1610 public boolean updateNetworkAfterDisconnect(int networkId) { 1611 if (mVerboseLoggingEnabled) { 1612 Log.v(TAG, "Update network after disconnect for " + networkId); 1613 } 1614 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1615 if (config == null) { 1616 return false; 1617 } 1618 config.lastDisconnected = mClock.getWallClockMillis(); 1619 // If the network hasn't been disabled, mark it back as 1620 // enabled after disconnection. 1621 if (config.status == WifiConfiguration.Status.CURRENT) { 1622 setNetworkStatus(config, WifiConfiguration.Status.ENABLED); 1623 } 1624 saveToStore(false); 1625 return true; 1626 } 1627 1628 /** 1629 * Set default GW MAC address for the provided network. 1630 * 1631 * @param networkId network ID corresponding to the network. 1632 * @param macAddress MAC address of the gateway to be set. 1633 * @return true if the network was found, false otherwise. 1634 */ 1635 public boolean setNetworkDefaultGwMacAddress(int networkId, String macAddress) { 1636 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1637 if (config == null) { 1638 return false; 1639 } 1640 config.defaultGwMacAddress = macAddress; 1641 return true; 1642 } 1643 1644 /** 1645 * Clear the {@link NetworkSelectionStatus#mCandidate}, 1646 * {@link NetworkSelectionStatus#mCandidateScore} & 1647 * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network. 1648 * 1649 * This is invoked by Network Selector at the start of every selection procedure to clear all 1650 * configured networks' scan-result-candidates. 1651 * 1652 * @param networkId network ID corresponding to the network. 1653 * @return true if the network was found, false otherwise. 1654 */ 1655 public boolean clearNetworkCandidateScanResult(int networkId) { 1656 if (mVerboseLoggingEnabled) { 1657 Log.v(TAG, "Clear network candidate scan result for " + networkId); 1658 } 1659 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1660 if (config == null) { 1661 return false; 1662 } 1663 config.getNetworkSelectionStatus().setCandidate(null); 1664 config.getNetworkSelectionStatus().setCandidateScore(Integer.MIN_VALUE); 1665 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(false); 1666 return true; 1667 } 1668 1669 /** 1670 * Set the {@link NetworkSelectionStatus#mCandidate}, 1671 * {@link NetworkSelectionStatus#mCandidateScore} & 1672 * {@link NetworkSelectionStatus#mSeenInLastQualifiedNetworkSelection} for the provided network. 1673 * 1674 * This is invoked by Network Selector when it sees a network during network selection procedure 1675 * to set the scan result candidate. 1676 * 1677 * @param networkId network ID corresponding to the network. 1678 * @param scanResult Candidate ScanResult associated with this network. 1679 * @param score Score assigned to the candidate. 1680 * @return true if the network was found, false otherwise. 1681 */ 1682 public boolean setNetworkCandidateScanResult(int networkId, ScanResult scanResult, int score) { 1683 if (mVerboseLoggingEnabled) { 1684 Log.v(TAG, "Set network candidate scan result " + scanResult + " for " + networkId); 1685 } 1686 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1687 if (config == null) { 1688 return false; 1689 } 1690 config.getNetworkSelectionStatus().setCandidate(scanResult); 1691 config.getNetworkSelectionStatus().setCandidateScore(score); 1692 config.getNetworkSelectionStatus().setSeenInLastQualifiedNetworkSelection(true); 1693 return true; 1694 } 1695 1696 /** 1697 * Iterate through all the saved networks and remove the provided configuration from the 1698 * {@link NetworkSelectionStatus#mConnectChoice} from them. 1699 * 1700 * This is invoked when a network is removed from our records. 1701 * 1702 * @param connectChoiceConfigKey ConfigKey corresponding to the network that is being removed. 1703 */ 1704 private void removeConnectChoiceFromAllNetworks(String connectChoiceConfigKey) { 1705 if (mVerboseLoggingEnabled) { 1706 Log.v(TAG, "Removing connect choice from all networks " + connectChoiceConfigKey); 1707 } 1708 if (connectChoiceConfigKey == null) { 1709 return; 1710 } 1711 for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) { 1712 WifiConfiguration.NetworkSelectionStatus status = config.getNetworkSelectionStatus(); 1713 String connectChoice = status.getConnectChoice(); 1714 if (TextUtils.equals(connectChoice, connectChoiceConfigKey)) { 1715 Log.d(TAG, "remove connect choice:" + connectChoice + " from " + config.SSID 1716 + " : " + config.networkId); 1717 clearNetworkConnectChoice(config.networkId); 1718 } 1719 } 1720 } 1721 1722 /** 1723 * Clear the {@link NetworkSelectionStatus#mConnectChoice} & 1724 * {@link NetworkSelectionStatus#mConnectChoiceTimestamp} for the provided network. 1725 * 1726 * @param networkId network ID corresponding to the network. 1727 * @return true if the network was found, false otherwise. 1728 */ 1729 public boolean clearNetworkConnectChoice(int networkId) { 1730 if (mVerboseLoggingEnabled) { 1731 Log.v(TAG, "Clear network connect choice for " + networkId); 1732 } 1733 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1734 if (config == null) { 1735 return false; 1736 } 1737 config.getNetworkSelectionStatus().setConnectChoice(null); 1738 config.getNetworkSelectionStatus().setConnectChoiceTimestamp( 1739 NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP); 1740 saveToStore(false); 1741 return true; 1742 } 1743 1744 /** 1745 * Set the {@link NetworkSelectionStatus#mConnectChoice} & 1746 * {@link NetworkSelectionStatus#mConnectChoiceTimestamp} for the provided network. 1747 * 1748 * This is invoked by Network Selector when the user overrides the currently connected network 1749 * choice. 1750 * 1751 * @param networkId network ID corresponding to the network. 1752 * @param connectChoiceConfigKey ConfigKey corresponding to the network which was chosen over 1753 * this network. 1754 * @param timestamp timestamp at which the choice was made. 1755 * @return true if the network was found, false otherwise. 1756 */ 1757 public boolean setNetworkConnectChoice( 1758 int networkId, String connectChoiceConfigKey, long timestamp) { 1759 if (mVerboseLoggingEnabled) { 1760 Log.v(TAG, "Set network connect choice " + connectChoiceConfigKey + " for " + networkId); 1761 } 1762 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1763 if (config == null) { 1764 return false; 1765 } 1766 config.getNetworkSelectionStatus().setConnectChoice(connectChoiceConfigKey); 1767 config.getNetworkSelectionStatus().setConnectChoiceTimestamp(timestamp); 1768 saveToStore(false); 1769 return true; 1770 } 1771 1772 /** 1773 * Increments the number of no internet access reports in the provided network. 1774 * 1775 * @param networkId network ID corresponding to the network. 1776 * @return true if the network was found, false otherwise. 1777 */ 1778 public boolean incrementNetworkNoInternetAccessReports(int networkId) { 1779 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1780 if (config == null) { 1781 return false; 1782 } 1783 config.numNoInternetAccessReports++; 1784 return true; 1785 } 1786 1787 /** 1788 * Sets the internet access is validated or not in the provided network. 1789 * 1790 * @param networkId network ID corresponding to the network. 1791 * @param validated Whether access is validated or not. 1792 * @return true if the network was found, false otherwise. 1793 */ 1794 public boolean setNetworkValidatedInternetAccess(int networkId, boolean validated) { 1795 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1796 if (config == null) { 1797 return false; 1798 } 1799 config.validatedInternetAccess = validated; 1800 config.numNoInternetAccessReports = 0; 1801 saveToStore(false); 1802 return true; 1803 } 1804 1805 /** 1806 * Sets whether the internet access is expected or not in the provided network. 1807 * 1808 * @param networkId network ID corresponding to the network. 1809 * @param expected Whether access is expected or not. 1810 * @return true if the network was found, false otherwise. 1811 */ 1812 public boolean setNetworkNoInternetAccessExpected(int networkId, boolean expected) { 1813 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 1814 if (config == null) { 1815 return false; 1816 } 1817 config.noInternetAccessExpected = expected; 1818 return true; 1819 } 1820 1821 /** 1822 * Helper method to clear out the {@link #mNextNetworkId} user/app network selection. This 1823 * is done when either the corresponding network is either removed or disabled. 1824 */ 1825 private void clearLastSelectedNetwork() { 1826 if (mVerboseLoggingEnabled) { 1827 Log.v(TAG, "Clearing last selected network"); 1828 } 1829 mLastSelectedNetworkId = WifiConfiguration.INVALID_NETWORK_ID; 1830 mLastSelectedTimeStamp = NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP; 1831 } 1832 1833 /** 1834 * Helper method to mark a network as the last selected one by an app/user. This is set 1835 * when an app invokes {@link #enableNetwork(int, boolean, int)} with |disableOthers| flag set. 1836 * This is used by network selector to assign a special bonus during network selection. 1837 */ 1838 private void setLastSelectedNetwork(int networkId) { 1839 if (mVerboseLoggingEnabled) { 1840 Log.v(TAG, "Setting last selected network to " + networkId); 1841 } 1842 mLastSelectedNetworkId = networkId; 1843 mLastSelectedTimeStamp = mClock.getElapsedSinceBootMillis(); 1844 } 1845 1846 /** 1847 * Retrieve the network Id corresponding to the last network that was explicitly selected by 1848 * an app/user. 1849 * 1850 * @return network Id corresponding to the last selected network. 1851 */ 1852 public int getLastSelectedNetwork() { 1853 return mLastSelectedNetworkId; 1854 } 1855 1856 /** 1857 * Retrieve the configKey corresponding to the last network that was explicitly selected by 1858 * an app/user. 1859 * 1860 * @return network Id corresponding to the last selected network. 1861 */ 1862 public String getLastSelectedNetworkConfigKey() { 1863 if (mLastSelectedNetworkId == WifiConfiguration.INVALID_NETWORK_ID) { 1864 return ""; 1865 } 1866 WifiConfiguration config = getInternalConfiguredNetwork(mLastSelectedNetworkId); 1867 if (config == null) { 1868 return ""; 1869 } 1870 return config.configKey(); 1871 } 1872 1873 /** 1874 * Retrieve the time stamp at which a network was explicitly selected by an app/user. 1875 * 1876 * @return timestamp in milliseconds from boot when this was set. 1877 */ 1878 public long getLastSelectedTimeStamp() { 1879 return mLastSelectedTimeStamp; 1880 } 1881 1882 /** 1883 * Helper method to get the scan detail cache entry {@link #mScanDetailCaches} for the provided 1884 * network. 1885 * 1886 * @param networkId network ID corresponding to the network. 1887 * @return existing {@link ScanDetailCache} entry if one exists or null. 1888 */ 1889 public ScanDetailCache getScanDetailCacheForNetwork(int networkId) { 1890 return mScanDetailCaches.get(networkId); 1891 } 1892 1893 /** 1894 * Helper method to get or create a scan detail cache entry {@link #mScanDetailCaches} for 1895 * the provided network. 1896 * 1897 * @param config configuration corresponding to the the network. 1898 * @return existing {@link ScanDetailCache} entry if one exists or a new instance created for 1899 * this network. 1900 */ 1901 private ScanDetailCache getOrCreateScanDetailCacheForNetwork(WifiConfiguration config) { 1902 if (config == null) return null; 1903 ScanDetailCache cache = getScanDetailCacheForNetwork(config.networkId); 1904 if (cache == null && config.networkId != WifiConfiguration.INVALID_NETWORK_ID) { 1905 cache = new ScanDetailCache( 1906 config, SCAN_CACHE_ENTRIES_MAX_SIZE, SCAN_CACHE_ENTRIES_TRIM_SIZE); 1907 mScanDetailCaches.put(config.networkId, cache); 1908 } 1909 return cache; 1910 } 1911 1912 /** 1913 * Saves the provided ScanDetail into the corresponding scan detail cache entry 1914 * {@link #mScanDetailCaches} for the provided network. 1915 * 1916 * @param config configuration corresponding to the the network. 1917 * @param scanDetail new scan detail instance to be saved into the cache. 1918 */ 1919 private void saveToScanDetailCacheForNetwork( 1920 WifiConfiguration config, ScanDetail scanDetail) { 1921 ScanResult scanResult = scanDetail.getScanResult(); 1922 1923 ScanDetailCache scanDetailCache = getOrCreateScanDetailCacheForNetwork(config); 1924 if (scanDetailCache == null) { 1925 Log.e(TAG, "Could not allocate scan cache for " + config.getPrintableSsid()); 1926 return; 1927 } 1928 1929 // Adding a new BSSID 1930 ScanResult result = scanDetailCache.getScanResult(scanResult.BSSID); 1931 if (result != null) { 1932 // transfer the black list status 1933 scanResult.blackListTimestamp = result.blackListTimestamp; 1934 scanResult.numIpConfigFailures = result.numIpConfigFailures; 1935 scanResult.numConnection = result.numConnection; 1936 } 1937 if (config.ephemeral) { 1938 // For an ephemeral Wi-Fi config, the ScanResult should be considered 1939 // untrusted. 1940 scanResult.untrusted = true; 1941 } 1942 1943 // Add the scan detail to this network's scan detail cache. 1944 scanDetailCache.put(scanDetail); 1945 1946 // Since we added a scan result to this configuration, re-attempt linking. 1947 // TODO: Do we really need to do this after every scan result? 1948 attemptNetworkLinking(config); 1949 } 1950 1951 /** 1952 * Retrieves a configured network corresponding to the provided scan detail if one exists. 1953 * 1954 * @param scanDetail ScanDetail instance to use for looking up the network. 1955 * @return WifiConfiguration object representing the network corresponding to the scanDetail, 1956 * null if none exists. 1957 */ 1958 public WifiConfiguration getConfiguredNetworkForScanDetail(ScanDetail scanDetail) { 1959 ScanResult scanResult = scanDetail.getScanResult(); 1960 if (scanResult == null) { 1961 Log.e(TAG, "No scan result found in scan detail"); 1962 return null; 1963 } 1964 WifiConfiguration config = null; 1965 try { 1966 config = mConfiguredNetworks.getByScanResultForCurrentUser(scanResult); 1967 } catch (IllegalArgumentException e) { 1968 Log.e(TAG, "Failed to lookup network from config map", e); 1969 } 1970 if (config != null) { 1971 if (mVerboseLoggingEnabled) { 1972 Log.v(TAG, "getSavedNetworkFromScanDetail Found " + config.configKey() 1973 + " for " + scanResult.SSID + "[" + scanResult.capabilities + "]"); 1974 } 1975 } 1976 return config; 1977 } 1978 1979 /** 1980 * Retrieves a configured network corresponding to the provided scan detail if one exists and 1981 * caches the provided |scanDetail| into the corresponding scan detail cache entry 1982 * {@link #mScanDetailCaches} for the retrieved network. 1983 * 1984 * @param scanDetail input a scanDetail from the scan result 1985 * @return WifiConfiguration object representing the network corresponding to the scanDetail, 1986 * null if none exists. 1987 */ 1988 public WifiConfiguration getConfiguredNetworkForScanDetailAndCache(ScanDetail scanDetail) { 1989 WifiConfiguration network = getConfiguredNetworkForScanDetail(scanDetail); 1990 if (network == null) { 1991 return null; 1992 } 1993 saveToScanDetailCacheForNetwork(network, scanDetail); 1994 // Cache DTIM values parsed from the beacon frame Traffic Indication Map (TIM) 1995 // Information Element (IE), into the associated WifiConfigurations. Most of the 1996 // time there is no TIM IE in the scan result (Probe Response instead of Beacon 1997 // Frame), these scanResult DTIM's are negative and ignored. 1998 // Used for metrics collection. 1999 if (scanDetail.getNetworkDetail() != null 2000 && scanDetail.getNetworkDetail().getDtimInterval() > 0) { 2001 network.dtimInterval = scanDetail.getNetworkDetail().getDtimInterval(); 2002 } 2003 return createExternalWifiConfiguration(network, true); 2004 } 2005 2006 /** 2007 * Update the scan detail cache associated with current connected network with latest 2008 * RSSI value in the provided WifiInfo. 2009 * This is invoked when we get an RSSI poll update after connection. 2010 * 2011 * @param info WifiInfo instance pointing to the current connected network. 2012 */ 2013 public void updateScanDetailCacheFromWifiInfo(WifiInfo info) { 2014 WifiConfiguration config = getInternalConfiguredNetwork(info.getNetworkId()); 2015 ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(info.getNetworkId()); 2016 if (config != null && scanDetailCache != null) { 2017 ScanDetail scanDetail = scanDetailCache.getScanDetail(info.getBSSID()); 2018 if (scanDetail != null) { 2019 ScanResult result = scanDetail.getScanResult(); 2020 long previousSeen = result.seen; 2021 int previousRssi = result.level; 2022 // Update the scan result 2023 scanDetail.setSeen(); 2024 result.level = info.getRssi(); 2025 // Average the RSSI value 2026 result.averageRssi(previousRssi, previousSeen, SCAN_RESULT_MAXIMUM_AGE_MS); 2027 if (mVerboseLoggingEnabled) { 2028 Log.v(TAG, "Updating scan detail cache freq=" + result.frequency 2029 + " BSSID=" + result.BSSID 2030 + " RSSI=" + result.level 2031 + " for " + config.configKey()); 2032 } 2033 } 2034 } 2035 } 2036 2037 /** 2038 * Save the ScanDetail to the ScanDetailCache of the given network. This is used 2039 * by {@link com.android.server.wifi.hotspot2.PasspointNetworkEvaluator} for caching 2040 * ScanDetail for newly created {@link WifiConfiguration} for Passpoint network. 2041 * 2042 * @param networkId The ID of the network to save ScanDetail to 2043 * @param scanDetail The ScanDetail to cache 2044 */ 2045 public void updateScanDetailForNetwork(int networkId, ScanDetail scanDetail) { 2046 WifiConfiguration network = getInternalConfiguredNetwork(networkId); 2047 if (network == null) { 2048 return; 2049 } 2050 saveToScanDetailCacheForNetwork(network, scanDetail); 2051 } 2052 2053 /** 2054 * Helper method to check if the 2 provided networks can be linked or not. 2055 * Networks are considered for linking if: 2056 * 1. Share the same GW MAC address. 2057 * 2. Scan results for the networks have AP's with MAC address which differ only in the last 2058 * nibble. 2059 * 2060 * @param network1 WifiConfiguration corresponding to network 1. 2061 * @param network2 WifiConfiguration corresponding to network 2. 2062 * @param scanDetailCache1 ScanDetailCache entry for network 1. 2063 * @param scanDetailCache1 ScanDetailCache entry for network 2. 2064 * @return true if the networks should be linked, false if the networks should be unlinked. 2065 */ 2066 private boolean shouldNetworksBeLinked( 2067 WifiConfiguration network1, WifiConfiguration network2, 2068 ScanDetailCache scanDetailCache1, ScanDetailCache scanDetailCache2) { 2069 // TODO (b/30706406): Link networks only with same passwords if the 2070 // |mOnlyLinkSameCredentialConfigurations| flag is set. 2071 if (mOnlyLinkSameCredentialConfigurations) { 2072 if (!TextUtils.equals(network1.preSharedKey, network2.preSharedKey)) { 2073 if (mVerboseLoggingEnabled) { 2074 Log.v(TAG, "shouldNetworksBeLinked unlink due to password mismatch"); 2075 } 2076 return false; 2077 } 2078 } 2079 if (network1.defaultGwMacAddress != null && network2.defaultGwMacAddress != null) { 2080 // If both default GW are known, link only if they are equal 2081 if (network1.defaultGwMacAddress.equals(network2.defaultGwMacAddress)) { 2082 if (mVerboseLoggingEnabled) { 2083 Log.v(TAG, "shouldNetworksBeLinked link due to same gw " + network2.SSID 2084 + " and " + network1.SSID + " GW " + network1.defaultGwMacAddress); 2085 } 2086 return true; 2087 } 2088 } else { 2089 // We do not know BOTH default gateways hence we will try to link 2090 // hoping that WifiConfigurations are indeed behind the same gateway. 2091 // once both WifiConfiguration have been tried and thus once both default gateways 2092 // are known we will revisit the choice of linking them. 2093 if (scanDetailCache1 != null && scanDetailCache2 != null) { 2094 for (String abssid : scanDetailCache1.keySet()) { 2095 for (String bbssid : scanDetailCache2.keySet()) { 2096 if (abssid.regionMatches( 2097 true, 0, bbssid, 0, LINK_CONFIGURATION_BSSID_MATCH_LENGTH)) { 2098 // If first 16 ASCII characters of BSSID matches, 2099 // we assume this is a DBDC. 2100 if (mVerboseLoggingEnabled) { 2101 Log.v(TAG, "shouldNetworksBeLinked link due to DBDC BSSID match " 2102 + network2.SSID + " and " + network1.SSID 2103 + " bssida " + abssid + " bssidb " + bbssid); 2104 } 2105 return true; 2106 } 2107 } 2108 } 2109 } 2110 } 2111 return false; 2112 } 2113 2114 /** 2115 * Helper methods to link 2 networks together. 2116 * 2117 * @param network1 WifiConfiguration corresponding to network 1. 2118 * @param network2 WifiConfiguration corresponding to network 2. 2119 */ 2120 private void linkNetworks(WifiConfiguration network1, WifiConfiguration network2) { 2121 if (mVerboseLoggingEnabled) { 2122 Log.v(TAG, "linkNetworks will link " + network2.configKey() 2123 + " and " + network1.configKey()); 2124 } 2125 if (network2.linkedConfigurations == null) { 2126 network2.linkedConfigurations = new HashMap<>(); 2127 } 2128 if (network1.linkedConfigurations == null) { 2129 network1.linkedConfigurations = new HashMap<>(); 2130 } 2131 // TODO (b/30638473): This needs to become a set instead of map, but it will need 2132 // public interface changes and need some migration of existing store data. 2133 network2.linkedConfigurations.put(network1.configKey(), 1); 2134 network1.linkedConfigurations.put(network2.configKey(), 1); 2135 } 2136 2137 /** 2138 * Helper methods to unlink 2 networks from each other. 2139 * 2140 * @param network1 WifiConfiguration corresponding to network 1. 2141 * @param network2 WifiConfiguration corresponding to network 2. 2142 */ 2143 private void unlinkNetworks(WifiConfiguration network1, WifiConfiguration network2) { 2144 if (network2.linkedConfigurations != null 2145 && (network2.linkedConfigurations.get(network1.configKey()) != null)) { 2146 if (mVerboseLoggingEnabled) { 2147 Log.v(TAG, "unlinkNetworks un-link " + network1.configKey() 2148 + " from " + network2.configKey()); 2149 } 2150 network2.linkedConfigurations.remove(network1.configKey()); 2151 } 2152 if (network1.linkedConfigurations != null 2153 && (network1.linkedConfigurations.get(network2.configKey()) != null)) { 2154 if (mVerboseLoggingEnabled) { 2155 Log.v(TAG, "unlinkNetworks un-link " + network2.configKey() 2156 + " from " + network1.configKey()); 2157 } 2158 network1.linkedConfigurations.remove(network2.configKey()); 2159 } 2160 } 2161 2162 /** 2163 * This method runs through all the saved networks and checks if the provided network can be 2164 * linked with any of them. 2165 * 2166 * @param config WifiConfiguration object corresponding to the network that needs to be 2167 * checked for potential links. 2168 */ 2169 private void attemptNetworkLinking(WifiConfiguration config) { 2170 // Only link WPA_PSK config. 2171 if (!config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { 2172 return; 2173 } 2174 ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(config.networkId); 2175 // Ignore configurations with large number of BSSIDs. 2176 if (scanDetailCache != null 2177 && scanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) { 2178 return; 2179 } 2180 for (WifiConfiguration linkConfig : getInternalConfiguredNetworks()) { 2181 if (linkConfig.configKey().equals(config.configKey())) { 2182 continue; 2183 } 2184 if (linkConfig.ephemeral) { 2185 continue; 2186 } 2187 // Network Selector will be allowed to dynamically jump from a linked configuration 2188 // to another, hence only link configurations that have WPA_PSK security type. 2189 if (!linkConfig.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) { 2190 continue; 2191 } 2192 ScanDetailCache linkScanDetailCache = 2193 getScanDetailCacheForNetwork(linkConfig.networkId); 2194 // Ignore configurations with large number of BSSIDs. 2195 if (linkScanDetailCache != null 2196 && linkScanDetailCache.size() > LINK_CONFIGURATION_MAX_SCAN_CACHE_ENTRIES) { 2197 continue; 2198 } 2199 // Check if the networks should be linked/unlinked. 2200 if (shouldNetworksBeLinked( 2201 config, linkConfig, scanDetailCache, linkScanDetailCache)) { 2202 linkNetworks(config, linkConfig); 2203 } else { 2204 unlinkNetworks(config, linkConfig); 2205 } 2206 } 2207 } 2208 2209 /** 2210 * Helper method to fetch list of channels for a network from the associated ScanResult's cache 2211 * and add it to the provided channel as long as the size of the set is less than 2212 * |maxChannelSetSize|. 2213 * 2214 * @param channelSet Channel set holding all the channels for the network. 2215 * @param scanDetailCache ScanDetailCache entry associated with the network. 2216 * @param nowInMillis current timestamp to be used for age comparison. 2217 * @param ageInMillis only consider scan details whose timestamps are earlier than this 2218 * value. 2219 * @param maxChannelSetSize Maximum number of channels to be added to the set. 2220 * @return false if the list is full, true otherwise. 2221 */ 2222 private boolean addToChannelSetForNetworkFromScanDetailCache( 2223 Set<Integer> channelSet, ScanDetailCache scanDetailCache, 2224 long nowInMillis, long ageInMillis, int maxChannelSetSize) { 2225 if (scanDetailCache != null && scanDetailCache.size() > 0) { 2226 for (ScanDetail scanDetail : scanDetailCache.values()) { 2227 ScanResult result = scanDetail.getScanResult(); 2228 boolean valid = (nowInMillis - result.seen) < ageInMillis; 2229 if (mVerboseLoggingEnabled) { 2230 Log.v(TAG, "fetchChannelSetForNetwork has " + result.BSSID + " freq " 2231 + result.frequency + " age " + (nowInMillis - result.seen) 2232 + " ?=" + valid); 2233 } 2234 if (valid) { 2235 channelSet.add(result.frequency); 2236 } 2237 if (channelSet.size() >= maxChannelSetSize) { 2238 return false; 2239 } 2240 } 2241 } 2242 return true; 2243 } 2244 2245 /** 2246 * Retrieve a set of channels on which AP's for the provided network was seen using the 2247 * internal ScanResult's cache {@link #mScanDetailCaches}. This is used for initiating partial 2248 * scans for the currently connected network. 2249 * 2250 * @param networkId network ID corresponding to the network. 2251 * @param ageInMillis only consider scan details whose timestamps are earlier than this value. 2252 * @param homeChannelFreq frequency of the currently connected network. 2253 * @return Set containing the frequencies on which this network was found, null if the network 2254 * was not found or there are no associated scan details in the cache. 2255 */ 2256 public Set<Integer> fetchChannelSetForNetworkForPartialScan(int networkId, long ageInMillis, 2257 int homeChannelFreq) { 2258 WifiConfiguration config = getInternalConfiguredNetwork(networkId); 2259 if (config == null) { 2260 return null; 2261 } 2262 ScanDetailCache scanDetailCache = getScanDetailCacheForNetwork(networkId); 2263 if (scanDetailCache == null && config.linkedConfigurations == null) { 2264 Log.i(TAG, "No scan detail and linked configs associated with networkId " + networkId); 2265 return null; 2266 } 2267 if (mVerboseLoggingEnabled) { 2268 StringBuilder dbg = new StringBuilder(); 2269 dbg.append("fetchChannelSetForNetworkForPartialScan ageInMillis ") 2270 .append(ageInMillis) 2271 .append(" for ") 2272 .append(config.configKey()) 2273 .append(" max ") 2274 .append(mMaxNumActiveChannelsForPartialScans); 2275 if (scanDetailCache != null) { 2276 dbg.append(" bssids " + scanDetailCache.size()); 2277 } 2278 if (config.linkedConfigurations != null) { 2279 dbg.append(" linked " + config.linkedConfigurations.size()); 2280 } 2281 Log.v(TAG, dbg.toString()); 2282 } 2283 Set<Integer> channelSet = new HashSet<>(); 2284 2285 // First add the currently connected network channel. 2286 if (homeChannelFreq > 0) { 2287 channelSet.add(homeChannelFreq); 2288 if (channelSet.size() >= mMaxNumActiveChannelsForPartialScans) { 2289 return channelSet; 2290 } 2291 } 2292 2293 long nowInMillis = mClock.getWallClockMillis(); 2294 2295 // Then get channels for the network. 2296 if (!addToChannelSetForNetworkFromScanDetailCache( 2297 channelSet, scanDetailCache, nowInMillis, ageInMillis, 2298 mMaxNumActiveChannelsForPartialScans)) { 2299 return channelSet; 2300 } 2301 2302 // Lastly get channels for linked networks. 2303 if (config.linkedConfigurations != null) { 2304 for (String configKey : config.linkedConfigurations.keySet()) { 2305 WifiConfiguration linkedConfig = getInternalConfiguredNetwork(configKey); 2306 if (linkedConfig == null) { 2307 continue; 2308 } 2309 ScanDetailCache linkedScanDetailCache = 2310 getScanDetailCacheForNetwork(linkedConfig.networkId); 2311 if (!addToChannelSetForNetworkFromScanDetailCache( 2312 channelSet, linkedScanDetailCache, nowInMillis, ageInMillis, 2313 mMaxNumActiveChannelsForPartialScans)) { 2314 break; 2315 } 2316 } 2317 } 2318 return channelSet; 2319 } 2320 2321 /** 2322 * Retrieves a list of all the saved networks before enabling disconnected/connected PNO. 2323 * 2324 * PNO network list sent to the firmware has limited size. If there are a lot of saved 2325 * networks, this list will be truncated and we might end up not sending the networks 2326 * with the highest chance of connecting to the firmware. 2327 * So, re-sort the network list based on the frequency of connection to those networks 2328 * and whether it was last seen in the scan results. 2329 * 2330 * TODO (b/30399964): Recalculate the list whenever network status changes. 2331 * @return list of networks with updated priorities. 2332 */ 2333 public List<WifiScanner.PnoSettings.PnoNetwork> retrievePnoNetworkList() { 2334 List<WifiScanner.PnoSettings.PnoNetwork> pnoList = new ArrayList<>(); 2335 List<WifiConfiguration> networks = new ArrayList<>(getInternalConfiguredNetworks()); 2336 // Remove any permanently disabled networks. 2337 Iterator<WifiConfiguration> iter = networks.iterator(); 2338 while (iter.hasNext()) { 2339 WifiConfiguration config = iter.next(); 2340 if (config.ephemeral || config.isPasspoint() 2341 || config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) { 2342 iter.remove(); 2343 } 2344 } 2345 Collections.sort(networks, sScanListComparator); 2346 // Let's use the network list size - 1 as the highest priority and then go down from there. 2347 // So, the most frequently connected network has the highest priority now. 2348 int priority = networks.size() - 1; 2349 for (WifiConfiguration config : networks) { 2350 pnoList.add(WifiConfigurationUtil.createPnoNetwork(config, priority)); 2351 priority--; 2352 } 2353 return pnoList; 2354 } 2355 2356 /** 2357 * Retrieves a list of all the saved hidden networks for scans. 2358 * 2359 * Hidden network list sent to the firmware has limited size. If there are a lot of saved 2360 * networks, this list will be truncated and we might end up not sending the networks 2361 * with the highest chance of connecting to the firmware. 2362 * So, re-sort the network list based on the frequency of connection to those networks 2363 * and whether it was last seen in the scan results. 2364 * 2365 * @return list of networks with updated priorities. 2366 */ 2367 public List<WifiScanner.ScanSettings.HiddenNetwork> retrieveHiddenNetworkList() { 2368 List<WifiScanner.ScanSettings.HiddenNetwork> hiddenList = new ArrayList<>(); 2369 List<WifiConfiguration> networks = new ArrayList<>(getInternalConfiguredNetworks()); 2370 // Remove any permanently disabled networks or non hidden networks. 2371 Iterator<WifiConfiguration> iter = networks.iterator(); 2372 while (iter.hasNext()) { 2373 WifiConfiguration config = iter.next(); 2374 if (!config.hiddenSSID || 2375 config.getNetworkSelectionStatus().isNetworkPermanentlyDisabled()) { 2376 iter.remove(); 2377 } 2378 } 2379 Collections.sort(networks, sScanListComparator); 2380 // Let's use the network list size - 1 as the highest priority and then go down from there. 2381 // So, the most frequently connected network has the highest priority now. 2382 int priority = networks.size() - 1; 2383 for (WifiConfiguration config : networks) { 2384 hiddenList.add( 2385 new WifiScanner.ScanSettings.HiddenNetwork(config.SSID)); 2386 priority--; 2387 } 2388 return hiddenList; 2389 } 2390 2391 /** 2392 * Check if the provided ephemeral network was deleted by the user or not. 2393 * 2394 * @param ssid caller must ensure that the SSID passed thru this API match 2395 * the WifiConfiguration.SSID rules, and thus be surrounded by quotes. 2396 * @return true if network was deleted, false otherwise. 2397 */ 2398 public boolean wasEphemeralNetworkDeleted(String ssid) { 2399 return mDeletedEphemeralSSIDs.contains(ssid); 2400 } 2401 2402 /** 2403 * Disable an ephemeral SSID for the purpose of network selection. 2404 * 2405 * The only way to "un-disable it" is if the user create a network for that SSID and then 2406 * forget it. 2407 * 2408 * @param ssid caller must ensure that the SSID passed thru this API match 2409 * the WifiConfiguration.SSID rules, and thus be surrounded by quotes. 2410 * @return the {@link WifiConfiguration} corresponding to this SSID, if any, so that we can 2411 * disconnect if this is the current network. 2412 */ 2413 public WifiConfiguration disableEphemeralNetwork(String ssid) { 2414 if (ssid == null) { 2415 return null; 2416 } 2417 WifiConfiguration foundConfig = null; 2418 for (WifiConfiguration config : getInternalConfiguredNetworks()) { 2419 if (config.ephemeral && TextUtils.equals(config.SSID, ssid)) { 2420 foundConfig = config; 2421 break; 2422 } 2423 } 2424 mDeletedEphemeralSSIDs.add(ssid); 2425 Log.d(TAG, "Forget ephemeral SSID " + ssid + " num=" + mDeletedEphemeralSSIDs.size()); 2426 if (foundConfig != null) { 2427 Log.d(TAG, "Found ephemeral config in disableEphemeralNetwork: " 2428 + foundConfig.networkId); 2429 } 2430 return foundConfig; 2431 } 2432 2433 /** 2434 * Resets all sim networks state. 2435 */ 2436 public void resetSimNetworks(boolean simPresent) { 2437 if (mVerboseLoggingEnabled) localLog("resetSimNetworks"); 2438 for (WifiConfiguration config : getInternalConfiguredNetworks()) { 2439 if (TelephonyUtil.isSimConfig(config)) { 2440 String currentIdentity = null; 2441 if (simPresent) { 2442 currentIdentity = TelephonyUtil.getSimIdentity(mTelephonyManager, config); 2443 } 2444 // Update the loaded config 2445 config.enterpriseConfig.setIdentity(currentIdentity); 2446 if (config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.PEAP) { 2447 config.enterpriseConfig.setAnonymousIdentity(""); 2448 } 2449 } 2450 } 2451 mSimPresent = simPresent; 2452 } 2453 2454 /** 2455 * Check if SIM is present. 2456 * 2457 * @return True if SIM is present, otherwise false. 2458 */ 2459 public boolean isSimPresent() { 2460 return mSimPresent; 2461 } 2462 2463 /** 2464 * Any network using certificates to authenticate access requires unlocked key store; unless 2465 * the certificates can be stored with hardware encryption 2466 * 2467 * @return true if we need an unlocked keystore, false otherwise. 2468 */ 2469 public boolean needsUnlockedKeyStore() { 2470 for (WifiConfiguration config : getInternalConfiguredNetworks()) { 2471 if (WifiConfigurationUtil.isConfigForEapNetwork(config)) { 2472 if (mWifiKeyStore.needsSoftwareBackedKeyStore(config.enterpriseConfig)) { 2473 return true; 2474 } 2475 } 2476 } 2477 return false; 2478 } 2479 2480 /** 2481 * Helper method to perform the following operations during user switch/unlock: 2482 * - Remove private networks of the old user. 2483 * - Load from the new user store file. 2484 * - Save the store files again to migrate any user specific networks from the shared store 2485 * to user store. 2486 * This method assumes the user store is visible (i.e CE storage is unlocked). So, the caller 2487 * should ensure that the stores are accessible before invocation. 2488 * 2489 * @param userId The identifier of the new foreground user, after the unlock or switch. 2490 */ 2491 private void handleUserUnlockOrSwitch(int userId) { 2492 if (mVerboseLoggingEnabled) { 2493 Log.v(TAG, "Loading from store after user switch/unlock for " + userId); 2494 } 2495 // Switch out the user store file. 2496 if (loadFromUserStoreAfterUnlockOrSwitch(userId)) { 2497 saveToStore(true); 2498 mPendingUnlockStoreRead = false; 2499 } 2500 } 2501 2502 /** 2503 * Handles the switch to a different foreground user: 2504 * - Flush the current state to the old user's store file. 2505 * - Switch the user specific store file. 2506 * - Reload the networks from the store files (shared & user). 2507 * - Write the store files to move any user specific private networks from shared store to user 2508 * store. 2509 * 2510 * Need to be called when {@link com.android.server.SystemService#onSwitchUser(int)} is invoked. 2511 * 2512 * @param userId The identifier of the new foreground user, after the switch. 2513 * @return List of network ID's of all the private networks of the old user which will be 2514 * removed from memory. 2515 */ 2516 public Set<Integer> handleUserSwitch(int userId) { 2517 if (mVerboseLoggingEnabled) { 2518 Log.v(TAG, "Handling user switch for " + userId); 2519 } 2520 if (userId == mCurrentUserId) { 2521 Log.w(TAG, "User already in foreground " + userId); 2522 return new HashSet<>(); 2523 } 2524 if (mPendingStoreRead) { 2525 Log.wtf(TAG, "Unexpected user switch before store is read!"); 2526 return new HashSet<>(); 2527 } 2528 if (mUserManager.isUserUnlockingOrUnlocked(mCurrentUserId)) { 2529 saveToStore(true); 2530 } 2531 // Remove any private networks of the old user before switching the userId. 2532 Set<Integer> removedNetworkIds = clearInternalUserData(mCurrentUserId); 2533 mConfiguredNetworks.setNewUser(userId); 2534 mCurrentUserId = userId; 2535 2536 if (mUserManager.isUserUnlockingOrUnlocked(mCurrentUserId)) { 2537 handleUserUnlockOrSwitch(mCurrentUserId); 2538 } else { 2539 // Cannot read data from new user's CE store file before they log-in. 2540 mPendingUnlockStoreRead = true; 2541 Log.i(TAG, "Waiting for user unlock to load from store"); 2542 } 2543 return removedNetworkIds; 2544 } 2545 2546 /** 2547 * Handles the unlock of foreground user. This maybe needed to read the store file if the user's 2548 * CE storage is not visible when {@link #handleUserSwitch(int)} is invoked. 2549 * 2550 * Need to be called when {@link com.android.server.SystemService#onUnlockUser(int)} is invoked. 2551 * 2552 * @param userId The identifier of the user that unlocked. 2553 */ 2554 public void handleUserUnlock(int userId) { 2555 if (mVerboseLoggingEnabled) { 2556 Log.v(TAG, "Handling user unlock for " + userId); 2557 } 2558 if (mPendingStoreRead) { 2559 Log.w(TAG, "Ignore user unlock until store is read!"); 2560 mDeferredUserUnlockRead = true; 2561 return; 2562 } 2563 if (userId == mCurrentUserId && mPendingUnlockStoreRead) { 2564 handleUserUnlockOrSwitch(mCurrentUserId); 2565 } 2566 } 2567 2568 /** 2569 * Handles the stop of foreground user. This is needed to write the store file to flush 2570 * out any pending data before the user's CE store storage is unavailable. 2571 * 2572 * Need to be called when {@link com.android.server.SystemService#onStopUser(int)} is invoked. 2573 * 2574 * @param userId The identifier of the user that stopped. 2575 */ 2576 public void handleUserStop(int userId) { 2577 if (userId == mCurrentUserId && mUserManager.isUserUnlockingOrUnlocked(mCurrentUserId)) { 2578 saveToStore(true); 2579 clearInternalData(); 2580 mCurrentUserId = UserHandle.USER_SYSTEM; 2581 } 2582 } 2583 2584 /** 2585 * Helper method to clear internal databases. 2586 * This method clears the: 2587 * - List of configured networks. 2588 * - Map of scan detail caches. 2589 * - List of deleted ephemeral networks. 2590 */ 2591 private void clearInternalData() { 2592 mConfiguredNetworks.clear(); 2593 mDeletedEphemeralSSIDs.clear(); 2594 mScanDetailCaches.clear(); 2595 clearLastSelectedNetwork(); 2596 } 2597 2598 /** 2599 * Helper method to clear internal databases of the specified user. 2600 * This method clears the: 2601 * - Private configured configured networks of the specified user. 2602 * - Map of scan detail caches. 2603 * - List of deleted ephemeral networks. 2604 * 2605 * @param userId The identifier of the current foreground user, before the switch. 2606 * @return List of network ID's of all the private networks of the old user which will be 2607 * removed from memory. 2608 */ 2609 private Set<Integer> clearInternalUserData(int userId) { 2610 Set<Integer> removedNetworkIds = new HashSet<>(); 2611 // Remove any private networks of the old user before switching the userId. 2612 for (WifiConfiguration config : getInternalConfiguredNetworks()) { 2613 if (!config.shared && WifiConfigurationUtil.doesUidBelongToAnyProfile( 2614 config.creatorUid, mUserManager.getProfiles(userId))) { 2615 removedNetworkIds.add(config.networkId); 2616 mConfiguredNetworks.remove(config.networkId); 2617 } 2618 } 2619 mDeletedEphemeralSSIDs.clear(); 2620 mScanDetailCaches.clear(); 2621 clearLastSelectedNetwork(); 2622 return removedNetworkIds; 2623 } 2624 2625 /** 2626 * Helper function to populate the internal (in-memory) data from the retrieved shared store 2627 * (file) data. 2628 * 2629 * @param configurations list of configurations retrieved from store. 2630 */ 2631 private void loadInternalDataFromSharedStore( 2632 List<WifiConfiguration> configurations) { 2633 for (WifiConfiguration configuration : configurations) { 2634 configuration.networkId = mNextNetworkId++; 2635 if (mVerboseLoggingEnabled) { 2636 Log.v(TAG, "Adding network from shared store " + configuration.configKey()); 2637 } 2638 try { 2639 mConfiguredNetworks.put(configuration); 2640 } catch (IllegalArgumentException e) { 2641 Log.e(TAG, "Failed to add network to config map", e); 2642 } 2643 } 2644 } 2645 2646 /** 2647 * Helper function to populate the internal (in-memory) data from the retrieved user store 2648 * (file) data. 2649 * 2650 * @param configurations list of configurations retrieved from store. 2651 * @param deletedEphemeralSSIDs list of ssid's representing the ephemeral networks deleted by 2652 * the user. 2653 */ 2654 private void loadInternalDataFromUserStore( 2655 List<WifiConfiguration> configurations, Set<String> deletedEphemeralSSIDs) { 2656 for (WifiConfiguration configuration : configurations) { 2657 configuration.networkId = mNextNetworkId++; 2658 if (mVerboseLoggingEnabled) { 2659 Log.v(TAG, "Adding network from user store " + configuration.configKey()); 2660 } 2661 try { 2662 mConfiguredNetworks.put(configuration); 2663 } catch (IllegalArgumentException e) { 2664 Log.e(TAG, "Failed to add network to config map", e); 2665 } 2666 } 2667 for (String ssid : deletedEphemeralSSIDs) { 2668 mDeletedEphemeralSSIDs.add(ssid); 2669 } 2670 } 2671 2672 /** 2673 * Helper function to populate the internal (in-memory) data from the retrieved stores (file) 2674 * data. 2675 * This method: 2676 * 1. Clears all existing internal data. 2677 * 2. Sends out the networks changed broadcast after loading all the data. 2678 * 2679 * @param sharedConfigurations list of network configurations retrieved from shared store. 2680 * @param userConfigurations list of network configurations retrieved from user store. 2681 * @param deletedEphemeralSSIDs list of ssid's representing the ephemeral networks deleted by 2682 * the user. 2683 */ 2684 private void loadInternalData( 2685 List<WifiConfiguration> sharedConfigurations, 2686 List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSSIDs) { 2687 // Clear out all the existing in-memory lists and load the lists from what was retrieved 2688 // from the config store. 2689 clearInternalData(); 2690 loadInternalDataFromSharedStore(sharedConfigurations); 2691 loadInternalDataFromUserStore(userConfigurations, deletedEphemeralSSIDs); 2692 if (mConfiguredNetworks.sizeForAllUsers() == 0) { 2693 Log.w(TAG, "No stored networks found."); 2694 } 2695 sendConfiguredNetworksChangedBroadcast(); 2696 mPendingStoreRead = false; 2697 } 2698 2699 /** 2700 * Migrate data from legacy store files. The function performs the following operations: 2701 * 1. Check if the legacy store files are present. 2702 * 2. If yes, read all the data from the store files. 2703 * 3. Save it to the new store files. 2704 * 4. Delete the legacy store file. 2705 * 2706 * @return true if migration was successful or not needed (fresh install), false if it failed. 2707 */ 2708 public boolean migrateFromLegacyStore() { 2709 if (!mWifiConfigStoreLegacy.areStoresPresent()) { 2710 Log.d(TAG, "Legacy store files not found. No migration needed!"); 2711 return true; 2712 } 2713 WifiConfigStoreDataLegacy storeData = mWifiConfigStoreLegacy.read(); 2714 Log.d(TAG, "Reading from legacy store completed"); 2715 loadInternalData(storeData.getConfigurations(), new ArrayList<WifiConfiguration>(), 2716 storeData.getDeletedEphemeralSSIDs()); 2717 2718 // Setup user store for the current user in case it have not setup yet, so that data 2719 // owned by the current user will be backed to the user store. 2720 if (mDeferredUserUnlockRead) { 2721 mWifiConfigStore.setUserStore(WifiConfigStore.createUserFile(mCurrentUserId)); 2722 mDeferredUserUnlockRead = false; 2723 } 2724 2725 if (!saveToStore(true)) { 2726 return false; 2727 } 2728 mWifiConfigStoreLegacy.removeStores(); 2729 Log.d(TAG, "Migration from legacy store completed"); 2730 return true; 2731 } 2732 2733 /** 2734 * Read the config store and load the in-memory lists from the store data retrieved and sends 2735 * out the networks changed broadcast. 2736 * 2737 * This reads all the network configurations from: 2738 * 1. Shared WifiConfigStore.xml 2739 * 2. User WifiConfigStore.xml 2740 * 2741 * @return true on success or not needed (fresh install/pending legacy store migration), 2742 * false otherwise. 2743 */ 2744 public boolean loadFromStore() { 2745 if (!mWifiConfigStore.areStoresPresent()) { 2746 Log.d(TAG, "New store files not found. No saved networks loaded!"); 2747 if (!mWifiConfigStoreLegacy.areStoresPresent()) { 2748 // No legacy store files either, so reset the pending store read flag. 2749 mPendingStoreRead = false; 2750 } 2751 return true; 2752 } 2753 // If the user unlock comes in before we load from store, which means the user store have 2754 // not been setup yet for the current user. Setup the user store before the read so that 2755 // configurations for the current user will also being loaded. 2756 if (mDeferredUserUnlockRead) { 2757 Log.i(TAG, "Handling user unlock before loading from store."); 2758 mWifiConfigStore.setUserStore(WifiConfigStore.createUserFile(mCurrentUserId)); 2759 mDeferredUserUnlockRead = false; 2760 } 2761 try { 2762 mWifiConfigStore.read(); 2763 } catch (IOException e) { 2764 Log.wtf(TAG, "Reading from new store failed. All saved networks are lost!", e); 2765 return false; 2766 } catch (XmlPullParserException e) { 2767 Log.wtf(TAG, "XML deserialization of store failed. All saved networks are lost!", e); 2768 return false; 2769 } 2770 loadInternalData(mNetworkListStoreData.getSharedConfigurations(), 2771 mNetworkListStoreData.getUserConfigurations(), 2772 mDeletedEphemeralSsidsStoreData.getSsidList()); 2773 return true; 2774 } 2775 2776 /** 2777 * Read the user config store and load the in-memory lists from the store data retrieved and 2778 * sends out the networks changed broadcast. 2779 * This should be used for all user switches/unlocks to only load networks from the user 2780 * specific store and avoid reloading the shared networks. 2781 * 2782 * This reads all the network configurations from: 2783 * 1. User WifiConfigStore.xml 2784 * 2785 * @param userId The identifier of the foreground user. 2786 * @return true on success, false otherwise. 2787 */ 2788 public boolean loadFromUserStoreAfterUnlockOrSwitch(int userId) { 2789 try { 2790 mWifiConfigStore.switchUserStoreAndRead(WifiConfigStore.createUserFile(userId)); 2791 } catch (IOException e) { 2792 Log.wtf(TAG, "Reading from new store failed. All saved private networks are lost!", e); 2793 return false; 2794 } catch (XmlPullParserException e) { 2795 Log.wtf(TAG, "XML deserialization of store failed. All saved private networks are" + 2796 "lost!", e); 2797 return false; 2798 } 2799 loadInternalDataFromUserStore(mNetworkListStoreData.getUserConfigurations(), 2800 mDeletedEphemeralSsidsStoreData.getSsidList()); 2801 return true; 2802 } 2803 2804 /** 2805 * Save the current snapshot of the in-memory lists to the config store. 2806 * 2807 * @param forceWrite Whether the write needs to be forced or not. 2808 * @return Whether the write was successful or not, this is applicable only for force writes. 2809 */ 2810 public boolean saveToStore(boolean forceWrite) { 2811 ArrayList<WifiConfiguration> sharedConfigurations = new ArrayList<>(); 2812 ArrayList<WifiConfiguration> userConfigurations = new ArrayList<>(); 2813 // List of network IDs for legacy Passpoint configuration to be removed. 2814 List<Integer> legacyPasspointNetId = new ArrayList<>(); 2815 for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) { 2816 // Ignore ephemeral networks and non-legacy Passpoint configurations. 2817 if (config.ephemeral || (config.isPasspoint() && !config.isLegacyPasspointConfig)) { 2818 continue; 2819 } 2820 2821 // Migrate the legacy Passpoint configurations owned by the current user to 2822 // {@link PasspointManager}. 2823 if (config.isLegacyPasspointConfig && WifiConfigurationUtil.doesUidBelongToAnyProfile( 2824 config.creatorUid, mUserManager.getProfiles(mCurrentUserId))) { 2825 legacyPasspointNetId.add(config.networkId); 2826 // Migrate the legacy Passpoint configuration and add it to PasspointManager. 2827 if (!PasspointManager.addLegacyPasspointConfig(config)) { 2828 Log.e(TAG, "Failed to migrate legacy Passpoint config: " + config.FQDN); 2829 } 2830 // This will prevent adding |config| to the |sharedConfigurations|. 2831 continue; 2832 } 2833 2834 // We push all shared networks & private networks not belonging to the current 2835 // user to the shared store. Ideally, private networks for other users should 2836 // not even be in memory, 2837 // But, this logic is in place to deal with store migration from N to O 2838 // because all networks were previously stored in a central file. We cannot 2839 // write these private networks to the user specific store until the corresponding 2840 // user logs in. 2841 if (config.shared || !WifiConfigurationUtil.doesUidBelongToAnyProfile( 2842 config.creatorUid, mUserManager.getProfiles(mCurrentUserId))) { 2843 sharedConfigurations.add(config); 2844 } else { 2845 userConfigurations.add(config); 2846 } 2847 } 2848 2849 // Remove the configurations for migrated Passpoint configurations. 2850 for (int networkId : legacyPasspointNetId) { 2851 mConfiguredNetworks.remove(networkId); 2852 } 2853 2854 // Setup store data for write. 2855 mNetworkListStoreData.setSharedConfigurations(sharedConfigurations); 2856 mNetworkListStoreData.setUserConfigurations(userConfigurations); 2857 mDeletedEphemeralSsidsStoreData.setSsidList(mDeletedEphemeralSSIDs); 2858 2859 try { 2860 mWifiConfigStore.write(forceWrite); 2861 } catch (IOException e) { 2862 Log.wtf(TAG, "Writing to store failed. Saved networks maybe lost!", e); 2863 return false; 2864 } catch (XmlPullParserException e) { 2865 Log.wtf(TAG, "XML serialization for store failed. Saved networks maybe lost!", e); 2866 return false; 2867 } 2868 return true; 2869 } 2870 2871 /** 2872 * Helper method for logging into local log buffer. 2873 */ 2874 private void localLog(String s) { 2875 if (mLocalLog != null) { 2876 mLocalLog.log(s); 2877 } 2878 } 2879 2880 /** 2881 * Dump the local log buffer and other internal state of WifiConfigManager. 2882 */ 2883 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2884 pw.println("Dump of WifiConfigManager"); 2885 pw.println("WifiConfigManager - Log Begin ----"); 2886 mLocalLog.dump(fd, pw, args); 2887 pw.println("WifiConfigManager - Log End ----"); 2888 pw.println("WifiConfigManager - Configured networks Begin ----"); 2889 for (WifiConfiguration network : getInternalConfiguredNetworks()) { 2890 pw.println(network); 2891 } 2892 pw.println("WifiConfigManager - Configured networks End ----"); 2893 pw.println("WifiConfigManager - Next network ID to be allocated " + mNextNetworkId); 2894 pw.println("WifiConfigManager - Last selected network ID " + mLastSelectedNetworkId); 2895 } 2896 2897 /** 2898 * Returns true if the given uid has permission to add, update or remove proxy settings 2899 */ 2900 private boolean canModifyProxySettings(int uid) { 2901 final DevicePolicyManagerInternal dpmi = 2902 mWifiPermissionsWrapper.getDevicePolicyManagerInternal(); 2903 final boolean isUidProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid, 2904 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); 2905 final boolean isUidDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(uid, 2906 DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); 2907 final boolean hasNetworkSettingsPermission = 2908 mWifiPermissionsUtil.checkNetworkSettingsPermission(uid); 2909 // If |uid| corresponds to the device owner, allow all modifications. 2910 if (isUidDeviceOwner || isUidProfileOwner || hasNetworkSettingsPermission) { 2911 return true; 2912 } 2913 if (mVerboseLoggingEnabled) { 2914 Log.v(TAG, "UID: " + uid + " cannot modify WifiConfiguration proxy settings." 2915 + " ConfigOverride=" + hasNetworkSettingsPermission 2916 + " DeviceOwner=" + isUidDeviceOwner 2917 + " ProfileOwner=" + isUidProfileOwner); 2918 } 2919 return false; 2920 } 2921 2922 /** 2923 * Set the saved network update event listener 2924 */ 2925 public void setOnSavedNetworkUpdateListener(OnSavedNetworkUpdateListener listener) { 2926 mListener = listener; 2927 } 2928 2929 /** 2930 * Set extra failure reason for given config. Used to surface extra failure details to the UI 2931 * @param netId The network ID of the config to set the extra failure reason for 2932 * @param reason the WifiConfiguration.ExtraFailureReason failure code representing the most 2933 * recent failure reason 2934 */ 2935 public void setRecentFailureAssociationStatus(int netId, int reason) { 2936 WifiConfiguration config = getInternalConfiguredNetwork(netId); 2937 if (config == null) { 2938 return; 2939 } 2940 config.recentFailure.setAssociationStatus(reason); 2941 } 2942 2943 /** 2944 * @param netId The network ID of the config to clear the extra failure reason from 2945 */ 2946 public void clearRecentFailureReason(int netId) { 2947 WifiConfiguration config = getInternalConfiguredNetwork(netId); 2948 if (config == null) { 2949 return; 2950 } 2951 config.recentFailure.clear(); 2952 } 2953} 2954