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