1 /*
2  * Copyright (C) 2024 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.b2b;
18 
19 import android.hardware.wifi.WifiStatusCode;
20 import android.net.wifi.WifiManager;
21 import android.net.wifi.WifiSsid;
22 import android.util.Log;
23 
24 import com.android.server.wifi.ActiveModeWarden;
25 import com.android.server.wifi.WifiNative;
26 import com.android.server.wifi.WifiRoamingConfigStore;
27 
28 import java.io.FileDescriptor;
29 import java.io.PrintWriter;
30 import java.util.Map;
31 
32 public class WifiRoamingModeManager {
33     private static final String TAG = "WifiRoamingModeManager";
34     private final WifiNative mWifiNative;
35     private final WifiRoamingConfigStore mWifiRoamingConfigStore;
36     private final ActiveModeWarden mActiveModeWarden;
37     private boolean mVerboseLoggingEnabled = false;
38 
WifiRoamingModeManager(WifiNative wifiNative, ActiveModeWarden activeModeWarden, WifiRoamingConfigStore wifiRoamingConfigStore)39     public WifiRoamingModeManager(WifiNative wifiNative,
40                                   ActiveModeWarden activeModeWarden,
41                                   WifiRoamingConfigStore wifiRoamingConfigStore) {
42         this.mWifiNative = wifiNative;
43         this.mWifiRoamingConfigStore = wifiRoamingConfigStore;
44         this.mActiveModeWarden = activeModeWarden;
45     }
46 
47     /**
48      * To handle policy updates when device is already in connected state
49      * and also when policy get removed in connected state.
50      */
checkAndUpdatePolicy(String updatedSsid)51     private void checkAndUpdatePolicy(String updatedSsid) {
52         String currentSsid = mActiveModeWarden.getConnectionInfo().getSSID();
53         if (!updatedSsid.equals(currentSsid)) return;
54         String ifaceName = mActiveModeWarden.getPrimaryClientModeManager().getInterfaceName();
55         if (currentSsid != null && ifaceName != null) {
56             if (mVerboseLoggingEnabled) {
57                 Log.i(TAG, "Re-applying roaming policy as it updated");
58             }
59             applyWifiRoamingMode(ifaceName, currentSsid);
60         }
61     }
62 
63     /**
64      * Add a new network roaming policy.
65      *
66      * @param ssid name of the network on which policy is to be added.
67      * @param roamingMode   denotes roaming mode value configured.
68      * @param isDeviceOwner flag denoting whether API is called by the device owner.
69      */
setPerSsidRoamingMode(WifiSsid ssid, @WifiManager.RoamingMode int roamingMode, boolean isDeviceOwner)70     public void setPerSsidRoamingMode(WifiSsid ssid, @WifiManager.RoamingMode int roamingMode,
71                                       boolean isDeviceOwner) {
72         mWifiRoamingConfigStore.addRoamingMode(ssid.toString(), roamingMode, isDeviceOwner);
73         checkAndUpdatePolicy(ssid.toString());
74     }
75 
76     /**
77      * Remove the network roaming policy for the given ssid.
78      *
79      * @param ssid name of the network on which policy is to be removed.
80      * @param isDeviceOwner flag denoting whether API is called by the device owner.
81      */
removePerSsidRoamingMode(WifiSsid ssid, boolean isDeviceOwner)82     public void removePerSsidRoamingMode(WifiSsid ssid, boolean isDeviceOwner) {
83         mWifiRoamingConfigStore.removeRoamingMode(ssid.toString(), isDeviceOwner);
84         checkAndUpdatePolicy(ssid.toString());
85     }
86 
87     /**
88      * Get all the network roaming policies configured.
89      *
90      * @param isDeviceOwner flag denoting whether API is called by the device owner.
91      * @return Map of corresponding policies for the API caller,
92      *         where key is ssid and value is roaming mode/policy configured for that ssid.
93      */
getPerSsidRoamingModes(boolean isDeviceOwner)94     public Map<String, Integer> getPerSsidRoamingModes(boolean isDeviceOwner) {
95         return mWifiRoamingConfigStore.getPerSsidRoamingModes(isDeviceOwner);
96     }
97 
98     /**
99      * Apply roaming policy to the provided network.
100      * If policy does not exist, apply normal roaming policy.
101      *
102      * @param iface represents the name of the wifi interface.
103      * @param ssid  represents the name of the network.
104      */
applyWifiRoamingMode(String iface, String ssid)105     public void applyWifiRoamingMode(String iface, String ssid) {
106         int roamingMode = mWifiRoamingConfigStore.getRoamingMode(ssid);
107         if (mVerboseLoggingEnabled) {
108             Log.i(TAG, "Applying roaming policy for network "
109                     + ssid + " with value " + roamingMode);
110         }
111         @WifiStatusCode int errorCode = mWifiNative.setRoamingMode(iface, roamingMode);
112         switch (errorCode) {
113             case WifiStatusCode.SUCCESS:
114                 if (mVerboseLoggingEnabled) {
115                     Log.d(TAG, "Roaming mode value successfully set to: " + roamingMode);
116                 }
117                 break;
118             case WifiStatusCode.ERROR_NOT_STARTED:
119                 Log.e(TAG, "Failed to set roaming mode as WifiStaIfaceAidlImpl"
120                         + " instance is not created.");
121                 break;
122             case WifiStatusCode.ERROR_WIFI_IFACE_INVALID:
123                 Log.e(TAG, "Failed to set roaming mode as interface is invalid.");
124                 break;
125             case WifiStatusCode.ERROR_INVALID_ARGS:
126                 Log.e(TAG, "Failed to set roaming mode due to invalid parameter "
127                         + roamingMode);
128                 break;
129             default:
130                 Log.e(TAG, "Failed to set roaming mode due to unknown error.");
131         }
132     }
133 
134     /**
135      * Enable verbose logging.
136      */
enableVerboseLogging(boolean verboseEnabled)137     public void enableVerboseLogging(boolean verboseEnabled) {
138         mVerboseLoggingEnabled = verboseEnabled;
139     }
140 
141     /**
142      * Dump roaming policies for debugging.
143      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)144     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
145         mWifiRoamingConfigStore.dump(fd, pw, args);
146     }
147 }
148