1 //
2 // Copyright (C) 2013 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 #ifndef SHILL_WIFI_WIFI_PROVIDER_H_
18 #define SHILL_WIFI_WIFI_PROVIDER_H_
19 
20 #include <time.h>
21 
22 #include <deque>
23 #include <map>
24 #include <string>
25 #include <vector>
26 
27 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
28 
29 #include "shill/accessor_interface.h"  // for ByteArrays
30 #include "shill/provider_interface.h"
31 #include "shill/refptr_types.h"
32 
33 namespace shill {
34 
35 class ByteString;
36 class ControlInterface;
37 class Error;
38 class EventDispatcher;
39 class KeyValueStore;
40 class Manager;
41 class Metrics;
42 class StoreInterface;
43 class Time;
44 class WiFiEndpoint;
45 class WiFiService;
46 
47 // The WiFi Provider is the holder of all WiFi Services.  It holds both
48 // visible (created due to an Endpoint becoming visible) and invisible
49 // (created due to user or storage configuration) Services.
50 class WiFiProvider : public ProviderInterface {
51  public:
52   static const char kStorageFrequencies[];
53   static const int kMaxStorageFrequencies;
54   typedef std::map<uint16_t, int64_t> ConnectFrequencyMap;
55   // The key to |ConnectFrequencyMapDated| is the number of days since the
56   // Epoch.
57   typedef std::map<time_t, ConnectFrequencyMap> ConnectFrequencyMapDated;
58   struct FrequencyCount {
FrequencyCountFrequencyCount59     FrequencyCount() : frequency(0), connection_count(0) {}
FrequencyCountFrequencyCount60     FrequencyCount(uint16_t freq, size_t conn)
61         : frequency(freq), connection_count(conn) {}
62     uint16_t frequency;
63     size_t connection_count;  // Number of successful connections at this
64                               // frequency.
65   };
66   typedef std::deque<FrequencyCount> FrequencyCountList;
67 
68   WiFiProvider(ControlInterface* control_interface,
69                EventDispatcher* dispatcher,
70                Metrics* metrics,
71                Manager* manager);
72   ~WiFiProvider() override;
73 
74   // Called by Manager as a part of the Provider interface.  The attributes
75   // used for matching services for the WiFi provider are the SSID, mode and
76   // security parameters.
77   void CreateServicesFromProfile(const ProfileRefPtr& profile) override;
78   ServiceRefPtr FindSimilarService(
79       const KeyValueStore& args, Error* error) const override;
80   ServiceRefPtr GetService(const KeyValueStore& args, Error* error) override;
81   ServiceRefPtr CreateTemporaryService(
82       const KeyValueStore& args, Error* error) override;
83   ServiceRefPtr CreateTemporaryServiceFromProfile(
84       const ProfileRefPtr& profile,
85       const std::string& entry_name,
86       Error* error) override;
87   void Start() override;
88   void Stop() override;
89 
90   // Find a Service this Endpoint should be associated with.
91   virtual WiFiServiceRefPtr FindServiceForEndpoint(
92       const WiFiEndpointConstRefPtr& endpoint);
93 
94   // Find or create a Service for |endpoint| to be associated with.  This
95   // method first calls FindServiceForEndpoint, and failing this, creates
96   // a new Service.  It then associates |endpoint| with this service.
97   virtual void OnEndpointAdded(const WiFiEndpointConstRefPtr& endpoint);
98 
99   // Called by a Device when it removes an Endpoint.  If the Provider
100   // forgets a service as a result, it returns a reference to the
101   // forgotten service, otherwise it returns a null reference.
102   virtual WiFiServiceRefPtr OnEndpointRemoved(
103       const WiFiEndpointConstRefPtr& endpoint);
104 
105   // Called by a Device when it receives notification that an Endpoint
106   // has changed.  Ensure the updated endpoint still matches its
107   // associated service.  If necessary re-assign the endpoint to a new
108   // service, otherwise notify the associated service of the update to
109   // the endpoint.
110   virtual void OnEndpointUpdated(const WiFiEndpointConstRefPtr& endpoint);
111 
112   // Called by a WiFiService when it is unloaded and no longer visible.
113   virtual bool OnServiceUnloaded(const WiFiServiceRefPtr& service);
114 
115   // Get the list of SSIDs for hidden WiFi services we are aware of.
116   virtual ByteArrays GetHiddenSSIDList();
117 
118   // Calls WiFiService::FixupServiceEntries() and adds a UMA metric if
119   // this causes entries to be updated.
120   virtual void LoadAndFixupServiceEntries(Profile* profile);
121 
122   // Save configuration for wifi_provider to |storage|.
123   virtual bool Save(StoreInterface* storage) const;
124 
125   virtual void IncrementConnectCount(uint16_t frequency_mhz);
126 
127   // Returns a list of all of the frequencies on which this device has
128   // connected.  This data is accumulated across multiple shill runs.
129   virtual FrequencyCountList GetScanFrequencies() const;
130 
131   // Report the number of auto connectable services available to uma
132   // metrics.
133   void ReportAutoConnectableServices();
134 
135   // Returns number of services available for auto-connect.
136   virtual int NumAutoConnectableServices();
137 
138   // Returns a list of ByteStrings representing the SSIDs of WiFi services
139   // configured for auto-connect.
140   std::vector<ByteString> GetSsidsConfiguredForAutoConnect();
141 
disable_vht()142   bool disable_vht() { return disable_vht_; }
set_disable_vht(bool disable_vht)143   void set_disable_vht(bool disable_vht) { disable_vht_ = disable_vht; }
144 
145  private:
146   friend class WiFiProviderTest;
147   FRIEND_TEST(WiFiProviderTest, FrequencyMapAgingIllegalDay);
148   FRIEND_TEST(WiFiProviderTest, FrequencyMapBasicAging);
149   FRIEND_TEST(WiFiProviderTest, FrequencyMapToStringList);
150   FRIEND_TEST(WiFiProviderTest, FrequencyMapToStringListEmpty);
151   FRIEND_TEST(WiFiProviderTest, IncrementConnectCount);
152   FRIEND_TEST(WiFiProviderTest, IncrementConnectCountCreateNew);
153   FRIEND_TEST(WiFiProviderTest, LoadAndFixupServiceEntriesDefaultProfile);
154   FRIEND_TEST(WiFiProviderTest, LoadAndFixupServiceEntriesUserProfile);
155   FRIEND_TEST(WiFiProviderTest, LoadAndFixupServiceEntriesNothingToDo);
156   FRIEND_TEST(WiFiProviderTest, StringListToFrequencyMap);
157   FRIEND_TEST(WiFiProviderTest, StringListToFrequencyMapEmpty);
158 
159   typedef std::map<const WiFiEndpoint*, WiFiServiceRefPtr> EndpointServiceMap;
160 
161   static const char kManagerErrorSSIDTooLong[];
162   static const char kManagerErrorSSIDTooShort[];
163   static const char kManagerErrorSSIDRequired[];
164   static const char kManagerErrorUnsupportedSecurityClass[];
165   static const char kManagerErrorUnsupportedSecurityMode[];
166   static const char kManagerErrorUnsupportedServiceMode[];
167   static const char kManagerErrorArgumentConflict[];
168   static const char kFrequencyDelimiter;
169   static const char kStartWeekHeader[];
170   static const time_t kIllegalStartWeek;
171   static const char kStorageId[];
172   static const time_t kWeeksToKeepFrequencyCounts;
173   static const time_t kSecondsPerWeek;
174 
175   // Add a service to the service_ vector and register it with the Manager.
176   WiFiServiceRefPtr AddService(const std::vector<uint8_t>& ssid,
177                                const std::string& mode,
178                                const std::string& security,
179                                bool is_hidden);
180 
181   // Find a service given its properties.
182   WiFiServiceRefPtr FindService(const std::vector<uint8_t>& ssid,
183                                 const std::string& mode,
184                                 const std::string& security) const;
185 
186   // Returns a WiFiServiceRefPtr for unit tests and for down-casting to a
187   // ServiceRefPtr in GetService().
188   WiFiServiceRefPtr GetWiFiService(const KeyValueStore& args, Error* error);
189 
190   // Disassociate the service from its WiFi device and remove it from the
191   // services_ vector.
192   void ForgetService(const WiFiServiceRefPtr& service);
193 
194   void ReportRememberedNetworkCount();
195   void ReportServiceSourceMetrics();
196 
197   // Retrieve a WiFi service's identifying properties from passed-in |args|.
198   // Returns true if |args| are valid and populates |ssid|, |mode|,
199   // |security| and |hidden_ssid|, if successful.  Otherwise, this function
200   // returns false and populates |error| with the reason for failure.  It
201   // is a fatal error if the "Type" parameter passed in |args| is not kWiFi.
202   static bool GetServiceParametersFromArgs(const KeyValueStore& args,
203                                            std::vector<uint8_t>* ssid_bytes,
204                                            std::string* mode,
205                                            std::string* security_method,
206                                            bool* hidden_ssid,
207                                            Error* error);
208   // Retrieve a WiFi service's identifying properties from passed-in |storage|.
209   // Return true if storage contain valid parameter values and populates |ssid|,
210   // |mode|, |security| and |hidden_ssid|. Otherwise, this function returns
211   // false and populates |error| with the reason for failure.
212   static bool GetServiceParametersFromStorage(const StoreInterface* storage,
213                                               const std::string& entry_name,
214                                               std::vector<uint8_t>* ssid_bytes,
215                                               std::string* mode,
216                                               std::string* security_method,
217                                               bool* hidden_ssid,
218                                               Error* error);
219 
220   // Converts frequency profile information from a list of strings of the form
221   // "frequency:connection_count" to a form consistent with
222   // |connect_count_by_frequency_|.  The first string must be of the form
223   // [nnn] where |nnn| is a positive integer that represents the creation time
224   // (number of days since the Epoch) of the data.
225   static time_t StringListToFrequencyMap(
226       const std::vector<std::string>& strings,
227       ConnectFrequencyMap* numbers);
228 
229   // Extracts the start week from the first string in the StringList for
230   // |StringListToFrequencyMap|.
231   static time_t GetStringListStartWeek(const std::string& week_string);
232 
233   // Extracts frequency and connection count from a string from the StringList
234   // for |StringListToFrequencyMap|.  Places those values in |numbers|.
235   static void ParseStringListFreqCount(const std::string& freq_count_string,
236                                        ConnectFrequencyMap* numbers);
237 
238   // Converts frequency profile information from a form consistent with
239   // |connect_count_by_frequency_| to a list of strings of the form
240   // "frequency:connection_count".  The |creation_day| is the day that the
241   // data was first createed (represented as the number of days since the
242   // Epoch).
243   static void FrequencyMapToStringList(time_t creation_day,
244                                        const ConnectFrequencyMap& numbers,
245                                        std::vector<std::string>* strings);
246 
247   ControlInterface* control_interface_;
248   EventDispatcher* dispatcher_;
249   Metrics* metrics_;
250   Manager* manager_;
251 
252   std::vector<WiFiServiceRefPtr> services_;
253   EndpointServiceMap service_by_endpoint_;
254 
255   bool running_;
256 
257   // Map of frequencies at which we've connected and the number of times a
258   // successful connection has been made at that frequency.  Absent frequencies
259   // have not had a successful connection.
260   ConnectFrequencyMap connect_count_by_frequency_;
261   // A number of entries of |ConnectFrequencyMap| stored by date of creation.
262   ConnectFrequencyMapDated connect_count_by_frequency_dated_;
263 
264   // Count of successful wifi connections we've made.
265   int64_t total_frequency_connections_;
266 
267   Time* time_;
268 
269   // Disable 802.11ac Very High Throughput (VHT) connections.
270   bool disable_vht_;
271 
272   DISALLOW_COPY_AND_ASSIGN(WiFiProvider);
273 };
274 
275 }  // namespace shill
276 
277 #endif  // SHILL_WIFI_WIFI_PROVIDER_H_
278