mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Fixed a few issues found during test
PiperOrigin-RevId: 457604581
This commit is contained in:
committed by
Copybara-Service
parent
87c76ea235
commit
698b04184a
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "internal/platform/implementation/windows/ble_medium.h"
|
||||
|
||||
#include <chrono> // NOLINT
|
||||
#include <future> // NOLINT
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -21,6 +22,8 @@
|
||||
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/platform/implementation/windows/ble_peripheral.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
@@ -29,6 +32,7 @@
|
||||
#include "winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "winrt/Windows.Storage.Streams.h"
|
||||
#include "winrt/base.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
@@ -110,6 +114,10 @@ using ::winrt::Windows::Storage::Streams::DataReader;
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-22621
|
||||
using ::winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
// Represents a time interval as a signed 64-bit integer value.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.timespan?view=winrt-22621
|
||||
using ::winrt::Windows::Foundation::TimeSpan;
|
||||
|
||||
template <typename T>
|
||||
using IVector = winrt::Windows::Foundation::Collections::IVector<T>;
|
||||
|
||||
@@ -132,6 +140,12 @@ bool BleMedium::StartAdvertising(
|
||||
<< " fast advertisement service uuid= 0x"
|
||||
<< absl::BytesToHexString(fast_advertisement_service_uuid);
|
||||
|
||||
if (is_publisher_started_) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "BLE cannot start to advertise again when it is running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
DataWriter data_writer;
|
||||
|
||||
// TODO(b/234229562): Add parsing logic for fast_advertisement_service_uuid
|
||||
@@ -160,58 +174,47 @@ bool BleMedium::StartAdvertising(
|
||||
if (fast_advertisement_service_uuid.empty()) {
|
||||
publisher_ = BluetoothLEAdvertisementPublisher(advertisement_);
|
||||
publisher_.UseExtendedAdvertisement(true);
|
||||
|
||||
publisher_token_ =
|
||||
publisher_.StatusChanged({this, &BleMedium::PublisherHandler});
|
||||
|
||||
publisher_started_promise_ = std::promise<PublisherState>();
|
||||
|
||||
std::future<PublisherState> publisher_state_future =
|
||||
publisher_started_promise_.get_future();
|
||||
|
||||
publisher_.Start();
|
||||
|
||||
return publisher_state_future.get() == PublisherState::kStarted;
|
||||
} else {
|
||||
// Extended Advertisement not supported, must make sure advertisement_bytes
|
||||
// is less than 27 bytes
|
||||
if (advertisement_bytes.size() <= 27) {
|
||||
publisher_ = BluetoothLEAdvertisementPublisher(advertisement_);
|
||||
publisher_.UseExtendedAdvertisement(false);
|
||||
|
||||
publisher_token_ =
|
||||
publisher_.StatusChanged({this, &BleMedium::PublisherHandler});
|
||||
|
||||
publisher_started_promise_ = std::promise<PublisherState>();
|
||||
|
||||
std::future<PublisherState> publisher_state_future =
|
||||
publisher_started_promise_.get_future();
|
||||
|
||||
publisher_.Start();
|
||||
|
||||
return publisher_state_future.get() == PublisherState::kStarted;
|
||||
} else {
|
||||
// otherwise no-op
|
||||
NEARBY_LOGS(INFO) << "Everyone Mode unavailable for hardware that does "
|
||||
"not support Extended Advertising.";
|
||||
publisher_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
publisher_token_ =
|
||||
publisher_.StatusChanged({this, &BleMedium::PublisherHandler});
|
||||
|
||||
publisher_.Start();
|
||||
|
||||
is_publisher_started_ = true;
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartAdvertising started.";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleMedium::StopAdvertising(const std::string& service_id) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StopAdvertising: service_id=" << service_id;
|
||||
|
||||
publisher_stopped_promise_ = std::promise<PublisherState>();
|
||||
|
||||
std::future<PublisherState> publisher_state_future =
|
||||
publisher_stopped_promise_.get_future();
|
||||
if (!is_publisher_started_) {
|
||||
NEARBY_LOGS(WARNING) << "BLE advertising is not running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
publisher_.Stop();
|
||||
|
||||
return publisher_state_future.get() == PublisherState::kStopped;
|
||||
// Don't need to wait for the status becomes to `Stopped`. If application
|
||||
// starts to scanning immediately, the scanning still needs to wait the
|
||||
// stopping to finish.
|
||||
is_publisher_started_ = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleMedium::StartScanning(
|
||||
@@ -222,34 +225,34 @@ bool BleMedium::StartScanning(
|
||||
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartScanning: service_id=" << service_id;
|
||||
|
||||
if (is_watcher_started_) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "BLE cannot start to scan again when it is running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
service_id_ = service_id;
|
||||
advertisement_received_callback_ = std::move(callback);
|
||||
|
||||
watcher_ = BluetoothLEAdvertisementWatcher();
|
||||
watcher_token_ = watcher_.Stopped({this, &BleMedium::WatcherHandler});
|
||||
advertisement_received_token_ =
|
||||
watcher_.Received({this, &BleMedium::AdvertisementReceivedHandler});
|
||||
|
||||
is_watcher_started_ = false;
|
||||
|
||||
watcher_started_promise_ = std::promise<WatcherState>();
|
||||
|
||||
std::future<WatcherState> watcher_state_future =
|
||||
watcher_started_promise_.get_future();
|
||||
|
||||
if (adapter_->IsExtendedAdvertisingSupported()) {
|
||||
watcher_.AllowExtendedAdvertisements(true);
|
||||
}
|
||||
// Active mode indicates that scan request packets will be sent to query for
|
||||
// Scan Response
|
||||
watcher_.ScanningMode(BluetoothLEScanningMode::Active);
|
||||
::winrt::Windows::Devices::Bluetooth::BluetoothSignalStrengthFilter filter;
|
||||
filter.SamplingInterval(TimeSpan(std::chrono::seconds(2)));
|
||||
watcher_.SignalStrengthFilter(filter);
|
||||
watcher_.Start();
|
||||
|
||||
while (!is_watcher_started_) {
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Created) {
|
||||
watcher_started_promise_.set_value(WatcherState::kStarted);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
is_watcher_started_ = true;
|
||||
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartScanning started.";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -257,23 +260,21 @@ bool BleMedium::StopScanning(const std::string& service_id) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StopScanning: service_id=" << service_id;
|
||||
|
||||
is_watcher_stopped_ = false;
|
||||
|
||||
watcher_stopped_promise_ = std::promise<WatcherState>();
|
||||
|
||||
std::future<WatcherState> watcher_state_future =
|
||||
watcher_stopped_promise_.get_future();
|
||||
if (!is_watcher_started_) {
|
||||
NEARBY_LOGS(WARNING) << "BLE scanning is not running.";
|
||||
return false;
|
||||
}
|
||||
|
||||
watcher_.Stop();
|
||||
|
||||
while (!is_watcher_stopped_) {
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Stopped) {
|
||||
watcher_stopped_promise_.set_value(WatcherState::kStopped);
|
||||
watcher_.Stopped(watcher_token_);
|
||||
watcher_.Received(advertisement_received_token_);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Don't need to wait for the status becomes to `Stopped`. If application
|
||||
// starts to scanning immediately, the scanning still needs to wait the
|
||||
// stopping to finish.
|
||||
is_watcher_started_ = false;
|
||||
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Windows Ble stoped scanning successfully for service_id="
|
||||
<< service_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -309,13 +310,22 @@ std::unique_ptr<api::BleSocket> BleMedium::Connect(
|
||||
void BleMedium::PublisherHandler(
|
||||
BluetoothLEAdvertisementPublisher publisher,
|
||||
BluetoothLEAdvertisementPublisherStatusChangedEventArgs args) {
|
||||
// This method is called when publisher's status is changed.
|
||||
switch (args.Status()) {
|
||||
case BluetoothLEAdvertisementPublisherStatus::Created:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium created to advertise.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Started:
|
||||
publisher_started_promise_.set_value(PublisherState::kStarted);
|
||||
break;
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium started to advertise.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Stopping:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium is stopping.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Waiting:
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium is waiting.";
|
||||
return;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Stopped:
|
||||
publisher_stopped_promise_.set_value(PublisherState::kStopped);
|
||||
publisher_.StatusChanged(publisher_token_);
|
||||
NEARBY_LOGS(INFO) << "Nearby BLE Medium stopped to advertise.";
|
||||
break;
|
||||
case BluetoothLEAdvertisementPublisherStatus::Aborted:
|
||||
switch (args.Error()) {
|
||||
@@ -325,181 +335,137 @@ void BleMedium::PublisherHandler(
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium start advertising operation was "
|
||||
"successfully completed or serviced.";
|
||||
publisher_started_promise_.set_value(PublisherState::kStarted);
|
||||
}
|
||||
if (publisher_.Status() ==
|
||||
BluetoothLEAdvertisementPublisherStatus::Stopped) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stop advertising operation was "
|
||||
"successfully completed or serviced.";
|
||||
publisher_stopped_promise_.set_value(PublisherState::kStopped);
|
||||
publisher_.StatusChanged(publisher_token_);
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"unknown errors.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
}
|
||||
break;
|
||||
case BluetoothError::RadioNotAvailable:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"radio not available.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::ResourceInUse:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium advertising failed due to resource in use.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::DeviceNotConnected:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"remote device is not connected.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::DisabledByPolicy:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by policy.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::DisabledByUser:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"disabled by user.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::NotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"hardware not supported.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::TransportNotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"transport not supported.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::ConsentRequired:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium advertising failed due to "
|
||||
"consent required.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
case BluetoothError::OtherError:
|
||||
default:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium advertising failed due to unknown errors.";
|
||||
publisher_started_promise_.set_value(PublisherState::kError);
|
||||
publisher_stopped_promise_.set_value(PublisherState::kError);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// The publisher is stopped. Clean up the running publisher
|
||||
{
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
if (publisher_ != nullptr) {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium cleaned the publisher.";
|
||||
publisher_.StatusChanged(publisher_token_);
|
||||
publisher_ = nullptr;
|
||||
is_publisher_started_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BleMedium::WatcherHandler(
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs args) {
|
||||
// This method is called when watcher stopped. Args give more detailed
|
||||
// information on the reason.
|
||||
switch (args.Error()) {
|
||||
case BluetoothError::Success:
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Started) {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium start scanning operation was "
|
||||
"successfully completed or serviced.";
|
||||
watcher_started_promise_.set_value(WatcherState::kStarted);
|
||||
is_watcher_started_ = true;
|
||||
}
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Stopped) {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stop scanning operation was "
|
||||
"successfully completed or serviced.";
|
||||
watcher_stopped_promise_.set_value(WatcherState::kStopped);
|
||||
watcher_.Stopped(watcher_token_);
|
||||
watcher_.Received(advertisement_received_token_);
|
||||
is_watcher_stopped_ = true;
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to unknown errors.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
}
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stoped to scan successfully.";
|
||||
break;
|
||||
case BluetoothError::RadioNotAvailable:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to radio not available.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
<< "Nearby BLE Medium stoped to scan due to radio not available.";
|
||||
break;
|
||||
case BluetoothError::ResourceInUse:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to resource in use.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
<< "Nearby BLE Medium stoped to scan due to resource in use.";
|
||||
break;
|
||||
case BluetoothError::DeviceNotConnected:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium scanning failed due to "
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"remote device is not connected.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
break;
|
||||
case BluetoothError::DisabledByPolicy:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to disabled by policy.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
<< "Nearby BLE Medium stoped to scan due to disabled by policy.";
|
||||
break;
|
||||
case BluetoothError::DisabledByUser:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to disabled by user.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
<< "Nearby BLE Medium stoped to scan due to disabled by user.";
|
||||
break;
|
||||
case BluetoothError::NotSupported:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to hardware not supported.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
<< "Nearby BLE Medium stoped to scan due to hardware not supported.";
|
||||
break;
|
||||
case BluetoothError::TransportNotSupported:
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium scanning failed due to "
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium stoped to scan due to "
|
||||
"transport not supported.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
break;
|
||||
case BluetoothError::ConsentRequired:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to consent required.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
<< "Nearby BLE Medium stoped to scan due to consent required.";
|
||||
break;
|
||||
case BluetoothError::OtherError:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to unknown errors.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
<< "Nearby BLE Medium stoped to scan due to unknown errors.";
|
||||
break;
|
||||
default:
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Started) {
|
||||
watcher_started_promise_.set_value(WatcherState::kStarted);
|
||||
is_watcher_started_ = true;
|
||||
}
|
||||
if (watcher_.Status() == BluetoothLEAdvertisementWatcherStatus::Stopped) {
|
||||
watcher_stopped_promise_.set_value(WatcherState::kStopped);
|
||||
watcher_.Stopped(watcher_token_);
|
||||
watcher_.Received(advertisement_received_token_);
|
||||
is_watcher_stopped_ = true;
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium scanning failed due to unknown errors.";
|
||||
watcher_started_promise_.set_value(WatcherState::kError);
|
||||
watcher_stopped_promise_.set_value(WatcherState::kError);
|
||||
}
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Nearby BLE Medium stoped to scan due to unknown errors.";
|
||||
break;
|
||||
}
|
||||
|
||||
// No matter the reason, should clean up the watcher if it is not empty.
|
||||
// The BLE V1 interface doesn't have API to return the error to upper layer.
|
||||
{
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
if (watcher_ != nullptr) {
|
||||
NEARBY_LOGS(ERROR) << "Nearby BLE Medium cleaned the watcher.";
|
||||
watcher_.Stopped(watcher_token_);
|
||||
watcher_.Received(advertisement_received_token_);
|
||||
watcher_ = nullptr;
|
||||
is_watcher_started_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BleMedium::AdvertisementReceivedHandler(
|
||||
@@ -508,7 +474,6 @@ void BleMedium::AdvertisementReceivedHandler(
|
||||
// Handle all BLE advertisements and determine whether the BLE Medium
|
||||
// Advertisement Scan Response packet (containing Copresence UUID 0xFEF3 in
|
||||
// 0x16 Service Data) has been received in the handler
|
||||
absl::MutexLock lock(&peripheral_map_mutex_);
|
||||
BluetoothLEAdvertisement advertisement = args.Advertisement();
|
||||
|
||||
for (BluetoothLEAdvertisementDataSection service_data :
|
||||
@@ -543,16 +508,12 @@ void BleMedium::AdvertisementReceivedHandler(
|
||||
std::make_unique<BlePeripheral>();
|
||||
peripheral->SetName(peripheral_name);
|
||||
peripheral->SetAdvertisementBytes(advertisement_data);
|
||||
if (peripheral_map_.contains(peripheral_name)) {
|
||||
if (peripheral_map_[peripheral_name]->GetAdvertisementBytes(
|
||||
service_id_) == advertisement_data) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BlePeripheral* peripheral_ptr = peripheral.get();
|
||||
|
||||
peripheral_map_.emplace(peripheral_name, std::move(peripheral));
|
||||
{
|
||||
absl::MutexLock lock(&peripheral_map_mutex_);
|
||||
peripheral_map_[peripheral_name] = std::move(peripheral);
|
||||
}
|
||||
|
||||
// Received Fast Advertisement packet
|
||||
if (unconsumed_buffer_length <= 27) {
|
||||
|
||||
@@ -84,9 +84,20 @@ class BleMedium : public api::BleMedium {
|
||||
CancellationFlag* cancellation_flag) override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
enum class PublisherState { kStarted = 0, kStopped, kError };
|
||||
|
||||
enum class WatcherState { kStarted = 0, kStopped, kError };
|
||||
void PublisherHandler(
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisher publisher,
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisherStatusChangedEventArgs args);
|
||||
void AdvertisementReceivedHandler(
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementReceivedEventArgs args);
|
||||
void WatcherHandler(::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs args);
|
||||
|
||||
absl::Mutex mutex_;
|
||||
BluetoothAdapter* adapter_;
|
||||
@@ -103,37 +114,17 @@ class BleMedium : public api::BleMedium {
|
||||
|
||||
// WinRT objects
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisher publisher_;
|
||||
BluetoothLEAdvertisementPublisher publisher_ = nullptr;
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher_;
|
||||
BluetoothLEAdvertisementWatcher watcher_ = nullptr;
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisement
|
||||
advertisement_;
|
||||
|
||||
void PublisherHandler(
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisher publisher,
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementPublisherStatusChangedEventArgs args);
|
||||
void AdvertisementReceivedHandler(
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementReceivedEventArgs args);
|
||||
void WatcherHandler(::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcher watcher,
|
||||
::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs args);
|
||||
bool is_publisher_started_ = false;
|
||||
bool is_watcher_started_ = false;
|
||||
|
||||
::winrt::event_token publisher_token_;
|
||||
std::promise<PublisherState> publisher_started_promise_;
|
||||
std::promise<PublisherState> publisher_stopped_promise_;
|
||||
|
||||
::winrt::event_token watcher_token_;
|
||||
std::promise<WatcherState> watcher_started_promise_;
|
||||
std::promise<WatcherState> watcher_stopped_promise_;
|
||||
bool is_watcher_started_ = false;
|
||||
bool is_watcher_stopped_ = false;
|
||||
|
||||
::winrt::event_token advertisement_received_token_;
|
||||
};
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ void BluetoothClassicMedium::OnScanModeChanged(
|
||||
|
||||
bool BluetoothClassicMedium::StartDiscovery(
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback) {
|
||||
NEARBY_LOGS(INFO) << "StartDiscovery is called.";
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
@@ -84,6 +85,7 @@ bool BluetoothClassicMedium::StartDiscovery(
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopDiscovery() {
|
||||
NEARBY_LOGS(INFO) << "StopDiscovery is called.";
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
@@ -136,6 +138,7 @@ void BluetoothClassicMedium::InitializeDeviceWatcher() {
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
NEARBY_LOGS(INFO) << "ConnectToService is called.";
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid not specified.";
|
||||
return nullptr;
|
||||
@@ -354,6 +357,8 @@ bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) {
|
||||
std::unique_ptr<api::BluetoothServerSocket>
|
||||
BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
const std::string& service_uuid) {
|
||||
NEARBY_LOGS(INFO) << "ListenForService is called with service name: "
|
||||
<< service_name << ".";
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid was empty.";
|
||||
return nullptr;
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
|
||||
// Standard C/C++ headers
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
// Nearby connections headers
|
||||
#include "internal/platform/implementation/wifi_hotspot.h"
|
||||
|
||||
// WinRT headers
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.WiFi.h"
|
||||
#include "internal/platform/implementation/windows/generated/winrt/Windows.Devices.WiFiDirect.h"
|
||||
@@ -71,8 +73,9 @@ using ::winrt::Windows::Security::Cryptography::CryptographicBuffer;
|
||||
|
||||
using ::winrt::Windows::Networking::HostName;
|
||||
using ::winrt::Windows::Networking::HostNameType;
|
||||
using ::winrt::Windows::Networking::Connectivity::NetworkInformation;
|
||||
using ::winrt::Windows::Networking::Connectivity::ConnectionProfile;
|
||||
using ::winrt::Windows::Networking::Connectivity::ConnectionProfileDeleteStatus;
|
||||
using ::winrt::Windows::Networking::Connectivity::NetworkInformation;
|
||||
using ::winrt::Windows::Networking::Sockets::StreamSocket;
|
||||
using ::winrt::Windows::Networking::Sockets::StreamSocketListener;
|
||||
using ::winrt::Windows::Networking::Sockets::
|
||||
@@ -244,13 +247,16 @@ class WifiHotspotMedium : public api::WifiHotspotMedium {
|
||||
}
|
||||
|
||||
private:
|
||||
enum Value:char {
|
||||
enum Value : char {
|
||||
kMediumStatusIdle = 0,
|
||||
kMediumStatusAccepting = (1 << 0),
|
||||
kMediumStatusBeaconing = (1 << 1),
|
||||
kMediumStatusConnected = (1 << 2),
|
||||
};
|
||||
|
||||
// Implemented the disconnection to WiFi hotspot, and used to avoid deadlock.
|
||||
bool InternalDisconnectWifiHotspot();
|
||||
|
||||
bool IsIdle() { return medium_status_ == kMediumStatusIdle; }
|
||||
// Advertiser is accepting connection on server socket
|
||||
bool IsAccepting() { return (medium_status_ & kMediumStatusAccepting) != 0; }
|
||||
@@ -280,15 +286,9 @@ class WifiHotspotMedium : public api::WifiHotspotMedium {
|
||||
// Protects to access some members
|
||||
absl::Mutex mutex_;
|
||||
|
||||
// If the WiFi Adaptor supports to start a Hotspot interface.
|
||||
bool hotspot_interface_valid_;
|
||||
|
||||
// Medium Status
|
||||
int medium_status_ = kMediumStatusIdle;
|
||||
|
||||
// Hotspot profiles that Discoverer has connected in the whole session;
|
||||
std::vector<ConnectionProfile> hotspot_profiles_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
// Keep the server socket listener pointer
|
||||
WifiHotspotServerSocket* server_socket_ptr_ ABSL_GUARDED_BY(mutex_) = nullptr;
|
||||
};
|
||||
|
||||
@@ -17,25 +17,20 @@
|
||||
|
||||
// Nearby connections headers
|
||||
#include "internal/platform/cancellation_flag_listener.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/platform/implementation/windows/utils.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
namespace {
|
||||
constexpr int kMaxRetries = 3;
|
||||
constexpr int kRetryIntervalMilliSeconds = 300;
|
||||
constexpr int kMaxScans = 2;
|
||||
constexpr int kMaxRetries = 3;
|
||||
constexpr int kRetryIntervalMilliSeconds = 300;
|
||||
constexpr int kMaxScans = 2;
|
||||
} // namespace
|
||||
|
||||
WifiHotspotMedium::WifiHotspotMedium() {
|
||||
HotspotCredentials hotspot_credentials_;
|
||||
hotspot_interface_valid_ = StartWifiHotspot(&hotspot_credentials_);
|
||||
if (hotspot_interface_valid_)
|
||||
StopWifiHotspot();
|
||||
}
|
||||
WifiHotspotMedium::WifiHotspotMedium() {}
|
||||
|
||||
WifiHotspotMedium::~WifiHotspotMedium() {
|
||||
StopWifiHotspot();
|
||||
@@ -43,14 +38,15 @@ WifiHotspotMedium::~WifiHotspotMedium() {
|
||||
}
|
||||
|
||||
bool WifiHotspotMedium::IsInterfaceValid() const {
|
||||
return hotspot_interface_valid_;
|
||||
// Windows 10 starts to support WiFi direct feature, so don't need to check
|
||||
// feature by OS due to targeting OS version is at leat Windows 10.
|
||||
NEARBY_LOGS(ERROR) << "WiFi hotspot: valid interface found.";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
|
||||
absl::string_view ip_address, int port,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
|
||||
if (ip_address.empty() || port == 0) {
|
||||
NEARBY_LOGS(ERROR) << "no valid service address and port to connect: "
|
||||
<< "ip_address = " << ip_address << ", port = " << port;
|
||||
@@ -85,10 +81,11 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
|
||||
cancellation_flag, [socket]() { socket.CancelIOAsync().get(); });
|
||||
}
|
||||
|
||||
// Try connecting to the service up to kMaxRetries. Because it may fail fisrt
|
||||
// time if DHCP procedure is not finished yet.
|
||||
// Try connecting to the service up to kMaxRetries, because it may fail
|
||||
// first time if DHCP procedure is not finished yet.
|
||||
for (int i = 0; i < kMaxRetries; i++) {
|
||||
try {
|
||||
Sleep(kRetryIntervalMilliSeconds);
|
||||
socket.ConnectAsync(host_name, service_name).get();
|
||||
|
||||
auto wifi_hotspot_socket = std::make_unique<WifiHotspotSocket>(socket);
|
||||
@@ -98,8 +95,7 @@ std::unique_ptr<api::WifiHotspotSocket> WifiHotspotMedium::ConnectToService(
|
||||
return wifi_hotspot_socket;
|
||||
} catch (...) {
|
||||
NEARBY_LOGS(ERROR) << "failed to connect remote service " << ipv4_address
|
||||
<< ":" << port << " for the " << i+1 << " time";
|
||||
Sleep(kRetryIntervalMilliSeconds);
|
||||
<< ":" << port << " for the " << i + 1 << " time";
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@@ -152,16 +148,11 @@ bool WifiHotspotMedium::StartWifiHotspot(
|
||||
publisher_status_changed_token_ =
|
||||
publisher_.StatusChanged({this, &WifiHotspotMedium::OnStatusChanged});
|
||||
listener_ = WiFiDirectConnectionListener();
|
||||
try {
|
||||
listener_.ConnectionRequested(
|
||||
{this, &WifiHotspotMedium::OnConnectionRequested});
|
||||
} catch (winrt::hresult_error const& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": winrt exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
}
|
||||
connection_requested_token_ = listener_.ConnectionRequested(
|
||||
{this, &WifiHotspotMedium::OnConnectionRequested});
|
||||
|
||||
// Normal mode: The device is highly discoverable so long as the app is in the
|
||||
// foreground.
|
||||
// Normal mode: The device is highly discoverable so long as the app is in
|
||||
// the foreground.
|
||||
publisher_.Advertisement().ListenStateDiscoverability(
|
||||
WiFiDirectAdvertisementListenStateDiscoverability::Normal);
|
||||
// Enbale Autonomous GO mode
|
||||
@@ -189,6 +180,8 @@ bool WifiHotspotMedium::StartWifiHotspot(
|
||||
|
||||
// Clean up when fail
|
||||
NEARBY_LOGS(ERROR) << "Windows WiFi Hotspot fails to start";
|
||||
publisher_.StatusChanged(publisher_status_changed_token_);
|
||||
listener_.ConnectionRequested(connection_requested_token_);
|
||||
listener_ = nullptr;
|
||||
publisher_ = nullptr;
|
||||
return false;
|
||||
@@ -207,8 +200,11 @@ bool WifiHotspotMedium::StopWifiHotspot() {
|
||||
publisher_.Stop();
|
||||
publisher_.StatusChanged(publisher_status_changed_token_);
|
||||
listener_.ConnectionRequested(connection_requested_token_);
|
||||
publisher_ = nullptr;
|
||||
listener_ = nullptr;
|
||||
NEARBY_LOGS(INFO) << "succeeded to stop WiFi Hotspot";
|
||||
}
|
||||
|
||||
medium_status_ &= (~kMediumStatusBeaconing);
|
||||
return true;
|
||||
}
|
||||
@@ -228,10 +224,31 @@ fire_and_forget WifiHotspotMedium::OnStatusChanged(
|
||||
.Passphrase()
|
||||
.Password());
|
||||
}
|
||||
return winrt::fire_and_forget();
|
||||
} else if (event.Status() ==
|
||||
WiFiDirectAdvertisementPublisherStatus::Created) {
|
||||
NEARBY_LOGS(INFO) << "Receive WiFi direct/SoftAP Created event.";
|
||||
return winrt::fire_and_forget();
|
||||
} else if (event.Status() ==
|
||||
WiFiDirectAdvertisementPublisherStatus::Stopped) {
|
||||
NEARBY_LOGS(INFO) << "Receive WiFi direct/SoftAP Stopped event.";
|
||||
} else if (event.Status() ==
|
||||
WiFiDirectAdvertisementPublisherStatus::Aborted) {
|
||||
NEARBY_LOGS(INFO) << "Receive WiFi direct/SoftAP Aborted event.";
|
||||
}
|
||||
if (event.Status() == WiFiDirectAdvertisementPublisherStatus::Stopped) {
|
||||
NEARBY_LOGS(INFO) << "Receive WiFi direct/SoftAP stop event";
|
||||
|
||||
// Publisher is stopped. Need to clean up the publisher.
|
||||
{
|
||||
absl::MutexLock lock(&mutex_);
|
||||
if (publisher_ != nullptr) {
|
||||
NEARBY_LOGS(ERROR) << "Windows WiFi Hotspot cleanup.";
|
||||
publisher_.StatusChanged(publisher_status_changed_token_);
|
||||
listener_.ConnectionRequested(connection_requested_token_);
|
||||
listener_ = nullptr;
|
||||
publisher_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
@@ -259,7 +276,7 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
|
||||
|
||||
if (IsConnected()) {
|
||||
NEARBY_LOGS(WARNING) << "Already connected to AP, disconnect first.";
|
||||
DisconnectWifiHotspot();
|
||||
InternalDisconnectWifiHotspot();
|
||||
}
|
||||
|
||||
auto access = WiFiAdapter::RequestAccessAsync().get();
|
||||
@@ -269,12 +286,12 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
|
||||
return false;
|
||||
}
|
||||
|
||||
auto adaptors = WiFiAdapter::FindAllAdaptersAsync().get();
|
||||
if (adaptors.Size() < 1) {
|
||||
NEARBY_LOGS(WARNING) << "No WiFi Adaptor found.";
|
||||
auto adapters = WiFiAdapter::FindAllAdaptersAsync().get();
|
||||
if (adapters.Size() < 1) {
|
||||
NEARBY_LOGS(WARNING) << "No WiFi Adapter found.";
|
||||
return false;
|
||||
}
|
||||
wifi_adapter_ = adaptors.GetAt(0);
|
||||
wifi_adapter_ = adapters.GetAt(0);
|
||||
|
||||
// SoftAP is an abbreviation for "software enabled access point".
|
||||
WiFiAvailableNetwork nearby_softap{nullptr};
|
||||
@@ -283,6 +300,8 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
|
||||
|
||||
// First time scan may not find our target hotspot, try 2 more times can
|
||||
// almost guarantee to find the Hotspot
|
||||
wifi_adapter_.ScanAsync().get();
|
||||
|
||||
for (int i = 0; i < kMaxScans; i++) {
|
||||
for (const auto& network :
|
||||
wifi_adapter_.NetworkReport().AvailableNetworks()) {
|
||||
@@ -311,54 +330,76 @@ bool WifiHotspotMedium::ConnectWifiHotspot(
|
||||
.ConnectAsync(nearby_softap, WiFiReconnectionKind::Manual, creds)
|
||||
.get();
|
||||
|
||||
if (connect_result.ConnectionStatus() != WiFiConnectionStatus::Success) {
|
||||
if (connect_result == nullptr ||
|
||||
connect_result.ConnectionStatus() != WiFiConnectionStatus::Success) {
|
||||
NEARBY_LOGS(INFO) << "Connecting failed with reason: "
|
||||
<< static_cast<int>(connect_result.ConnectionStatus());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string last_ssid = hotspot_credentials_->GetSSID();
|
||||
NEARBY_LOGS(INFO) << "Connected to: " << last_ssid;
|
||||
medium_status_ |= kMediumStatusConnected;
|
||||
|
||||
Sleep(50);
|
||||
auto profile =
|
||||
wifi_adapter_.NetworkAdapter().GetConnectedProfileAsync().get();
|
||||
if (profile.IsWlanConnectionProfile()) {
|
||||
if (winrt::to_string(
|
||||
profile.WlanConnectionProfileDetails().GetConnectedSsid()) ==
|
||||
last_ssid) {
|
||||
hotspot_profiles_.push_back(profile);
|
||||
NEARBY_LOGS(INFO) << "Save WiFi profile with SSID: " << last_ssid;
|
||||
}
|
||||
}
|
||||
NEARBY_LOGS(INFO) << "Connected to hotspot: " << last_ssid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WifiHotspotMedium::DisconnectWifiHotspot() {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return InternalDisconnectWifiHotspot();
|
||||
}
|
||||
|
||||
if (!hotspot_profiles_.empty()) {
|
||||
for (auto profile : hotspot_profiles_) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Delete WiFi profile with SSID: "
|
||||
<< winrt::to_string(
|
||||
profile.WlanConnectionProfileDetails().GetConnectedSsid())
|
||||
<< ", result: " << static_cast<int>(profile.TryDeleteAsync().get());
|
||||
}
|
||||
hotspot_profiles_.clear();
|
||||
}
|
||||
|
||||
bool WifiHotspotMedium::InternalDisconnectWifiHotspot() {
|
||||
if (!IsConnected()) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "Cannot diconnect SoftAP because it is not connected.";
|
||||
<< "Cannot disconnect SoftAP because it is not connected.";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (wifi_adapter_) {
|
||||
// Gets connected WiFi profile.
|
||||
auto profile =
|
||||
wifi_adapter_.NetworkAdapter().GetConnectedProfileAsync().get();
|
||||
|
||||
// Disconnect to the WiFi connection through the WiFi adapter.
|
||||
wifi_adapter_.Disconnect();
|
||||
NEARBY_LOGS(INFO) << "Disconnect softAP.";
|
||||
wifi_adapter_ = {nullptr};
|
||||
wifi_adapter_ = nullptr;
|
||||
|
||||
// Try to remove the WiFi profile
|
||||
if (profile != nullptr && profile.CanDelete() &&
|
||||
profile.IsWlanConnectionProfile()) {
|
||||
std::string ssid = winrt::to_string(
|
||||
profile.WlanConnectionProfileDetails().GetConnectedSsid());
|
||||
|
||||
auto profile_delete_status = profile.TryDeleteAsync().get();
|
||||
switch (profile_delete_status) {
|
||||
case ConnectionProfileDeleteStatus::Success:
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "WiFi profile with SSID:" << ssid << " is deleted.";
|
||||
break;
|
||||
case ConnectionProfileDeleteStatus::DeniedBySystem:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to delete WiFi profile with SSID:" << ssid
|
||||
<< " due to denied by system.";
|
||||
break;
|
||||
case ConnectionProfileDeleteStatus::DeniedByUser:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to delete WiFi profile with SSID:" << ssid
|
||||
<< " due to denied by user.";
|
||||
break;
|
||||
case ConnectionProfileDeleteStatus::UnknownError:
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to delete WiFi profile with SSID:" << ssid
|
||||
<< " due to unknonw error.";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Disconnected to SoftAP.";
|
||||
}
|
||||
|
||||
medium_status_ &= (~kMediumStatusConnected);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user