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
33namespace shill {
34
35class ByteString;
36class ControlInterface;
37class Error;
38class EventDispatcher;
39class KeyValueStore;
40class Manager;
41class Metrics;
42class StoreInterface;
43class Time;
44class WiFiEndpoint;
45class 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.
50class 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 {
59    FrequencyCount() : frequency(0), connection_count(0) {}
60    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
142  bool disable_vht() { return 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