• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import java.util.BitSet;
29 
30 /**
31  * MboOceController is responsible for controlling MBO and OCE operations.
32  */
33 public class MboOceController {
34     private static final String TAG = "MboOceController";
35 
36     /** State of MBO/OCE module. */
37     private boolean mEnabled = false;
38     private boolean mIsMboSupported = false;
39     private boolean mIsOceSupported = false;
40     private boolean mVerboseLoggingEnabled = false;
41 
42     private final TelephonyManager mTelephonyManager;
43     private final ActiveModeWarden mActiveModeWarden;
44     private final WifiThreadRunner mWifiThreadRunner;
45 
46     /**
47      * Create new instance of MboOceController.
48      */
MboOceController(TelephonyManager telephonyManager, ActiveModeWarden activeModeWarden, WifiThreadRunner wifiThreadRunner)49     public MboOceController(TelephonyManager telephonyManager, ActiveModeWarden activeModeWarden,
50             WifiThreadRunner wifiThreadRunner) {
51         mTelephonyManager = telephonyManager;
52         mActiveModeWarden = activeModeWarden;
53         mWifiThreadRunner = wifiThreadRunner;
54     }
55 
56     /**
57      * Enable MBO and OCE functionality.
58      */
enable()59     public void enable() {
60         ClientModeManager clientModeManager =
61                 mActiveModeWarden.getPrimaryClientModeManagerNullable();
62         if (clientModeManager == null) {
63             return;
64         }
65         BitSet supportedFeatures = clientModeManager.getSupportedFeaturesBitSet();
66         mIsMboSupported = supportedFeatures.get(WIFI_FEATURE_MBO);
67         mIsOceSupported = supportedFeatures.get(WIFI_FEATURE_OCE);
68         mEnabled = true;
69         if (mVerboseLoggingEnabled) {
70             Log.d(TAG, "Enable MBO-OCE MBO support: " + mIsMboSupported
71                     + " OCE support: " + mIsOceSupported);
72         }
73         if (mIsMboSupported) {
74             // Register for data connection state change events (Cellular).
75             mTelephonyManager.listen(mDataConnectionStateListener,
76                     PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
77         }
78     }
79 
80     /**
81      * Disable MBO and OCE functionality.
82      */
disable()83     public void disable() {
84         if (mVerboseLoggingEnabled) {
85             Log.d(TAG, "Disable MBO-OCE");
86         }
87         if (mIsMboSupported) {
88             // Un-register for data connection state change events (Cellular).
89             mTelephonyManager.listen(mDataConnectionStateListener, PhoneStateListener.LISTEN_NONE);
90         }
91         mEnabled = false;
92     }
93 
94     /**
95      * Enable/Disable verbose logging.
96      *
97      * @param verbose true to enable and false to disable.
98      */
enableVerboseLogging(boolean verbose)99     public void enableVerboseLogging(boolean verbose) {
100         mVerboseLoggingEnabled = verbose;
101     }
102 
103     /**
104      * Listen for changes to the data connection state (Cellular).
105      */
106     private PhoneStateListener mDataConnectionStateListener = new PhoneStateListener(){
107         public void onDataConnectionStateChanged(int state, int networkType) {
108             mWifiThreadRunner.post(
109                     () -> {
110                         boolean dataAvailable;
111                         ClientModeManager clientModeManager =
112                                 mActiveModeWarden.getPrimaryClientModeManagerNullable();
113                         if (clientModeManager == null) {
114                             return;
115                         }
116                         if (!mEnabled) {
117                             Log.e(TAG, "onDataConnectionStateChanged called when MBO is "
118                                     + "disabled!!");
119                             return;
120                         }
121                         if (state == TelephonyManager.DATA_CONNECTED) {
122                             dataAvailable = true;
123                         } else if (state == TelephonyManager.DATA_DISCONNECTED) {
124                             dataAvailable = false;
125                         } else {
126                             Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state);
127                             return;
128                         }
129                         if (mVerboseLoggingEnabled) {
130                             Log.d(TAG, "Cell Data: " + dataAvailable);
131                         }
132                         clientModeManager.setMboCellularDataStatus(dataAvailable);
133                     }, TAG + "#onDataConnectionStateChanged"
134             );
135         }
136     };
137 
138     /**
139      * BtmFrameData carries the data retried from received BTM
140      * request frame handled in supplicant.
141      */
142     public static class BtmFrameData {
143         public @MboOceConstants.BtmResponseStatus int mStatus =
144                 MboOceConstants.BTM_RESPONSE_STATUS_INVALID;
145         public int mBssTmDataFlagsMask = 0;
146         public long mBlockListDurationMs = 0;
147         public @MboOceConstants.MboTransitionReason int mTransitionReason =
148                 MboOceConstants.MBO_TRANSITION_REASON_INVALID;
149         public @MboOceConstants.MboCellularDataConnectionPreference int mCellPreference =
150                 MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_INVALID;
151 
152         @Override
toString()153         public String toString() {
154             return new StringBuilder("BtmFrameData status=").append(mStatus).append(
155                     ", flags=").append(mBssTmDataFlagsMask).append(
156                     ", assocRetryDelay=").append(mBlockListDurationMs).append(
157                     ", transitionReason=").append(mTransitionReason).append(
158                     ", cellPref=").append(mCellPreference).toString();
159         }
160     }
161 
162     /**
163      * OceRssiBasedAssocRejectAttr is extracted from (Re-)Association response frame from an OCE AP
164      * to indicate that the AP has rejected the (Re-)Association request on the basis of
165      * insufficient RSSI.
166      * Refer OCE spec v1.0 section 4.2.2 Table 7.
167      */
168     public static class OceRssiBasedAssocRejectAttr {
169         /*
170          * Delta RSSI - The difference in dB between the minimum RSSI at which
171          * the AP would accept a (Re-)Association request from the STA before
172          * Retry Delay expires and the AP's measurement of the RSSI at which the
173          * (Re-)Association request was received.
174          */
175         public int mDeltaRssi;
176         /*
177          * Retry Delay - The time period in seconds for which the AP will not
178          * accept any subsequent (Re-)Association requests from the STA, unless
179          * the received RSSI has improved by Delta RSSI.
180          */
181         public int mRetryDelayS;
182 
OceRssiBasedAssocRejectAttr(int deltaRssi, int retryDelayS)183         public OceRssiBasedAssocRejectAttr(int deltaRssi, int retryDelayS) {
184             this.mDeltaRssi = deltaRssi;
185             this.mRetryDelayS = retryDelayS;
186         }
187 
188         @Override
toString()189         public String toString() {
190             return new StringBuilder("OceRssiBasedAssocRejectAttr Delta Rssi=")
191                     .append(mDeltaRssi).append(
192                     ", Retry Delay=").append(mRetryDelayS).toString();
193         }
194     }
195 
196     /**
197      * MboAssocDisallowedAttr is extracted from (Re-)Association response frame from the MBO AP
198      * to indicate that the AP is not accepting new associations.
199      * Refer MBO spec v1.2 section 4.2.4 Table 13 for the details of reason code.
200      */
201     public static class MboAssocDisallowedAttr {
202         /*
203          * Reason Code - The reason why the AP is not accepting new
204          * associations.
205          */
206         public @MboOceConstants.MboAssocDisallowedReasonCode int mReasonCode;
207 
MboAssocDisallowedAttr(int reasonCode)208         public MboAssocDisallowedAttr(int reasonCode) {
209             mReasonCode = halToFrameworkMboAssocRDisallowedReasonCode(reasonCode);
210         }
211 
212         @Override
toString()213         public String toString() {
214             return new StringBuilder("MboAssocDisallowedAttr Reason code=")
215                     .append(mReasonCode).toString();
216         }
217 
218         private @MboOceConstants.MboAssocDisallowedReasonCode int
halToFrameworkMboAssocRDisallowedReasonCode(int reasonCode)219                 halToFrameworkMboAssocRDisallowedReasonCode(int reasonCode) {
220             switch (reasonCode) {
221                 case MboAssocDisallowedReasonCode.RESERVED:
222                     return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED_0;
223                 case MboAssocDisallowedReasonCode.UNSPECIFIED:
224                     return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_UNSPECIFIED;
225                 case MboAssocDisallowedReasonCode.MAX_NUM_STA_ASSOCIATED:
226                     return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_MAX_NUM_STA_ASSOCIATED;
227                 case MboAssocDisallowedReasonCode.AIR_INTERFACE_OVERLOADED:
228                     return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AIR_INTERFACE_OVERLOADED;
229                 case MboAssocDisallowedReasonCode.AUTH_SERVER_OVERLOADED:
230                     return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_AUTH_SERVER_OVERLOADED;
231                 case MboAssocDisallowedReasonCode.INSUFFICIENT_RSSI:
232                     return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_INSUFFICIENT_RSSI;
233                 default:
234                     return MboOceConstants.MBO_ASSOC_DISALLOWED_REASON_RESERVED;
235             }
236         }
237     }
238 }
239