blob: ce8d881d08df53a228d61f881e5edc470d33753b [file] [log] [blame]
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_SCAN_SESSION_H_
#define SHILL_SCAN_SESSION_H_
#include <vector>
#include <base/basictypes.h>
#include "shill/wifi_provider.h"
namespace shill {
// Contains the state of a progressive wifi scan (for example, a list of the
// requested frequencies and an indication of which of those still need to be
// scanned). A wifi scan using ScanSession can transpire across multiple
// requests, each one encompassing a different set of frequencies.
//
// Use this as follows (note, this is shown as synchronous code for clarity
// but it really should be implemented as asynchronous code):
//
// ScanSession scan_session(frequencies_seen_ever, all_scan_frequencies_);
// while (scan_session.HasMoreFrequencies()) {
// scan_session.InitiateScan(scan_session.GetScanFrequencies(
// kScanFraction, kMinScanFrequencies, kMaxScanFrequencies));
// // Wait for scan results.
// }
//
// The sequence for a single scan is:
//
// +-------------+ +--------+
// | ScanSession | | Kernel |
// +---+---------+ +-----+--+
// |--- NL80211_CMD_TRIGGER_SCAN ---------------------------------->|
// |<-- NL80211_CMD_TRIGGER_SCAN (broadcast) -----------------------|
// |<-- NL80211_CMD_NEW_SCAN_RESULTS (broadcast) -------------------|
// |--- NL80211_CMD_GET_SCAN -------------------------------------->|
// |<-- NL80211_CMD_NEW_SCAN_RESULTS (reply, unicast, NLM_F_MULTI) -|
// |<-- NL80211_CMD_NEW_SCAN_RESULTS (reply, unicast, NLM_F_MULTI) -|
// | ... |
// |<-- NL80211_CMD_NEW_SCAN_RESULTS (reply, unicast, NLM_F_MULTI) -|
// | |
//
// ScanSession::OnNewScanBroadcast handles the broadcast
// NL80211_CMD_NEW_SCAN_RESULTS by issuing a NL80211_CMD_GET_SCAN and
// installing OnNewScanUnicast to handle the unicast
// NL80211_CMD_NEW_SCAN_RESULTS.
class ScanSession {
public:
// The frequency lists provide the frequencies that are returned by
// |GetScanFrequencies|. Frequencies are taken, first, from the connected
// list (in order of the number of connections per frequency -- high before
// low) and then from the unconnected list (in the order provided).
ScanSession(const WiFiProvider::FrequencyCountList &connected_frequency_list,
const std::vector<uint16_t> &unconnected_frequency_list);
virtual ~ScanSession();
// Returns true if |ScanSession| contains unscanned frequencies.
bool HasMoreFrequencies() const;
// Scanning WiFi frequencies for access points takes a long time (on the
// order of 100ms per frequency and the kernel doesn't return the result until
// the answers are ready for all the frequencies in the batch). Given this,
// scanning all frequencies in one batch takes a very long time.
// |GetScanFrequencies| is intended to be called multiple times in order to
// get a number of small batches of frequencies to scan. Frequencies most
// likely to yield a successful connection (based on previous connections)
// are returned first followed by less-likely frequencies followed, finally,
// by frequencies to which this machine hasn't connected before.
//
// |GetScanFrequencies| gets the next set of WiFi scan frequencies. Returns
// at least |min_frequencies| (unless fewer frequencies remain from previous
// calls) and no more than |max_frequencies|. Inside these constraints,
// |GetScanFrequencies| tries to return at least the number of frequencies
// required to reach the connection fraction |scan_fraction| out of the total
// number of previous connections. For example, the first call requesting
// 33.3% will return the minimum number frequencies that add up to _at least_
// the 33.3rd percentile of frequencies to which we've successfully connected
// in the past. The next call of 33.3% returns the minimum number of
// frequencies required so that the total of the frequencies returned are _at
// least_ the 66.6th percentile of the frequencies to which we've successfully
// connected.
//
// For example, say we've connected to 3 frequencies before:
// freq a,count=10; freq b,count=5; freq c,count=5.
//
// GetScanFrequencies(.50,2,10) // Returns a & b (|a| reaches %ile but |b| is
// // required to meet the minimum).
// GetScanFrequencies(.51,2,10) // Returns c & 9 frequencies from the list
// // of frequencies to which we've never
// // connected.
virtual std::vector<uint16_t> GetScanFrequencies(float scan_fraction,
size_t min_frequencies,
size_t max_frequencies);
private:
friend class ScanSessionTest;
// Assists with sorting the |connected_frequency_list| passed to the
// constructor.
static bool CompareFrequencyCount(const WiFiProvider::FrequencyCount &first,
const WiFiProvider::FrequencyCount &second);
// List of frequencies, sorted by the number of successful connections for
// each frequency.
WiFiProvider::FrequencyCountList frequency_list_;
size_t total_connections_;
size_t total_connects_provided_;
float total_fraction_wanted_;
DISALLOW_COPY_AND_ASSIGN(ScanSession);
};
} // namespace shill.
#endif // SHILL_SCAN_SESSION_H_