1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi; 18 19 import static android.net.wifi.WifiManager.WIFI_FEATURE_MBO; 20 import static android.net.wifi.WifiManager.WIFI_FEATURE_OCE; 21 22 import android.telephony.PhoneStateListener; 23 import android.telephony.TelephonyManager; 24 import android.util.Log; 25 26 import com.android.server.wifi.SupplicantStaIfaceHal.MboAssocDisallowedReasonCode; 27 28 /** 29 * MboOceController is responsible for controlling MBO and OCE operations. 30 */ 31 public class MboOceController { 32 private static final String TAG = "MboOceController"; 33 34 /** State of MBO/OCE module. */ 35 private boolean mEnabled = false; 36 private boolean mIsMboSupported = false; 37 private boolean mIsOceSupported = false; 38 private boolean mVerboseLoggingEnabled = false; 39 40 private final TelephonyManager mTelephonyManager; 41 private final ActiveModeWarden mActiveModeWarden; 42 43 /** 44 * Create new instance of MboOceController. 45 */ MboOceController(TelephonyManager telephonyManager, ActiveModeWarden activeModeWarden)46 public MboOceController(TelephonyManager telephonyManager, ActiveModeWarden activeModeWarden) { 47 mTelephonyManager = telephonyManager; 48 mActiveModeWarden = activeModeWarden; 49 } 50 51 /** 52 * Enable MBO and OCE functionality. 53 */ enable()54 public void enable() { 55 ClientModeManager clientModeManager = 56 mActiveModeWarden.getPrimaryClientModeManagerNullable(); 57 if (clientModeManager == null) { 58 return; 59 } 60 long supportedFeatures = clientModeManager.getSupportedFeatures(); 61 mIsMboSupported = (supportedFeatures & WIFI_FEATURE_MBO) != 0; 62 mIsOceSupported = (supportedFeatures & WIFI_FEATURE_OCE) != 0; 63 mEnabled = true; 64 if (mVerboseLoggingEnabled) { 65 Log.d(TAG, "Enable MBO-OCE MBO support: " + mIsMboSupported 66 + " OCE support: " + mIsOceSupported); 67 } 68 if (mIsMboSupported) { 69 // Register for data connection state change events (Cellular). 70 mTelephonyManager.listen(mDataConnectionStateListener, 71 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); 72 } 73 } 74 75 /** 76 * Disable MBO and OCE functionality. 77 */ disable()78 public void disable() { 79 if (mVerboseLoggingEnabled) { 80 Log.d(TAG, "Disable MBO-OCE"); 81 } 82 if (mIsMboSupported) { 83 // Un-register for data connection state change events (Cellular). 84 mTelephonyManager.listen(mDataConnectionStateListener, PhoneStateListener.LISTEN_NONE); 85 } 86 mEnabled = false; 87 } 88 89 /** 90 * Enable/Disable verbose logging. 91 * 92 * @param verbose true to enable and false to disable. 93 */ enableVerboseLogging(boolean verbose)94 public void enableVerboseLogging(boolean verbose) { 95 mVerboseLoggingEnabled = verbose; 96 } 97 98 /** 99 * Listen for changes to the data connection state (Cellular). 100 */ 101 private PhoneStateListener mDataConnectionStateListener = new PhoneStateListener(){ 102 public void onDataConnectionStateChanged(int state, int networkType) { 103 boolean dataAvailable; 104 105 ClientModeManager clientModeManager = 106 mActiveModeWarden.getPrimaryClientModeManagerNullable(); 107 if (clientModeManager == null) { 108 return; 109 } 110 if (!mEnabled) { 111 Log.e(TAG, "onDataConnectionStateChanged called when MBO is disabled!!"); 112 return; 113 } 114 if (state == TelephonyManager.DATA_CONNECTED) { 115 dataAvailable = true; 116 } else if (state == TelephonyManager.DATA_DISCONNECTED) { 117 dataAvailable = false; 118 } else { 119 Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state); 120 return; 121 } 122 if (mVerboseLoggingEnabled) { 123 Log.d(TAG, "Cell Data: " + dataAvailable); 124 } 125 clientModeManager.setMboCellularDataStatus(dataAvailable); 126 } 127 }; 128 129 /** 130 * BtmFrameData carries the data retried from received BTM 131 * request frame handled in supplicant. 132 */ 133 public static class BtmFrameData { 134 public @MboOceConstants.BtmResponseStatus int mStatus = 135 MboOceConstants.BTM_RESPONSE_STATUS_INVALID; 136 public int mBssTmDataFlagsMask = 0; 137 public long mBlockListDurationMs = 0; 138 public @MboOceConstants.MboTransitionReason int mTransitionReason = 139 MboOceConstants.MBO_TRANSITION_REASON_INVALID; 140 public @MboOceConstants.MboCellularDataConnectionPreference int mCellPreference = 141 MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_INVALID; 142 143 @Override toString()144 public String toString() { 145 return new StringBuilder("BtmFrameData status=").append(mStatus).append( 146 ", flags=").append(mBssTmDataFlagsMask).append( 147 ", assocRetryDelay=").append(mBlockListDurationMs).append( 148 ", transitionReason=").append(mTransitionReason).append( 149 ", cellPref=").append(mCellPreference).toString(); 150 } 151 } 152 153 /** 154 * OceRssiBasedAssocRejectAttr is extracted from (Re-)Association response frame from an OCE AP 155 * to indicate that the AP has rejected the (Re-)Association request on the basis of 156 * insufficient RSSI. 157 * Refer OCE spec v1.0 section 4.2.2 Table 7. 158 */ 159 public static class OceRssiBasedAssocRejectAttr { 160 /* 161 * Delta RSSI - The difference in dB between the minimum RSSI at which 162 * the AP would accept a (Re-)Association request from the STA before 163 * Retry Delay expires and the AP's measurement of the RSSI at which the 164 * (Re-)Association request was received. 165 */ 166 public int mDeltaRssi; 167 /* 168 * Retry Delay - The time period in seconds for which the AP will not 169 * accept any subsequent (Re-)Association requests from the STA, unless 170 * the received RSSI has improved by Delta RSSI. 171 */ 172 public int mRetryDelayS; 173 OceRssiBasedAssocRejectAttr(int deltaRssi, int retryDelayS)174 public OceRssiBasedAssocRejectAttr(int deltaRssi, int retryDelayS) { 175 this.mDeltaRssi = deltaRssi; 176 this.mRetryDelayS = retryDelayS; 177 } 178 179 @Override toString()180 public String toString() { 181 return new StringBuilder("OceRssiBasedAssocRejectAttr Delta Rssi=") 182 .append(mDeltaRssi).append( 183 ", Retry Delay=").append(mRetryDelayS).toString(); 184 } 185 } 186 187 /** 188 * MboAssocDisallowedAttr is extracted from (Re-)Association response frame from the MBO AP 189 * to indicate that the AP is not accepting new associations. 190 * Refer MBO spec v1.2 section 4.2.4 Table 13 for the details of reason code. 191 */ 192 public static class MboAssocDisallowedAttr { 193 /* 194 * Reason Code - The reason why the AP is not accepting new 195 * associations. 196 */ 197 public @MboOceConstants.MboAssocDisallowedReasonCode int mReasonCode; 198 MboAssocDisallowedAttr(int reasonCode)199 public MboAssocDisallowedAttr(int reasonCode) { 200 mReasonCode = halToFrameworkMboAssocRDisallowedReasonCode(reasonCode); 201 } 202 203 @Override toString()204 public String toString() { 205 return new StringBuilder("MboAssocDisallowedAttr Reason code=") 206 .append(mReasonCode).toString(); 207 } 208 209 private @MboOceConstants.MboAssocDisallowedReasonCode int halToFrameworkMboAssocRDisallowedReasonCode(int reasonCode)210 halToFrameworkMboAssocRDisallowedReasonCode(int reasonCode) { 211 switch (reasonCode) { 212 case MboAssocDisallowedReasonCode.RESERVED: 213 return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED_0; 214 case MboAssocDisallowedReasonCode.UNSPECIFIED: 215 return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_UNSPECIFIED; 216 case MboAssocDisallowedReasonCode.MAX_NUM_STA_ASSOCIATED: 217 return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_MAX_NUM_STA_ASSOCIATED; 218 case MboAssocDisallowedReasonCode.AIR_INTERFACE_OVERLOADED: 219 return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AIR_INTERFACE_OVERLOADED; 220 case MboAssocDisallowedReasonCode.AUTH_SERVER_OVERLOADED: 221 return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AUTH_SERVER_OVERLOADED; 222 case MboAssocDisallowedReasonCode.INSUFFICIENT_RSSI: 223 return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_INSUFFICIENT_RSSI; 224 default: 225 return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED; 226 } 227 } 228 } 229 } 230