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 /** 27 * MboOceController is responsible for controlling MBO and OCE operations. 28 */ 29 public class MboOceController { 30 private static final String TAG = "MboOceController"; 31 32 /** State of MBO/OCE module. */ 33 private boolean mEnabled = false; 34 private boolean mIsMboSupported = false; 35 private boolean mIsOceSupported = false; 36 private boolean mVerboseLoggingEnabled = false; 37 38 private final WifiNative mWifiNative; 39 private final TelephonyManager mTelephonyManager; 40 41 /** 42 * Create new instance of MboOceController. 43 */ MboOceController(TelephonyManager telephonyManager, WifiNative wifiNative)44 public MboOceController(TelephonyManager telephonyManager, 45 WifiNative wifiNative) { 46 mTelephonyManager = telephonyManager; 47 mWifiNative = wifiNative; 48 } 49 50 /** 51 * Enable MBO and OCE functionality. 52 */ enable()53 public void enable() { 54 String iface = mWifiNative.getClientInterfaceName(); 55 if (iface == null) { 56 return; 57 } 58 mIsMboSupported = (mWifiNative.getSupportedFeatureSet(iface) & WIFI_FEATURE_MBO) != 0; 59 mIsOceSupported = (mWifiNative.getSupportedFeatureSet(iface) & WIFI_FEATURE_OCE) != 0; 60 mEnabled = true; 61 if (mVerboseLoggingEnabled) { 62 Log.d(TAG, "Enable MBO-OCE MBO support: " + mIsMboSupported 63 + " OCE support: " + mIsOceSupported); 64 } 65 if (mIsMboSupported) { 66 // Register for data connection state change events (Cellular). 67 mTelephonyManager.listen(mDataConnectionStateListener, 68 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); 69 } 70 } 71 72 /** 73 * Disable MBO and OCE functionality. 74 */ disable()75 public void disable() { 76 if (mVerboseLoggingEnabled) { 77 Log.d(TAG, "Disable MBO-OCE"); 78 } 79 if (mIsMboSupported) { 80 // Un-register for data connection state change events (Cellular). 81 mTelephonyManager.listen(mDataConnectionStateListener, PhoneStateListener.LISTEN_NONE); 82 } 83 mEnabled = false; 84 } 85 86 /** 87 * Enable/Disable verbose logging. 88 * 89 * @param verbose true to enable and false to disable. 90 */ enableVerboseLogging(boolean verbose)91 public void enableVerboseLogging(boolean verbose) { 92 mVerboseLoggingEnabled = verbose; 93 } 94 95 /** 96 * Listen for changes to the data connection state (Cellular). 97 */ 98 private PhoneStateListener mDataConnectionStateListener = new PhoneStateListener(){ 99 public void onDataConnectionStateChanged(int state, int networkType) { 100 boolean dataAvailable; 101 102 String iface = mWifiNative.getClientInterfaceName(); 103 if (iface == null) { 104 return; 105 } 106 if (!mEnabled) { 107 Log.e(TAG, "onDataConnectionStateChanged called when MBO is disabled!!"); 108 return; 109 } 110 if (state == TelephonyManager.DATA_CONNECTED) { 111 dataAvailable = true; 112 } else if (state == TelephonyManager.DATA_DISCONNECTED) { 113 dataAvailable = false; 114 } else { 115 Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state); 116 return; 117 } 118 if (mVerboseLoggingEnabled) { 119 Log.d(TAG, "Cell Data: " + dataAvailable); 120 } 121 mWifiNative.setMboCellularDataStatus(iface, dataAvailable); 122 } 123 }; 124 125 /** 126 * BtmFrameData carries the data retried from received BTM 127 * request frame handled in supplicant. 128 */ 129 public static class BtmFrameData { 130 public @MboOceConstants.BtmResponseStatus int mStatus = 131 MboOceConstants.BTM_RESPONSE_STATUS_INVALID; 132 public int mBssTmDataFlagsMask = 0; 133 public long mBlackListDurationMs = 0; 134 public @MboOceConstants.MboTransitionReason int mTransitionReason = 135 MboOceConstants.MBO_TRANSITION_REASON_INVALID; 136 public @MboOceConstants.MboCellularDataConnectionPreference int mCellPreference = 137 MboOceConstants.MBO_CELLULAR_DATA_CONNECTION_INVALID; 138 139 @Override toString()140 public String toString() { 141 return new StringBuilder("BtmFrameData status=").append(mStatus).append( 142 ", flags=").append(mBssTmDataFlagsMask).append( 143 ", assocRetryDelay=").append(mBlackListDurationMs).append( 144 ", transitionReason=").append(mTransitionReason).append( 145 ", cellPref=").append(mCellPreference).toString(); 146 } 147 } 148 } 149