• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.car.settings.wifi;
18 
19 import android.annotation.FlaggedApi;
20 import android.content.Context;
21 import android.net.wifi.SoftApConfiguration;
22 import android.net.wifi.WifiManager;
23 import android.os.Handler;
24 import android.os.HandlerThread;
25 import android.os.Looper;
26 
27 import androidx.annotation.MainThread;
28 import androidx.annotation.Nullable;
29 import androidx.lifecycle.Lifecycle;
30 import androidx.lifecycle.LifecycleObserver;
31 import androidx.lifecycle.OnLifecycleEvent;
32 
33 import com.android.car.settings.Flags;
34 import com.android.wifitrackerlib.WifiEntry;
35 import com.android.wifitrackerlib.WifiPickerTracker;
36 
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.concurrent.Executor;
40 
41 /**
42  * Manages Wifi configuration: e.g. monitors wifi states, change wifi setting etc.
43  */
44 public class CarWifiManager implements WifiPickerTracker.WifiPickerTrackerCallback,
45         LifecycleObserver {
46     private static final String TAG = "CarWifiManager";
47 
48     private final Context mContext;
49     private final Lifecycle mLifecycle;
50     private final List<Listener> mListeners = new ArrayList<>();
51 
52     private HandlerThread mWorkerThread;
53     @Nullable private WifiPickerTracker mWifiTracker;
54     @Nullable private WifiManager mWifiManager;
55 
56     public interface Listener {
57         /**
58          * Something about wifi setting changed.
59          */
onWifiEntriesChanged()60         void onWifiEntriesChanged();
61 
62         /**
63          * Called when the state of Wifi has changed, the state will be one of
64          * the following.
65          *
66          * <li>{@link WifiManager#WIFI_STATE_DISABLED}</li>
67          * <li>{@link WifiManager#WIFI_STATE_ENABLED}</li>
68          * <li>{@link WifiManager#WIFI_STATE_DISABLING}</li>
69          * <li>{@link WifiManager#WIFI_STATE_ENABLING}</li>
70          * <li>{@link WifiManager#WIFI_STATE_UNKNOWN}</li>
71          * <p>
72          *
73          * @param state The new state of wifi.
74          */
onWifiStateChanged(int state)75         void onWifiStateChanged(int state);
76     }
77 
CarWifiManager(Context context, Lifecycle lifecycle)78     public CarWifiManager(Context context, Lifecycle lifecycle) {
79         mContext = context;
80         mLifecycle = lifecycle;
81         mLifecycle.addObserver(this);
82         mWifiManager = mContext.getSystemService(WifiManager.class);
83         mWorkerThread = new HandlerThread(TAG
84                 + "{" + Integer.toHexString(System.identityHashCode(this)) + "}",
85                 android.os.Process.THREAD_PRIORITY_BACKGROUND);
86         mWorkerThread.start();
87         if (mWifiManager != null) {
88             mWifiTracker = WifiUtil.createWifiPickerTracker(lifecycle, context,
89                     new Handler(Looper.getMainLooper()), mWorkerThread.getThreadHandler(),
90                     /* listener= */ this);
91         }
92     }
93 
94     /**
95      * Lifecycle method to clean up worker thread on destroy.
96      */
97     @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
98     @MainThread
onDestroy()99     public void onDestroy() {
100         if (mWorkerThread != null) {
101             mWorkerThread.quit();
102         }
103         mLifecycle.removeObserver(this);
104     }
105 
106     /**
107      * Adds {@link Listener}.
108      */
addListener(Listener listener)109     public boolean addListener(Listener listener) {
110         return mListeners.add(listener);
111     }
112 
113     /**
114      * Removes {@link Listener}.
115      */
removeListener(Listener listener)116     public boolean removeListener(Listener listener) {
117         return mListeners.remove(listener);
118     }
119 
120     /**
121      * Returns the currently connected Wi-Fi entries or an empty list if there is no Wi-Fi
122      * network connected.
123      */
getConnectedWifiEntries()124     public List<WifiEntry> getConnectedWifiEntries() {
125         if (mWifiManager != null && mWifiManager.isWifiEnabled() && mWifiTracker != null) {
126             return mWifiTracker.getActiveWifiEntries();
127         }
128         return new ArrayList<>();
129     }
130 
131     /**
132      * Returns a list of all reachable Wi-Fi entries, not including the connected Wi-Fi entry.
133      */
getAllWifiEntries()134     public List<WifiEntry> getAllWifiEntries() {
135         return getWifiEntries(false);
136     }
137 
138     /**
139      * Returns a list of saved Wi-Fi entries, not including the connected Wi-Fi entry.
140      */
getSavedWifiEntries()141     public List<WifiEntry> getSavedWifiEntries() {
142         return getWifiEntries(true);
143     }
144 
getWifiEntries(boolean onlySaved)145     private List<WifiEntry> getWifiEntries(boolean onlySaved) {
146         List<WifiEntry> wifiEntries = new ArrayList<WifiEntry>();
147         if (mWifiManager != null && mWifiManager.isWifiEnabled() && mWifiTracker != null) {
148             for (WifiEntry wifiEntry : mWifiTracker.getWifiEntries()) {
149                 // ignore out of reach Wi-Fi entries.
150                 if (shouldIncludeWifiEntry(wifiEntry, onlySaved)) {
151                     wifiEntries.add(wifiEntry);
152                 }
153             }
154         }
155         return wifiEntries;
156     }
157 
shouldIncludeWifiEntry(WifiEntry wifiEntry, boolean onlySaved)158     private boolean shouldIncludeWifiEntry(WifiEntry wifiEntry, boolean onlySaved) {
159         boolean reachable = wifiEntry.getLevel() != WifiEntry.WIFI_LEVEL_UNREACHABLE;
160         return onlySaved
161                 ? reachable && wifiEntry.isSaved()
162                 : reachable;
163     }
164 
165     /**
166      * Returns {@code true} if Wifi is enabled
167      */
isWifiEnabled()168     public boolean isWifiEnabled() {
169         if (mWifiManager != null) {
170             return mWifiManager.isWifiEnabled();
171         }
172         return false;
173     }
174 
175     /**
176      * Returns {@code true} if Wifi tethering is enabled
177      */
isWifiApEnabled()178     public boolean isWifiApEnabled() {
179         if (mWifiManager != null) {
180             return mWifiManager.isWifiApEnabled();
181         }
182         return false;
183     }
184 
185     /**
186      * Gets {@link SoftApConfiguration} for tethering
187      */
188     @Nullable
getSoftApConfig()189     public SoftApConfiguration getSoftApConfig() {
190         if (mWifiManager != null) {
191             return mWifiManager.getSoftApConfiguration();
192         }
193         return null;
194     }
195 
196     /**
197      * Sets {@link SoftApConfiguration} for tethering
198      */
setSoftApConfig(SoftApConfiguration config)199     public void setSoftApConfig(SoftApConfiguration config) {
200         if (mWifiManager != null) {
201             mWifiManager.setSoftApConfiguration(config);
202         }
203     }
204 
205     /**
206      * Gets the country code in ISO 3166 format.
207      */
208     @Nullable
getCountryCode()209     public String getCountryCode() {
210         if (mWifiManager != null) {
211             return mWifiManager.getCountryCode();
212         }
213         return null;
214     }
215 
216     /**
217      * Checks if the chipset supports 5GHz frequency band.
218      */
is5GhzBandSupported()219     public boolean is5GhzBandSupported() {
220         if (mWifiManager != null) {
221             return mWifiManager.is5GHzBandSupported();
222         }
223         return false;
224     }
225 
226     /** Gets the wifi state from {@link WifiManager}. */
getWifiState()227     public int getWifiState() {
228         if (mWifiManager != null) {
229             return mWifiManager.getWifiState();
230         }
231         return WifiManager.WIFI_STATE_UNKNOWN;
232     }
233 
234     /** Sets whether wifi is enabled. */
setWifiEnabled(boolean enabled)235     public boolean setWifiEnabled(boolean enabled) {
236         if (mWifiManager != null) {
237             return mWifiManager.setWifiEnabled(enabled);
238         }
239         return false;
240     }
241 
242     /** Adds callback for Soft AP */
registerSoftApCallback(Executor executor, WifiManager.SoftApCallback callback)243     public void registerSoftApCallback(Executor executor, WifiManager.SoftApCallback callback) {
244         if (mWifiManager != null) {
245             mWifiManager.registerSoftApCallback(executor, callback);
246         }
247     }
248 
249     /** Removes callback for Soft AP */
unregisterSoftApCallback(WifiManager.SoftApCallback callback)250     public void unregisterSoftApCallback(WifiManager.SoftApCallback callback) {
251         if (mWifiManager != null) {
252             mWifiManager.unregisterSoftApCallback(callback);
253         }
254     }
255 
256     /**
257      * Returns whether Wi-Fi Dual Band is supported or not.
258      */
259     @FlaggedApi(Flags.FLAG_HOTSPOT_UI_SPEED_UPDATE)
isDualBandSupported()260     public boolean isDualBandSupported() {
261         if (mWifiManager != null) {
262             return mWifiManager.isBridgedApConcurrencySupported();
263         }
264         return false;
265     }
266 
267     @Override
onWifiEntriesChanged()268     public void onWifiEntriesChanged() {
269         for (Listener listener : mListeners) {
270             listener.onWifiEntriesChanged();
271         }
272     }
273 
274     @Override
onNumSavedNetworksChanged()275     public void onNumSavedNetworksChanged() {
276     }
277 
278     @Override
onNumSavedSubscriptionsChanged()279     public void onNumSavedSubscriptionsChanged() {
280     }
281 
282     @Override
onWifiStateChanged()283     public void onWifiStateChanged() {
284         if (mWifiTracker != null) {
285             int state = mWifiTracker.getWifiState();
286             for (Listener listener : mListeners) {
287                 listener.onWifiStateChanged(state);
288             }
289         }
290     }
291 
292     /**
293      * @return true if this device supports Wi-Fi Easy-connect (Device Provisioning Protocol)
294      */
isEasyConnectSupported()295     public boolean isEasyConnectSupported() {
296         if (mWifiManager != null && mWifiManager.isEasyConnectSupported()) {
297             return true;
298         }
299         return false;
300     }
301 
302     /**
303      * Returns the {@link WifiManager}
304      */
getWifiManager()305     public WifiManager getWifiManager() {
306         return mWifiManager;
307     }
308 }
309