230 lines
9.0 KiB
Java
230 lines
9.0 KiB
Java
/*
|
|
* Copyright (C) 2019 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.server.wifi;
|
|
|
|
import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO;
|
|
import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE;
|
|
|
|
import android.telephony.PhoneStateListener;
|
|
import android.telephony.TelephonyManager;
|
|
import android.util.Log;
|
|
|
|
import com.android.server.wifi.SupplicantStaIfaceHal.MboAssocDisallowedReasonCode;
|
|
|
|
/**
|
|
* MboOceController is responsible for controlling MBO and OCE operations.
|
|
*/
|
|
public class MboOceController {
|
|
private static final String TAG = "MboOceController";
|
|
|
|
/** State of MBO/OCE module. */
|
|
private boolean mEnabled = false;
|
|
private boolean mIsMboSupported = false;
|
|
private boolean mIsOceSupported = false;
|
|
private boolean mVerboseLoggingEnabled = false;
|
|
|
|
private final TelephonyManager mTelephonyManager;
|
|
private final ActiveModeWarden mActiveModeWarden;
|
|
|
|
/**
|
|
* Create new instance of MboOceController.
|
|
*/
|
|
public MboOceController(TelephonyManager telephonyManager, ActiveModeWarden activeModeWarden) {
|
|
mTelephonyManager = telephonyManager;
|
|
mActiveModeWarden = activeModeWarden;
|
|
}
|
|
|
|
/**
|
|
* Enable MBO and OCE functionality.
|
|
*/
|
|
public void enable() {
|
|
ClientModeManager clientModeManager =
|
|
mActiveModeWarden.getPrimaryClientModeManagerNullable();
|
|
if (clientModeManager == null) {
|
|
return;
|
|
}
|
|
long supportedFeatures = clientModeManager.getSupportedFeatures();
|
|
mIsMboSupported = (supportedFeatures & WIFI_FEATURE_MBO) != 0;
|
|
mIsOceSupported = (supportedFeatures & WIFI_FEATURE_OCE) != 0;
|
|
mEnabled = true;
|
|
if (mVerboseLoggingEnabled) {
|
|
Log.d(TAG, "Enable MBO-OCE MBO support: " + mIsMboSupported
|
|
+ " OCE support: " + mIsOceSupported);
|
|
}
|
|
if (mIsMboSupported) {
|
|
// Register for data connection state change events (Cellular).
|
|
mTelephonyManager.listen(mDataConnectionStateListener,
|
|
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable MBO and OCE functionality.
|
|
*/
|
|
public void disable() {
|
|
if (mVerboseLoggingEnabled) {
|
|
Log.d(TAG, "Disable MBO-OCE");
|
|
}
|
|
if (mIsMboSupported) {
|
|
// Un-register for data connection state change events (Cellular).
|
|
mTelephonyManager.listen(mDataConnectionStateListener, PhoneStateListener.LISTEN_NONE);
|
|
}
|
|
mEnabled = false;
|
|
}
|
|
|
|
/**
|
|
* Enable/Disable verbose logging.
|
|
*
|
|
* @param verbose true to enable and false to disable.
|
|
*/
|
|
public void enableVerboseLogging(boolean verbose) {
|
|
mVerboseLoggingEnabled = verbose;
|
|
}
|
|
|
|
/**
|
|
* Listen for changes to the data connection state (Cellular).
|
|
*/
|
|
private PhoneStateListener mDataConnectionStateListener = new PhoneStateListener(){
|
|
public void onDataConnectionStateChanged(int state, int networkType) {
|
|
boolean dataAvailable;
|
|
|
|
ClientModeManager clientModeManager =
|
|
mActiveModeWarden.getPrimaryClientModeManagerNullable();
|
|
if (clientModeManager == null) {
|
|
return;
|
|
}
|
|
if (!mEnabled) {
|
|
Log.e(TAG, "onDataConnectionStateChanged called when MBO is disabled!!");
|
|
return;
|
|
}
|
|
if (state == TelephonyManager.DATA_CONNECTED) {
|
|
dataAvailable = true;
|
|
} else if (state == TelephonyManager.DATA_DISCONNECTED) {
|
|
dataAvailable = false;
|
|
} else {
|
|
Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state);
|
|
return;
|
|
}
|
|
if (mVerboseLoggingEnabled) {
|
|
Log.d(TAG, "Cell Data: " + dataAvailable);
|
|
}
|
|
clientModeManager.setMboCellularDataStatus(dataAvailable);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* BtmFrameData carries the data retried from received BTM
|
|
* request frame handled in supplicant.
|
|
*/
|
|
public static class BtmFrameData {
|
|
public @MboOceConstants.BtmResponseStatus int mStatus =
|
|
MboOceConstants.BTM_RESPONSE_STATUS_INVALID;
|
|
public int mBssTmDataFlagsMask = 0;
|
|
public long mBlockListDurationMs = 0;
|
|
public @MboOceConstants.MboTransitionReason int mTransitionReason =
|
|
MboOceConstants.MBO_TRANSITION_REASON_INVALID;
|
|
public @MboOceConstants.MboCellularDataConnectionPreference int mCellPreference =
|
|
MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_INVALID;
|
|
|
|
@Override
|
|
public String toString() {
|
|
return new StringBuilder("BtmFrameData status=").append(mStatus).append(
|
|
", flags=").append(mBssTmDataFlagsMask).append(
|
|
", assocRetryDelay=").append(mBlockListDurationMs).append(
|
|
", transitionReason=").append(mTransitionReason).append(
|
|
", cellPref=").append(mCellPreference).toString();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* OceRssiBasedAssocRejectAttr is extracted from (Re-)Association response frame from an OCE AP
|
|
* to indicate that the AP has rejected the (Re-)Association request on the basis of
|
|
* insufficient RSSI.
|
|
* Refer OCE spec v1.0 section 4.2.2 Table 7.
|
|
*/
|
|
public static class OceRssiBasedAssocRejectAttr {
|
|
/*
|
|
* Delta RSSI - The difference in dB between the minimum RSSI at which
|
|
* the AP would accept a (Re-)Association request from the STA before
|
|
* Retry Delay expires and the AP's measurement of the RSSI at which the
|
|
* (Re-)Association request was received.
|
|
*/
|
|
public int mDeltaRssi;
|
|
/*
|
|
* Retry Delay - The time period in seconds for which the AP will not
|
|
* accept any subsequent (Re-)Association requests from the STA, unless
|
|
* the received RSSI has improved by Delta RSSI.
|
|
*/
|
|
public int mRetryDelayS;
|
|
|
|
public OceRssiBasedAssocRejectAttr(int deltaRssi, int retryDelayS) {
|
|
this.mDeltaRssi = deltaRssi;
|
|
this.mRetryDelayS = retryDelayS;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return new StringBuilder("OceRssiBasedAssocRejectAttr Delta Rssi=")
|
|
.append(mDeltaRssi).append(
|
|
", Retry Delay=").append(mRetryDelayS).toString();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* MboAssocDisallowedAttr is extracted from (Re-)Association response frame from the MBO AP
|
|
* to indicate that the AP is not accepting new associations.
|
|
* Refer MBO spec v1.2 section 4.2.4 Table 13 for the details of reason code.
|
|
*/
|
|
public static class MboAssocDisallowedAttr {
|
|
/*
|
|
* Reason Code - The reason why the AP is not accepting new
|
|
* associations.
|
|
*/
|
|
public @MboOceConstants.MboAssocDisallowedReasonCode int mReasonCode;
|
|
|
|
public MboAssocDisallowedAttr(int reasonCode) {
|
|
mReasonCode = halToFrameworkMboAssocRDisallowedReasonCode(reasonCode);
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return new StringBuilder("MboAssocDisallowedAttr Reason code=")
|
|
.append(mReasonCode).toString();
|
|
}
|
|
|
|
private @MboOceConstants.MboAssocDisallowedReasonCode int
|
|
halToFrameworkMboAssocRDisallowedReasonCode(int reasonCode) {
|
|
switch (reasonCode) {
|
|
case MboAssocDisallowedReasonCode.RESERVED:
|
|
return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED_0;
|
|
case MboAssocDisallowedReasonCode.UNSPECIFIED:
|
|
return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_UNSPECIFIED;
|
|
case MboAssocDisallowedReasonCode.MAX_NUM_STA_ASSOCIATED:
|
|
return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_MAX_NUM_STA_ASSOCIATED;
|
|
case MboAssocDisallowedReasonCode.AIR_INTERFACE_OVERLOADED:
|
|
return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AIR_INTERFACE_OVERLOADED;
|
|
case MboAssocDisallowedReasonCode.AUTH_SERVER_OVERLOADED:
|
|
return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AUTH_SERVER_OVERLOADED;
|
|
case MboAssocDisallowedReasonCode.INSUFFICIENT_RSSI:
|
|
return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_INSUFFICIENT_RSSI;
|
|
default:
|
|
return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED;
|
|
}
|
|
}
|
|
}
|
|
}
|