summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libwifi_hal/Android.mk2
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java27
-rw-r--r--service/java/com/android/server/wifi/WifiConfigurationUtil.java102
-rw-r--r--service/java/com/android/server/wifi/WifiConnectivityManager.java22
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java37
-rw-r--r--service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java5
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java30
7 files changed, 217 insertions, 8 deletions
diff --git a/libwifi_hal/Android.mk b/libwifi_hal/Android.mk
index 4e2232fb4..f8987b6e4 100644
--- a/libwifi_hal/Android.mk
+++ b/libwifi_hal/Android.mk
@@ -104,6 +104,8 @@ else ifeq ($(BOARD_WLAN_DEVICE), rtl)
LIB_WIFI_HAL := libwifi-hal-rtl
else ifeq ($(BOARD_WLAN_DEVICE), emulator)
LIB_WIFI_HAL := libwifi-hal-emu
+else ifeq ($(BOARD_WLAN_DEVICE), slsi)
+ LIB_WIFI_HAL := libwifi-hal-slsi
endif
# The WiFi HAL that you should be linking.
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 5cf909695..0468f5ac3 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -326,6 +326,8 @@ public class ClientModeImpl extends StateMachine {
private NetworkInfo mNetworkInfo;
private SupplicantStateTracker mSupplicantStateTracker;
+ private int mWifiLinkLayerStatsSupported = 4; // Temporary disable
+
// Indicates that framework is attempting to roam, set true on CMD_START_ROAM, set false when
// wifi connects or fails to connect
private boolean mIsAutoRoaming = false;
@@ -1265,15 +1267,20 @@ public class ClientModeImpl extends StateMachine {
loge("getWifiLinkLayerStats called without an interface");
return null;
}
+ WifiLinkLayerStats stats = null;
mLastLinkLayerStatsUpdate = mClock.getWallClockMillis();
- WifiLinkLayerStats stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName);
- if (stats != null) {
- mOnTime = stats.on_time;
- mTxTime = stats.tx_time;
- mRxTime = stats.rx_time;
- mRunningBeaconCount = stats.beacon_rx;
- mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate);
- } else {
+ if (mWifiLinkLayerStatsSupported > 0) {
+ stats = mWifiNative.getWifiLinkLayerStats(mInterfaceName);
+ if (stats == null) {
+ mWifiLinkLayerStatsSupported -= 1;
+ } else {
+ mOnTime = stats.on_time;
+ mTxTime = stats.tx_time;
+ mRxTime = stats.rx_time;
+ mRunningBeaconCount = stats.beacon_rx;
+ mWifiInfo.updatePacketRates(stats, mLastLinkLayerStatsUpdate);
+ }
+ } else { // LinkLayerStats are broken or unsupported
long mTxPkts = mFacade.getTxPackets(mInterfaceName);
long mRxPkts = mFacade.getRxPackets(mInterfaceName);
mWifiInfo.updatePacketRates(mTxPkts, mRxPkts, mLastLinkLayerStatsUpdate);
@@ -3627,6 +3634,10 @@ public class ClientModeImpl extends StateMachine {
mTemporarilyDisconnectWifi = (message.arg1 == 1);
replyToMessage(message, WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
break;
+ case WifiP2pServiceImpl.SET_MIRACAST_MODE:
+ if (mVerboseLoggingEnabled) logd("SET_MIRACAST_MODE: " + (int)message.arg1);
+ mWifiConnectivityManager.saveMiracastMode((int)message.arg1);
+ break;
/* Link configuration (IP address, DNS, ...) changes notified via netlink */
case CMD_UPDATE_LINKPROPERTIES:
updateLinkProperties((LinkProperties) message.obj);
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
index 59d3eb3f4..b8992a011 100644
--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -28,6 +28,9 @@ import android.net.wifi.WifiNetworkSpecifier;
import android.net.wifi.WifiScanner;
import android.os.PatternMatcher;
import android.os.UserHandle;
+import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -36,7 +39,17 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.util.NativeUtil;
import com.android.server.wifi.util.TelephonyUtil;
+import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.ProviderException;
+import java.security.UnrecoverableKeyException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.BitSet;
@@ -44,6 +57,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
+import javax.crypto.KeyGenerator;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+
/**
* WifiConfiguration utility for any {@link android.net.wifi.WifiConfiguration} related operations.
* Currently contains:
@@ -72,6 +89,10 @@ public class WifiConfigurationUtil {
new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS);
private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN =
new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
+ private static final String MAC_RANDOMIZATION_ALIAS = "MacRandSecret";
+ private static final long MAC_ADDRESS_VALID_LONG_MASK = (1L << 48) - 1;
+ private static final long MAC_ADDRESS_LOCALLY_ASSIGNED_MASK = 1L << 41;
+ private static final long MAC_ADDRESS_MULTICAST_MASK = 1L << 40;
/**
* Check whether a network configuration is visible to a user or any of its managed profiles.
@@ -227,6 +248,87 @@ public class WifiConfigurationUtil {
}
/**
+ * Computes the persistent randomized MAC of the given configuration using the given
+ * hash function.
+ * @param config the WifiConfiguration to compute MAC address for
+ * @param hashFunction the hash function that will perform the MAC address computation.
+ * @return The persistent randomized MAC address or null if inputs are invalid.
+ */
+ public static MacAddress calculatePersistentMacForConfiguration(WifiConfiguration config,
+ Mac hashFunction) {
+ if (config == null || hashFunction == null) {
+ return null;
+ }
+ byte[] hashedBytes = hashFunction.doFinal(
+ config.getSsidAndSecurityTypeString().getBytes(StandardCharsets.UTF_8));
+ ByteBuffer bf = ByteBuffer.wrap(hashedBytes);
+ long longFromSsid = bf.getLong();
+ /**
+ * Masks the generated long so that it represents a valid randomized MAC address.
+ * Specifically, this sets the locally assigned bit to 1, multicast bit to 0
+ */
+ longFromSsid &= MAC_ADDRESS_VALID_LONG_MASK;
+ longFromSsid |= MAC_ADDRESS_LOCALLY_ASSIGNED_MASK;
+ longFromSsid &= ~MAC_ADDRESS_MULTICAST_MASK;
+ bf.clear();
+ bf.putLong(0, longFromSsid);
+
+ // MacAddress.fromBytes requires input of length 6, which is obtained from the
+ // last 6 bytes from the generated long.
+ MacAddress macAddress = MacAddress.fromBytes(Arrays.copyOfRange(bf.array(), 2, 8));
+ return macAddress;
+ }
+
+ /**
+ * Retrieves a Hash function that could be used to calculate the persistent randomized MAC
+ * for a WifiConfiguration.
+ * @param uid the UID of the KeyStore to get the secret of the hash function from.
+ */
+ public static Mac obtainMacRandHashFunction(int uid) {
+ try {
+ KeyStore keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(uid);
+ // tries to retrieve the secret, and generate a new one if it's unavailable.
+ Key key = keyStore.getKey(MAC_RANDOMIZATION_ALIAS, null);
+ if (key == null) {
+ key = generateAndPersistNewMacRandomizationSecret(uid);
+ }
+ if (key == null) {
+ Log.e(TAG, "Failed to generate secret for " + MAC_RANDOMIZATION_ALIAS);
+ return null;
+ }
+ Mac result = Mac.getInstance("HmacSHA256");
+ result.init(key);
+ return result;
+ } catch (KeyStoreException | NoSuchAlgorithmException | InvalidKeyException
+ | UnrecoverableKeyException | NoSuchProviderException e) {
+ Log.e(TAG, "Failure in obtainMacRandHashFunction", e);
+ return null;
+ }
+ }
+
+ /**
+ * Generates and returns a secret key to use for Mac randomization.
+ * Will also persist the generated secret inside KeyStore, accessible in the
+ * future with KeyGenerator#getKey.
+ */
+ private static SecretKey generateAndPersistNewMacRandomizationSecret(int uid) {
+ try {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(
+ KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore");
+ keyGenerator.init(
+ new KeyGenParameterSpec.Builder(MAC_RANDOMIZATION_ALIAS,
+ KeyProperties.PURPOSE_SIGN)
+ .setUid(uid)
+ .build());
+ return keyGenerator.generateKey();
+ } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
+ | NoSuchProviderException | ProviderException e) {
+ Log.e(TAG, "Failure in generateMacRandomizationSecret", e);
+ return null;
+ }
+ }
+
+ /**
* Compare existing and new WifiEnterpriseConfig objects after a network update and return if
* credential parameters have changed or not.
*
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 2e4b5c891..b8b7e6550 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -24,6 +24,7 @@ import static com.android.server.wifi.ClientModeImpl.WIFI_WORK_SOURCE;
import android.app.AlarmManager;
import android.content.Context;
+import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
@@ -159,6 +160,7 @@ public class WifiConnectivityManager {
private boolean mWifiConnectivityManagerEnabled = false;
private boolean mRunning = false;
private boolean mScreenOn = false;
+ private int mMiracastMode = WifiP2pManager.MIRACAST_DISABLED;
private int mWifiState = WIFI_STATE_UNKNOWN;
private boolean mUntrustedConnectionAllowed = false;
private boolean mTrustedConnectionAllowed = false;
@@ -903,6 +905,17 @@ public class WifiConnectivityManager {
return;
}
+ // Any scans will impact Wifi performance including WFD performance,
+ // So at least ignore scans triggered internally by ConnectivityManager
+ // when WFD session is active. We still allow connectivity scans initiated
+ // by other work source.
+ if (WIFI_WORK_SOURCE.equals(workSource) &&
+ (mMiracastMode == WifiP2pManager.MIRACAST_SOURCE ||
+ mMiracastMode == WifiP2pManager.MIRACAST_SINK)) {
+ localLog("Ignore connectivity scan, MiracastMode:" + mMiracastMode);
+ return;
+ }
+
mPnoScanListener.resetLowRssiNetworkRetryDelay();
ScanSettings settings = new ScanSettings();
@@ -1152,6 +1165,15 @@ public class WifiConnectivityManager {
}
/**
+ * Save current miracast mode, it will be used to ignore
+ * connectivity scan during the time when miracast is enabled.
+ */
+ public void saveMiracastMode(int mode) {
+ localLog("saveMiracastMode: mode=" + mode);
+ mMiracastMode = mode;
+ }
+
+ /**
* Helper function that converts the WIFI_STATE_XXX constants to string
*/
private static String stateToString(int state) {
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 0afa317c9..54c2b6121 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -500,6 +500,39 @@ public class WifiServiceImpl extends BaseWifiService {
mAsyncChannelExternalClientHandler.setWifiLog(log);
}
+ // Return true if it is DUAL SIM and either SIM is active.
+ private boolean checkDualSimActive() {
+ TelephonyManager tm = (TelephonyManager)
+ mContext.getSystemService(Context.TELEPHONY_SERVICE);
+
+ if (tm == null) {
+ Log.i(TAG, "checkDualSimActive() is false, tm == null");
+ return false;
+ }
+
+ int phoneCount = tm.getPhoneCount();
+ if (phoneCount < 2) {
+ Log.i(TAG, "checkDualSimActive() is false, phoneCount="
+ + phoneCount + " slot0State=" + tm.getSimState(0));
+ return false;
+ }
+
+ int slot0State = tm.getSimState(0);
+ int slot1State = tm.getSimState(1);
+ if (slot0State != TelephonyManager.SIM_STATE_READY &&
+ slot1State != TelephonyManager.SIM_STATE_READY) {
+ Log.i(TAG, "checkDualSimActive() is false, slot0State="
+ + slot0State + " slot1State=" + slot1State);
+ return false;
+ }
+
+ Log.i(TAG, "checkDualSimActive() is true, phoneCount="
+ + phoneCount
+ + " slot0State=" + slot0State + " slot1State=" + slot1State);
+
+ return true;
+ }
+
/**
* Check if we are ready to start wifi.
*
@@ -538,6 +571,10 @@ public class WifiServiceImpl extends BaseWifiService {
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) {
+ if (checkDualSimActive()) {
+ Log.d(TAG, "Not resetting networks as other SIM may active");
+ return;
+ }
Log.d(TAG, "resetting networks because SIM was removed");
mClientModeImpl.resetSimAuthNetworks(false);
} else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) {
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index 055fa72ef..532659102 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -681,6 +681,11 @@ public class WifiP2pServiceImpl extends IWifiP2pManager.Stub {
enforceConnectivityInternalPermission();
checkConfigureWifiDisplayPermission();
mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode);
+ if (mWifiChannel != null) {
+ mWifiChannel.sendMessage(WifiP2pServiceImpl.SET_MIRACAST_MODE, mode);
+ } else {
+ Log.e(TAG, "setMiracastMode(): WifiChannel is null");
+ }
}
@Override
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
index c1640ce91..7173dae5b 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
@@ -25,6 +25,7 @@ import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiNetworkSpecifier;
import android.net.wifi.WifiScanner;
+import android.os.Binder;
import android.os.PatternMatcher;
import android.os.UserHandle;
import android.util.Pair;
@@ -39,6 +40,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import javax.crypto.Mac;
+
/**
* Unit tests for {@link com.android.server.wifi.WifiConfigurationUtil}.
*/
@@ -961,6 +964,33 @@ public class WifiConfigurationUtilTest {
existingConfig, newConfig));
}
+ /**
+ * Verifies that calculatePersistentMacForConfiguration produces persistent, locally generated
+ * MAC addresses that are valid for MAC randomization.
+ */
+ @Test
+ public void testCalculatePersistentMacForConfiguration() {
+ // verify null inputs
+ assertNull(WifiConfigurationUtil.calculatePersistentMacForConfiguration(null, null));
+
+ // test multiple times since there is some randomness involved with hashing
+ int uid = Binder.getCallingUid();
+ for (int i = 0; i < 10; i++) {
+ // Verify that a the MAC address calculated is valid
+ WifiConfiguration config = WifiConfigurationTestUtil.createOpenNetwork();
+ Mac hashFunction = WifiConfigurationUtil.obtainMacRandHashFunction(uid);
+ MacAddress macAddress = WifiConfigurationUtil.calculatePersistentMacForConfiguration(
+ config, hashFunction);
+ assertTrue(WifiConfiguration.isValidMacAddressForRandomization(macAddress));
+
+ // Verify that the secret used to generate MAC address is persistent
+ Mac hashFunction2 = WifiConfigurationUtil.obtainMacRandHashFunction(uid);
+ MacAddress macAddress2 = WifiConfigurationUtil.calculatePersistentMacForConfiguration(
+ config, hashFunction2);
+ assertEquals(macAddress, macAddress2);
+ }
+ }
+
private static class EnterpriseConfig {
public String eap;
public String phase2;