mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 22:56:12 -04:00
Patch recent cls from nearby_connections;
Sync github to replace nearby_connections with nearby. PiperOrigin-RevId: 411609608
This commit is contained in:
+2
-2
@@ -22,12 +22,12 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
|
||||
"//third_party/nearby_connections/cpp:__subpackages__",
|
||||
"//third_party/nearby/cpp:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//absl/strings",
|
||||
"//absl/time",
|
||||
"//absl/types:optional",
|
||||
"//third_party/nearby_connections/cpp/cal/base:types",
|
||||
"//third_party/nearby/cpp/cal/base:types",
|
||||
],
|
||||
)
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "third_party/nearby_connections/cpp/cal/base/ble_types.h"
|
||||
#include "third_party/nearby/cpp/cal/base/ble_types.h"
|
||||
namespace nearby {
|
||||
namespace cal {
|
||||
namespace api {
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
|
||||
"//third_party/nearby_connections/cpp:__subpackages__",
|
||||
"//third_party/nearby/cpp:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//platform/base",
|
||||
|
||||
@@ -25,11 +25,11 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
|
||||
"//third_party/nearby_connections/cpp:__subpackages__",
|
||||
"//third_party/nearby/cpp:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//third_party/nearby_connections/cpp/cal/api:ble",
|
||||
"//third_party/nearby_connections/cpp/cal/base:types",
|
||||
"//third_party/nearby/cpp/cal/api:ble",
|
||||
"//third_party/nearby/cpp/cal/base:types",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -44,7 +44,7 @@ cc_test(
|
||||
":ble",
|
||||
"//testing/base/public:gunit",
|
||||
"//testing/base/public:gunit_main",
|
||||
"//third_party/nearby_connections/cpp/cal/api:ble",
|
||||
"//third_party/nearby_connections/cpp/cal/base:types",
|
||||
"//third_party/nearby/cpp/cal/api:ble",
|
||||
"//third_party/nearby/cpp/cal/base:types",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "third_party/nearby_connections/cpp/cal/public/ble.h"
|
||||
#include "third_party/nearby/cpp/cal/public/ble.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "third_party/nearby_connections/cpp/cal/api/ble.h"
|
||||
#include "third_party/nearby_connections/cpp/cal/base/ble_types.h"
|
||||
#include "third_party/nearby/cpp/cal/api/ble.h"
|
||||
#include "third_party/nearby/cpp/cal/base/ble_types.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace cal {
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "third_party/nearby_connections/cpp/cal/api/ble.h"
|
||||
#include "third_party/nearby_connections/cpp/cal/base/ble_types.h"
|
||||
#include "third_party/nearby/cpp/cal/api/ble.h"
|
||||
#include "third_party/nearby/cpp/cal/base/ble_types.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace cal {
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "third_party/nearby_connections/cpp/cal/api/ble.h"
|
||||
#include "third_party/nearby_connections/cpp/cal/base/ble_types.h"
|
||||
#include "third_party/nearby_connections/cpp/cal/public/ble.h"
|
||||
#include "third_party/nearby/cpp/cal/api/ble.h"
|
||||
#include "third_party/nearby/cpp/cal/base/ble_types.h"
|
||||
#include "third_party/nearby/cpp/cal/public/ble.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace cal {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ cc_library(
|
||||
copts = ["-DCORE_ADAPTER_DLL"],
|
||||
visibility = [
|
||||
"//platform/impl/ios:__subpackages__",
|
||||
"//third_party/nearby_connections/windows:__subpackages__",
|
||||
"//third_party/nearby/windows:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":core_types",
|
||||
|
||||
@@ -87,8 +87,8 @@ cc_library(
|
||||
copts = ["-DCORE_ADAPTER_DLL"],
|
||||
defines = ["NO_WEBRTC"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/core:__pkg__",
|
||||
"//third_party/nearby_connections/cpp/core/internal/fuzzers:__pkg__",
|
||||
"//third_party/nearby/cpp/core:__pkg__",
|
||||
"//third_party/nearby/cpp/core/internal/fuzzers:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
":message_lite",
|
||||
@@ -101,20 +101,20 @@ cc_library(
|
||||
"//third_party/absl/strings",
|
||||
"//third_party/absl/time",
|
||||
"//third_party/absl/types:span",
|
||||
"//third_party/nearby_connections/cpp/analytics",
|
||||
"//third_party/nearby_connections/cpp/core:core_types",
|
||||
"//third_party/nearby_connections/cpp/core/internal/mediums",
|
||||
"//third_party/nearby_connections/cpp/core/internal/mediums:utils",
|
||||
"//third_party/nearby_connections/cpp/platform/api:comm",
|
||||
"//third_party/nearby_connections/cpp/platform/base",
|
||||
"//third_party/nearby_connections/cpp/platform/base:cancellation_flag",
|
||||
"//third_party/nearby_connections/cpp/platform/base:error_code_recorder",
|
||||
"//third_party/nearby_connections/cpp/platform/base:util",
|
||||
"//third_party/nearby_connections/cpp/platform/public:comm",
|
||||
"//third_party/nearby_connections/cpp/platform/public:logging",
|
||||
"//third_party/nearby_connections/cpp/platform/public:types",
|
||||
"//third_party/nearby_connections/proto:connections_enums_portable_proto",
|
||||
"//third_party/nearby_connections/proto/connections:offline_wire_formats_portable_proto",
|
||||
"//third_party/nearby/cpp/analytics",
|
||||
"//third_party/nearby/cpp/core:core_types",
|
||||
"//third_party/nearby/cpp/core/internal/mediums",
|
||||
"//third_party/nearby/cpp/core/internal/mediums:utils",
|
||||
"//third_party/nearby/cpp/platform/api:comm",
|
||||
"//third_party/nearby/cpp/platform/base",
|
||||
"//third_party/nearby/cpp/platform/base:cancellation_flag",
|
||||
"//third_party/nearby/cpp/platform/base:error_code_recorder",
|
||||
"//third_party/nearby/cpp/platform/base:util",
|
||||
"//third_party/nearby/cpp/platform/public:comm",
|
||||
"//third_party/nearby/cpp/platform/public:logging",
|
||||
"//third_party/nearby/cpp/platform/public:types",
|
||||
"//third_party/nearby/proto:connections_enums_portable_proto",
|
||||
"//third_party/nearby/proto/connections:offline_wire_formats_portable_proto",
|
||||
"//third_party/ukey2",
|
||||
],
|
||||
)
|
||||
@@ -126,7 +126,7 @@ cc_library(
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/core:__subpackages__",
|
||||
"//third_party/nearby/cpp/core:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//net/proto2/public:proto2_lite",
|
||||
@@ -148,17 +148,17 @@ cc_library(
|
||||
],
|
||||
defines = ["NO_WEBRTC"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/core:__subpackages__",
|
||||
"//third_party/nearby/cpp/core:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":internal",
|
||||
"//testing/base/public:gunit_for_library_testonly",
|
||||
"//third_party/absl/functional:bind_front",
|
||||
"//third_party/absl/strings",
|
||||
"//third_party/nearby_connections/cpp/core:core_types",
|
||||
"//third_party/nearby_connections/cpp/platform/base",
|
||||
"//third_party/nearby_connections/cpp/platform/base:test_util",
|
||||
"//third_party/nearby_connections/cpp/platform/public:types",
|
||||
"//third_party/nearby/cpp/core:core_types",
|
||||
"//third_party/nearby/cpp/platform/base",
|
||||
"//third_party/nearby/cpp/platform/base:test_util",
|
||||
"//third_party/nearby/cpp/platform/public:types",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -199,18 +199,18 @@ cc_test(
|
||||
"//third_party/absl/synchronization",
|
||||
"//third_party/absl/time",
|
||||
"//third_party/absl/types:span",
|
||||
"//third_party/nearby_connections/cpp/analytics",
|
||||
"//third_party/nearby_connections/cpp/core:core_types",
|
||||
"//third_party/nearby_connections/cpp/core/internal/mediums",
|
||||
"//third_party/nearby_connections/cpp/core/internal/mediums:utils",
|
||||
"//third_party/nearby_connections/cpp/platform/base",
|
||||
"//third_party/nearby_connections/cpp/platform/base:test_util",
|
||||
"//third_party/nearby_connections/cpp/platform/impl/g3", # build_cleaner: keep
|
||||
"//third_party/nearby_connections/cpp/platform/public:comm",
|
||||
"//third_party/nearby_connections/cpp/platform/public:logging",
|
||||
"//third_party/nearby_connections/cpp/platform/public:types",
|
||||
"//third_party/nearby_connections/proto:connections_enums_portable_proto",
|
||||
"//third_party/nearby_connections/proto/connections:offline_wire_formats_portable_proto",
|
||||
"//third_party/nearby/cpp/analytics",
|
||||
"//third_party/nearby/cpp/core:core_types",
|
||||
"//third_party/nearby/cpp/core/internal/mediums",
|
||||
"//third_party/nearby/cpp/core/internal/mediums:utils",
|
||||
"//third_party/nearby/cpp/platform/base",
|
||||
"//third_party/nearby/cpp/platform/base:test_util",
|
||||
"//third_party/nearby/cpp/platform/impl/g3", # build_cleaner: keep
|
||||
"//third_party/nearby/cpp/platform/public:comm",
|
||||
"//third_party/nearby/cpp/platform/public:logging",
|
||||
"//third_party/nearby/cpp/platform/public:types",
|
||||
"//third_party/nearby/proto:connections_enums_portable_proto",
|
||||
"//third_party/nearby/proto/connections:offline_wire_formats_portable_proto",
|
||||
"//third_party/ukey2",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -39,7 +39,7 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
defines = ["NO_WEBRTC"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/core/internal:__subpackages__",
|
||||
"//third_party/nearby/cpp/core/internal:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":utils",
|
||||
@@ -50,15 +50,15 @@ cc_library(
|
||||
"//third_party/absl/strings",
|
||||
"//third_party/absl/strings:str_format",
|
||||
"//third_party/absl/time",
|
||||
"//third_party/nearby_connections/cpp/core:core_types",
|
||||
"//third_party/nearby_connections/cpp/core/internal/mediums/ble_v2",
|
||||
"//third_party/nearby_connections/cpp/platform/base",
|
||||
"//third_party/nearby_connections/cpp/platform/base:cancellation_flag",
|
||||
"//third_party/nearby_connections/cpp/platform/public:comm",
|
||||
"//third_party/nearby_connections/cpp/platform/public:logging",
|
||||
"//third_party/nearby_connections/cpp/platform/public:types",
|
||||
"//third_party/nearby_connections/proto/connections:offline_wire_formats_portable_proto",
|
||||
"//third_party/nearby_connections/proto/mediums:web_rtc_signaling_frames_cc_proto",
|
||||
"//third_party/nearby/cpp/core:core_types",
|
||||
"//third_party/nearby/cpp/core/internal/mediums/ble_v2",
|
||||
"//third_party/nearby/cpp/platform/base",
|
||||
"//third_party/nearby/cpp/platform/base:cancellation_flag",
|
||||
"//third_party/nearby/cpp/platform/public:comm",
|
||||
"//third_party/nearby/cpp/platform/public:logging",
|
||||
"//third_party/nearby/cpp/platform/public:types",
|
||||
"//third_party/nearby/proto/connections:offline_wire_formats_portable_proto",
|
||||
"//third_party/nearby/proto/mediums:web_rtc_signaling_frames_cc_proto",
|
||||
"//third_party/smhasher:libmurmur3",
|
||||
],
|
||||
)
|
||||
@@ -77,14 +77,14 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
defines = ["NO_WEBRTC"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/core/internal:__pkg__",
|
||||
"//third_party/nearby_connections/cpp/core/internal/mediums:__pkg__",
|
||||
"//third_party/nearby/cpp/core/internal:__pkg__",
|
||||
"//third_party/nearby/cpp/core/internal/mediums:__pkg__",
|
||||
],
|
||||
deps = [
|
||||
"//third_party/absl/strings",
|
||||
"//third_party/nearby_connections/cpp/platform/base",
|
||||
"//third_party/nearby_connections/cpp/platform/public:types",
|
||||
"//third_party/nearby_connections/proto/connections:offline_wire_formats_portable_proto",
|
||||
"//third_party/nearby/cpp/platform/base",
|
||||
"//third_party/nearby/cpp/platform/public:types",
|
||||
"//third_party/nearby/proto/connections:offline_wire_formats_portable_proto",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -109,10 +109,10 @@ cc_test(
|
||||
"//testing/base/public:gunit_main",
|
||||
"//third_party/absl/strings",
|
||||
"//third_party/absl/time",
|
||||
"//third_party/nearby_connections/cpp/platform/base",
|
||||
"//third_party/nearby_connections/cpp/platform/base:test_util",
|
||||
"//third_party/nearby_connections/cpp/platform/impl/g3", # build_cleaner: keep
|
||||
"//third_party/nearby_connections/cpp/platform/public:comm",
|
||||
"//third_party/nearby_connections/cpp/platform/public:types",
|
||||
"//third_party/nearby/cpp/platform/base",
|
||||
"//third_party/nearby/cpp/platform/base:test_util",
|
||||
"//third_party/nearby/cpp/platform/impl/g3", # build_cleaner: keep
|
||||
"//third_party/nearby/cpp/platform/public:comm",
|
||||
"//third_party/nearby/cpp/platform/public:types",
|
||||
],
|
||||
)
|
||||
|
||||
+78
-78
@@ -1,78 +1,78 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef CORE_MEDIUM_SELECTOR_H_
|
||||
#define CORE_MEDIUM_SELECTOR_H_
|
||||
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
using Medium = location::nearby::proto::connections::Medium;
|
||||
|
||||
// Generic type: allows definition of a feature T for every Medium.
|
||||
template <typename T>
|
||||
struct MediumSelector {
|
||||
T bluetooth;
|
||||
T ble;
|
||||
T web_rtc;
|
||||
T wifi_lan;
|
||||
|
||||
constexpr MediumSelector() = default;
|
||||
constexpr MediumSelector(const MediumSelector&) = default;
|
||||
constexpr MediumSelector& operator=(const MediumSelector&) = default;
|
||||
constexpr bool Any(T value) const {
|
||||
return bluetooth == value || ble == value || web_rtc == value ||
|
||||
wifi_lan == value;
|
||||
}
|
||||
|
||||
constexpr bool All(T value) const {
|
||||
return bluetooth == value && ble == value && web_rtc == value &&
|
||||
wifi_lan == value;
|
||||
}
|
||||
|
||||
constexpr int Count(T value) const {
|
||||
int count = 0;
|
||||
if (bluetooth == value) count++;
|
||||
if (ble == value) count++;
|
||||
if (wifi_lan == value) count++;
|
||||
if (web_rtc == value) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
constexpr MediumSelector& SetAll(T value) {
|
||||
bluetooth = value;
|
||||
ble = value;
|
||||
web_rtc = value;
|
||||
wifi_lan = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<Medium> GetMediums(T value) const {
|
||||
std::vector<Medium> mediums;
|
||||
// Mediums are sorted in order of decreasing preference.
|
||||
if (wifi_lan == value) mediums.push_back(Medium::WIFI_LAN);
|
||||
if (web_rtc == value) mediums.push_back(Medium::WEB_RTC);
|
||||
if (bluetooth == value) mediums.push_back(Medium::BLUETOOTH);
|
||||
if (ble == value) mediums.push_back(Medium::BLE);
|
||||
return mediums;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // CORE_MEDIUM_SELECTOR_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef CORE_MEDIUM_SELECTOR_H_
|
||||
#define CORE_MEDIUM_SELECTOR_H_
|
||||
|
||||
#include "proto/connections_enums.pb.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
using Medium = location::nearby::proto::connections::Medium;
|
||||
|
||||
// Generic type: allows definition of a feature T for every Medium.
|
||||
template <typename T>
|
||||
struct MediumSelector {
|
||||
T bluetooth;
|
||||
T ble;
|
||||
T web_rtc;
|
||||
T wifi_lan;
|
||||
|
||||
constexpr MediumSelector() = default;
|
||||
constexpr MediumSelector(const MediumSelector&) = default;
|
||||
constexpr MediumSelector& operator=(const MediumSelector&) = default;
|
||||
constexpr bool Any(T value) const {
|
||||
return bluetooth == value || ble == value || web_rtc == value ||
|
||||
wifi_lan == value;
|
||||
}
|
||||
|
||||
constexpr bool All(T value) const {
|
||||
return bluetooth == value && ble == value && web_rtc == value &&
|
||||
wifi_lan == value;
|
||||
}
|
||||
|
||||
constexpr int Count(T value) const {
|
||||
int count = 0;
|
||||
if (bluetooth == value) count++;
|
||||
if (ble == value) count++;
|
||||
if (wifi_lan == value) count++;
|
||||
if (web_rtc == value) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
constexpr MediumSelector& SetAll(T value) {
|
||||
bluetooth = value;
|
||||
ble = value;
|
||||
web_rtc = value;
|
||||
wifi_lan = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::vector<Medium> GetMediums(T value) const {
|
||||
std::vector<Medium> mediums;
|
||||
// Mediums are sorted in order of decreasing preference.
|
||||
if (wifi_lan == value) mediums.push_back(Medium::WIFI_LAN);
|
||||
if (web_rtc == value) mediums.push_back(Medium::WEB_RTC);
|
||||
if (bluetooth == value) mediums.push_back(Medium::BLUETOOTH);
|
||||
if (ble == value) mediums.push_back(Medium::BLE);
|
||||
return mediums;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // CORE_MEDIUM_SELECTOR_H_
|
||||
|
||||
@@ -45,7 +45,7 @@ cc_library(
|
||||
copts = ["-DCORE_ADAPTER_DLL"],
|
||||
visibility = [
|
||||
"//analytics:__subpackages__",
|
||||
"//third_party/nearby_connections/cpp/cal:__subpackages__",
|
||||
"//third_party/nearby/cpp/cal:__subpackages__",
|
||||
"//core:__subpackages__",
|
||||
"//platform:__subpackages__",
|
||||
"//platform/api:__subpackages__",
|
||||
|
||||
@@ -12,23 +12,23 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCAdvertiser.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCAdvertiser.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "third_party/absl/functional/bind_front.h"
|
||||
#include "third_party/nearby_connections/cpp/core/core.h"
|
||||
#include "third_party/nearby_connections/cpp/core/listeners.h"
|
||||
#include "third_party/nearby_connections/cpp/core/options.h"
|
||||
#include "third_party/nearby_connections/cpp/core/params.h"
|
||||
#include "third_party/nearby_connections/cpp/core/status.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/byte_array.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCPayloadListener.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCUtils.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby/cpp/core/core.h"
|
||||
#include "third_party/nearby/cpp/core/listeners.h"
|
||||
#include "third_party/nearby/cpp/core/options.h"
|
||||
#include "third_party/nearby/cpp/core/params.h"
|
||||
#include "third_party/nearby/cpp/core/status.h"
|
||||
#include "third_party/nearby/cpp/platform/base/byte_array.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCPayloadListener.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#import "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -12,15 +12,15 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "third_party/absl/container/flat_hash_map.h"
|
||||
#include "third_party/absl/container/internal/common.h"
|
||||
#include "third_party/nearby_connections/cpp/core/core.h"
|
||||
#include "third_party/nearby_connections/cpp/core/internal/service_controller_router.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/payload_id.h"
|
||||
#include "third_party/nearby/cpp/core/core.h"
|
||||
#include "third_party/nearby/cpp/core/internal/service_controller_router.h"
|
||||
#include "third_party/nearby/cpp/platform/base/payload_id.h"
|
||||
#import "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
using ::location::nearby::connections::Core;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,19 +12,19 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
|
||||
#include "third_party/nearby_connections/cpp/core/core.h"
|
||||
#include "third_party/nearby_connections/cpp/core/payload.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/input_file.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/base/exception.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/input_stream.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/base/payload_id.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/public/file.h"
|
||||
#include "third_party/nearby/cpp/core/core.h"
|
||||
#include "third_party/nearby/cpp/core/payload.h"
|
||||
#include "third_party/nearby/cpp/platform/api/input_file.h"
|
||||
#import "third_party/nearby/cpp/platform/base/exception.h"
|
||||
#include "third_party/nearby/cpp/platform/base/input_stream.h"
|
||||
#import "third_party/nearby/cpp/platform/base/payload_id.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby/cpp/platform/public/file.h"
|
||||
|
||||
using ::location::nearby::ByteArrayFromNSData;
|
||||
using ::location::nearby::CppStringFromObjCString;
|
||||
|
||||
@@ -12,23 +12,23 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCDiscoverer.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCDiscoverer.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "third_party/absl/functional/bind_front.h"
|
||||
#include "third_party/nearby_connections/cpp/core/core.h"
|
||||
#include "third_party/nearby_connections/cpp/core/listeners.h"
|
||||
#include "third_party/nearby_connections/cpp/core/options.h"
|
||||
#include "third_party/nearby_connections/cpp/core/status.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/byte_array.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCPayloadListener.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCUtils.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby/cpp/core/core.h"
|
||||
#include "third_party/nearby/cpp/core/listeners.h"
|
||||
#include "third_party/nearby/cpp/core/options.h"
|
||||
#include "third_party/nearby/cpp/core/status.h"
|
||||
#include "third_party/nearby/cpp/platform/base/byte_array.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCPayloadListener.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#import "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,23 +12,23 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCPayloadListener.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCPayloadListener.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "third_party/nearby_connections/cpp/core/core.h"
|
||||
#include "third_party/nearby_connections/cpp/core/listeners.h"
|
||||
#include "third_party/nearby_connections/cpp/core/payload.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/byte_array.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/exception.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/input_stream.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCPayload+Internal.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/public/file.h"
|
||||
#include "third_party/nearby/cpp/core/core.h"
|
||||
#include "third_party/nearby/cpp/core/listeners.h"
|
||||
#include "third_party/nearby/cpp/core/payload.h"
|
||||
#include "third_party/nearby/cpp/platform/base/byte_array.h"
|
||||
#include "third_party/nearby/cpp/platform/base/exception.h"
|
||||
#include "third_party/nearby/cpp/platform/base/input_stream.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCPayload.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCoreConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCPayload+Internal.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby/cpp/platform/public/file.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
#include "core/listeners.h"
|
||||
#include "core/options.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCAdvertiser.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCAdvertiser.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCUtils.h"
|
||||
|
||||
#include "third_party/nearby_connections/cpp/core/strategy.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCAdvertiser.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
#include "third_party/nearby/cpp/core/strategy.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCAdvertiser.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/GNCConnection.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,26 +12,26 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "third_party/nearby_connections/cpp/platform/api/platform.h"
|
||||
#include "third_party/nearby/cpp/platform/api/platform.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "third_party/nearby_connections/cpp/platform/api/mutex.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/payload_id.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/atomic_boolean.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/atomic_uint32.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/condition_variable.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/count_down_latch.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/input_file.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/log_message.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/multi_thread_executor.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/mutex.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/single_thread_executor.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/wifi_lan.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/shared/file.h"
|
||||
#include "third_party/nearby/cpp/platform/api/mutex.h"
|
||||
#include "third_party/nearby/cpp/platform/base/payload_id.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Internal/GNCCore.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/atomic_boolean.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/atomic_uint32.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/condition_variable.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/count_down_latch.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/input_file.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/log_message.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/multi_thread_executor.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/mutex.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/single_thread_executor.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/wifi_lan.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/shared/file.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCLeaks.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCLeaks.h"
|
||||
|
||||
void GNCVerifyDealloc(id object, NSTimeInterval timeInterval) {
|
||||
#if DEBUG
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourBrowser.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourBrowser.h"
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourUtils.h"
|
||||
#import "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
typedef NSString *GNCEndpointId;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourConnection.h"
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
enum { kMaxPacketSize = 32 * 1024 };
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourService.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourService.h"
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourUtils.h"
|
||||
#import "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
@interface GNCMBonjourService () <NSNetServiceDelegate>
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourUtils.h"
|
||||
|
||||
NSString *const GNCMBonjourDomain = @"local";
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "third_party/nearby_connections/cpp/platform/api/crypto.h"
|
||||
#include "third_party/nearby/cpp/platform/api/crypto.h"
|
||||
|
||||
#import "third_party/absl/strings/string_view.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Shared/GNCUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Shared/GNCUtils.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
@@ -12,12 +12,12 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/input_file.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/input_file.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/base/exception.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#import "third_party/nearby/cpp/platform/base/exception.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/log_message.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/log_message.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/log_message.h"
|
||||
#include "third_party/nearby/cpp/platform/api/log_message.h"
|
||||
#include "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
namespace location {
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#define PLATFORM_IMPL_IOS_MULTI_THREAD_EXECUTOR_H_
|
||||
|
||||
#include "platform/api/submittable_executor.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/base/runnable.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
#import "third_party/nearby/cpp/platform/base/runnable.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/multi_thread_executor.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/multi_thread_executor.h"
|
||||
|
||||
#include "third_party/nearby_connections/cpp/platform/base/runnable.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
#include "third_party/nearby/cpp/platform/base/runnable.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/scheduled_executor.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include "third_party/absl/time/time.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/runnable.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/atomic_boolean.h"
|
||||
#include "third_party/nearby/cpp/platform/base/runnable.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/atomic_boolean.h"
|
||||
|
||||
// This wraps the C++ Runnable in an Obj-C object for memory management. It is retained by the
|
||||
// dispatch block below, and deleted when the block is released.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#ifndef PLATFORM_IMPL_IOS_SINGLE_THREAD_EXECUTOR_H_
|
||||
#define PLATFORM_IMPL_IOS_SINGLE_THREAD_EXECUTOR_H_
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/multi_thread_executor.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/multi_thread_executor.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
|
||||
#import "third_party/absl/container/flat_hash_map.h"
|
||||
#include "third_party/absl/strings/string_view.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/byte_array.h"
|
||||
#include "third_party/nearby/cpp/platform/base/byte_array.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "platform/api/wifi_lan.h"
|
||||
#include "platform/base/nsd_service_info.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h" // IWYU pragma: export
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h" // IWYU pragma: export
|
||||
|
||||
@class GNCMBonjourBrowser;
|
||||
@class GNCMBonjourService;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/wifi_lan.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/wifi_lan.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -24,15 +24,15 @@
|
||||
#include "third_party/absl/strings/str_cat.h"
|
||||
#include "third_party/absl/strings/str_format.h"
|
||||
#include "third_party/absl/synchronization/mutex.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/wifi_lan.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/cancellation_flag.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/exception.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/nsd_service_info.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/prng.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourBrowser.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourService.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby/cpp/platform/api/wifi_lan.h"
|
||||
#include "third_party/nearby/cpp/platform/base/cancellation_flag.h"
|
||||
#include "third_party/nearby/cpp/platform/base/exception.h"
|
||||
#include "third_party/nearby/cpp/platform/base/nsd_service_info.h"
|
||||
#include "third_party/nearby/cpp/platform/base/prng.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/GNCMConnection.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourBrowser.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Mediums/WifiLan/GNCMBonjourService.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#import "third_party/objective_c/google_toolbox_for_mac/Foundation/GTMLogger.h"
|
||||
|
||||
namespace location {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Shared/GNCUtils.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Shared/GNCUtils.h"
|
||||
|
||||
#import <CommonCrypto/CommonDigest.h>
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "third_party/nearby_connections/cpp/platform/api/crypto.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/byte_array.h"
|
||||
#include "third_party/nearby/cpp/platform/api/crypto.h"
|
||||
#include "third_party/nearby/cpp/platform/base/byte_array.h"
|
||||
|
||||
@interface GNCCryptoTest : XCTestCase
|
||||
@end
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "third_party/nearby_connections/cpp/platform/base/byte_array.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/base/exception.h"
|
||||
#import "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/input_file.h"
|
||||
#import "third_party/nearby/cpp/platform/base/byte_array.h"
|
||||
#import "third_party/nearby/cpp/platform/base/exception.h"
|
||||
#import "third_party/nearby/cpp/platform/impl/ios/Source/Platform/input_file.h"
|
||||
|
||||
using ::location::nearby::ios::InputFile;
|
||||
using ::location::nearby::ByteArray;
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "third_party/absl/time/time.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/cancelable.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/executor.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/platform.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/submittable_executor.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/runnable.h"
|
||||
#include "third_party/nearby/cpp/platform/api/cancelable.h"
|
||||
#include "third_party/nearby/cpp/platform/api/executor.h"
|
||||
#include "third_party/nearby/cpp/platform/api/platform.h"
|
||||
#include "third_party/nearby/cpp/platform/api/submittable_executor.h"
|
||||
#include "third_party/nearby/cpp/platform/base/runnable.h"
|
||||
|
||||
using location::nearby::Runnable;
|
||||
using location::nearby::api::ImplementationPlatform;
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "third_party/absl/time/time.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/cancelable.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/executor.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/platform.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/scheduled_executor.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/runnable.h"
|
||||
#include "third_party/nearby/cpp/platform/api/cancelable.h"
|
||||
#include "third_party/nearby/cpp/platform/api/executor.h"
|
||||
#include "third_party/nearby/cpp/platform/api/platform.h"
|
||||
#include "third_party/nearby/cpp/platform/api/scheduled_executor.h"
|
||||
#include "third_party/nearby/cpp/platform/base/runnable.h"
|
||||
|
||||
using location::nearby::Runnable;
|
||||
using location::nearby::api::ImplementationPlatform;
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "third_party/absl/time/time.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/cancelable.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/executor.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/platform.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/api/submittable_executor.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/base/runnable.h"
|
||||
#include "third_party/nearby/cpp/platform/api/cancelable.h"
|
||||
#include "third_party/nearby/cpp/platform/api/executor.h"
|
||||
#include "third_party/nearby/cpp/platform/api/platform.h"
|
||||
#include "third_party/nearby/cpp/platform/api/submittable_executor.h"
|
||||
#include "third_party/nearby/cpp/platform/base/runnable.h"
|
||||
|
||||
using location::nearby::Runnable;
|
||||
using location::nearby::api::ImplementationPlatform;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#include "third_party/nearby_connections/cpp/platform/base/byte_array.h"
|
||||
#include "third_party/nearby_connections/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
#include "third_party/nearby/cpp/platform/base/byte_array.h"
|
||||
#include "third_party/nearby/cpp/platform/impl/ios/Source/Platform/utils.h"
|
||||
|
||||
using location::nearby::ByteArray;
|
||||
using location::nearby::ByteArrayFromNSData;
|
||||
|
||||
@@ -110,9 +110,9 @@ cc_library(
|
||||
"wifi_lan_socket.cc",
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
copts = ["-Ithird_party/nearby_connections/cpp/platform/impl/windows/generated"],
|
||||
copts = ["-Ithird_party/nearby/cpp/platform/impl/windows/generated"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/windows:__subpackages__",
|
||||
"//third_party/nearby/windows:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":comm",
|
||||
@@ -138,7 +138,7 @@ cc_library(
|
||||
"test_utils.h",
|
||||
],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/windows:__subpackages__",
|
||||
"//third_party/nearby/windows:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//platform/base",
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/atomic_reference.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(atomic_reference, SuccessfulCreation) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = UINT32_MAX;
|
||||
const uint32_t expected = 0;
|
||||
|
||||
// Act
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(atomic_reference, SuccessfulMaxSet) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = 0;
|
||||
const uint32_t expected = UINT32_MAX;
|
||||
|
||||
// Act
|
||||
atomicUint32.Set(UINT32_MAX);
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(atomic_reference, SuccessfulMinSet) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = UINT32_MAX;
|
||||
const uint32_t expected = 0;
|
||||
|
||||
// Act
|
||||
atomicUint32.Set(0);
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(atomic_reference, SetNegativeOneReturnsMAXUINT) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = 0;
|
||||
const uint32_t expected = UINT32_MAX;
|
||||
|
||||
// Act
|
||||
atomicUint32.Set(-1); // Try Set -1, should actually store UINT32_MAX
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/atomic_reference.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(atomic_reference, SuccessfulCreation) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = UINT32_MAX;
|
||||
const uint32_t expected = 0;
|
||||
|
||||
// Act
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(atomic_reference, SuccessfulMaxSet) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = 0;
|
||||
const uint32_t expected = UINT32_MAX;
|
||||
|
||||
// Act
|
||||
atomicUint32.Set(UINT32_MAX);
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(atomic_reference, SuccessfulMinSet) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = UINT32_MAX;
|
||||
const uint32_t expected = 0;
|
||||
|
||||
// Act
|
||||
atomicUint32.Set(0);
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(atomic_reference, SetNegativeOneReturnsMAXUINT) {
|
||||
// Arrange
|
||||
location::nearby::windows::AtomicUint32 atomicUint32;
|
||||
uint32_t result = 0;
|
||||
const uint32_t expected = UINT32_MAX;
|
||||
|
||||
// Act
|
||||
atomicUint32.Set(-1); // Try Set -1, should actually store UINT32_MAX
|
||||
result = atomicUint32.Get();
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
|
||||
#include <winstring.h>
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
|
||||
#include "platform/impl/windows/utils.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothDevice::~BluetoothDevice() {}
|
||||
|
||||
BluetoothDevice::BluetoothDevice(
|
||||
const winrt::Windows::Devices::Bluetooth::BluetoothDevice& bluetoothDevice)
|
||||
: windows_bluetooth_device_(bluetoothDevice) {
|
||||
id_ = winrt::to_string(bluetoothDevice.DeviceId());
|
||||
|
||||
// Get the device address.
|
||||
auto bluetoothAddress = bluetoothDevice.BluetoothAddress();
|
||||
|
||||
mac_address_ = uint64_to_mac_address_string(bluetoothAddress);
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName()
|
||||
std::string BluetoothDevice::GetName() const {
|
||||
return winrt::to_string(windows_bluetooth_device_.Name());
|
||||
}
|
||||
|
||||
// Returns BT MAC address assigned to this device.
|
||||
std::string BluetoothDevice::GetMacAddress() const { return mac_address_; }
|
||||
|
||||
// We are using Uncached because:
|
||||
// For the following APIs, Cached means only use values cached in the system
|
||||
// cached (if not cached then don't fall back to querying the device).
|
||||
// The device may be present, but not entered into the cache yet, so always
|
||||
// check the actual device.
|
||||
IAsyncOperation<RfcommDeviceServicesResult>
|
||||
BluetoothDevice::GetRfcommServicesForIdAsync(const RfcommServiceId serviceId) {
|
||||
return windows_bluetooth_device_.GetRfcommServicesForIdAsync(
|
||||
serviceId, BluetoothCacheMode::Uncached);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
|
||||
#include <winstring.h>
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
|
||||
#include "platform/impl/windows/utils.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothDevice::~BluetoothDevice() {}
|
||||
|
||||
BluetoothDevice::BluetoothDevice(
|
||||
const winrt::Windows::Devices::Bluetooth::BluetoothDevice& bluetoothDevice)
|
||||
: windows_bluetooth_device_(bluetoothDevice) {
|
||||
id_ = winrt::to_string(bluetoothDevice.DeviceId());
|
||||
|
||||
// Get the device address.
|
||||
auto bluetoothAddress = bluetoothDevice.BluetoothAddress();
|
||||
|
||||
mac_address_ = uint64_to_mac_address_string(bluetoothAddress);
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getName()
|
||||
std::string BluetoothDevice::GetName() const {
|
||||
return winrt::to_string(windows_bluetooth_device_.Name());
|
||||
}
|
||||
|
||||
// Returns BT MAC address assigned to this device.
|
||||
std::string BluetoothDevice::GetMacAddress() const { return mac_address_; }
|
||||
|
||||
// We are using Uncached because:
|
||||
// For the following APIs, Cached means only use values cached in the system
|
||||
// cached (if not cached then don't fall back to querying the device).
|
||||
// The device may be present, but not entered into the cache yet, so always
|
||||
// check the actual device.
|
||||
IAsyncOperation<RfcommDeviceServicesResult>
|
||||
BluetoothDevice::GetRfcommServicesForIdAsync(const RfcommServiceId serviceId) {
|
||||
return windows_bluetooth_device_.GetRfcommServicesForIdAsync(
|
||||
serviceId, BluetoothCacheMode::Uncached);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -1,443 +1,443 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_medium.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <regex> // NOLINT
|
||||
#include <string>
|
||||
|
||||
#include "platform/base/cancellation_flag.h"
|
||||
#include "platform/base/cancellation_flag_listener.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_server_socket.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.Collections.h"
|
||||
#include "platform/impl/windows/generated/winrt/base.h"
|
||||
#include "platform/impl/windows/utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothClassicMedium::BluetoothClassicMedium(
|
||||
api::BluetoothAdapter& bluetoothAdapter)
|
||||
: bluetooth_adapter_(dynamic_cast<BluetoothAdapter&>(bluetoothAdapter)) {
|
||||
InitializeCriticalSection(&critical_section_);
|
||||
|
||||
InitializeDeviceWatcher();
|
||||
|
||||
bluetooth_adapter_.SetOnScanModeChanged(std::bind(
|
||||
&BluetoothClassicMedium::OnScanModeChanged, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
BluetoothClassicMedium::~BluetoothClassicMedium() {}
|
||||
|
||||
void BluetoothClassicMedium::OnScanModeChanged(
|
||||
BluetoothAdapter::ScanMode scanMode) {
|
||||
scan_mode_ = scanMode;
|
||||
bool radioDiscoverable = bluetooth_adapter_.GetScanMode() ==
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable;
|
||||
|
||||
if (bluetooth_server_socket_ != nullptr) {
|
||||
bluetooth_server_socket_->SetScanMode(radioDiscoverable);
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartDiscovery(
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
discovery_callback_ = discovery_callback;
|
||||
|
||||
if (!IsWatcherStarted()) {
|
||||
result = StartScanning();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopDiscovery() {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (IsWatcherStarted()) {
|
||||
result = StopScanning();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void BluetoothClassicMedium::InitializeDeviceWatcher() {
|
||||
// create watcher
|
||||
device_watcher_ = DeviceInformation::CreateWatcher(
|
||||
BLUETOOTH_SELECTOR, // aqsFilter
|
||||
nullptr, // additionalProperties
|
||||
DeviceInformationKind::AssociationEndpoint); // kind
|
||||
|
||||
// An app must subscribe to all of the added, removed, and updated events to
|
||||
// be notified when there are device additions, removals or updates. If an
|
||||
// app handles only the added event, it will not receive an update if a
|
||||
// device is added to the system after the initial device enumeration
|
||||
// completes. register event handlers before starting the watcher
|
||||
|
||||
// Event that is raised when a device is added to the collection enumerated
|
||||
// by the DeviceWatcher.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348
|
||||
device_watcher_.Added({this, &BluetoothClassicMedium::DeviceWatcher_Added});
|
||||
|
||||
// Event that is raised when a device is updated in the collection of
|
||||
// enumerated devices.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.updated?view=winrt-20348
|
||||
device_watcher_.Updated(
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Updated});
|
||||
|
||||
// Event that is raised when a device is removed from the collection of
|
||||
// enumerated devices.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.removed?view=winrt-20348
|
||||
device_watcher_.Removed(
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Removed});
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid not specified.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::regex pattern(
|
||||
"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]"
|
||||
"{12}$");
|
||||
|
||||
// Must check for valid pattern as the guid constructor will throw on an
|
||||
// invalid format
|
||||
if (!regex_match(service_uuid, pattern)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": invalid service_uuid: " << service_uuid;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::guid service(service_uuid);
|
||||
|
||||
if (cancellation_flag == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": cancellation_flag not specified.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BluetoothDevice* currentDevice =
|
||||
dynamic_cast<BluetoothDevice*>(&remote_device);
|
||||
|
||||
if (currentDevice == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get current device.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::hstring deviceId = winrt::to_hstring(currentDevice->GetId());
|
||||
|
||||
if (!HaveAccess(deviceId)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to gain access to device: "
|
||||
<< winrt::to_string(deviceId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RfcommDeviceService requestedService(
|
||||
GetRequestedService(currentDevice, service));
|
||||
|
||||
if (!CheckSdp(requestedService)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Invalid SDP.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
device_watcher_.Stop();
|
||||
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
std::unique_ptr<BluetoothSocket> rfcommSocket =
|
||||
std::make_unique<BluetoothSocket>();
|
||||
|
||||
location::nearby::CancellationFlagListener cancellationFlagListener(
|
||||
cancellation_flag,
|
||||
[&rfcommSocket]() { rfcommSocket.get()->CancelIOAsync().get(); });
|
||||
|
||||
try {
|
||||
rfcommSocket->Connect(requestedService.ConnectionHostName(),
|
||||
requestedService.ConnectionServiceName());
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception connecting bluetooth async: "
|
||||
<< exception.what();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return rfcommSocket;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::HaveAccess(winrt::hstring deviceId) {
|
||||
DeviceAccessStatus accessStatus =
|
||||
DeviceAccessInformation::CreateFromId(deviceId).CurrentStatus();
|
||||
|
||||
if (accessStatus == DeviceAccessStatus::DeniedByUser ||
|
||||
// This status is most likely caused by app permissions (did not declare
|
||||
// the device in the app's package.appxmanifest)
|
||||
// This status does not cover the case where the device is already opened
|
||||
// by another app.
|
||||
accessStatus == DeviceAccessStatus::DeniedBySystem ||
|
||||
// Most likely the device is opened by another app, but cannot be sure
|
||||
accessStatus == DeviceAccessStatus::Unspecified) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RfcommDeviceService BluetoothClassicMedium::GetRequestedService(
|
||||
BluetoothDevice* device, winrt::guid service) {
|
||||
RfcommServiceId rfcommServiceId = RfcommServiceId::FromUuid(service);
|
||||
|
||||
// Retrieves all Rfcomm Services on the Remote Bluetooth Device matching the
|
||||
// specified RfcommServiceId.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice.getrfcommservicesforidasync?view=winrt-20348
|
||||
IAsyncOperation<RfcommDeviceServicesResult> rfcommServices =
|
||||
device->GetRfcommServicesForIdAsync(rfcommServiceId);
|
||||
|
||||
RfcommDeviceService requestedService(nullptr);
|
||||
|
||||
if (rfcommServices.get().Services().Size() > 0) {
|
||||
requestedService = rfcommServices.get().Services().GetAt(0);
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No services found.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return requestedService;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) {
|
||||
// Do various checks of the SDP record to make sure you are talking to a
|
||||
// device that actually supports the Bluetooth Rfcomm Service
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.getsdprawattributesasync?view=winrt-20348
|
||||
auto attributes = requestedService.GetSdpRawAttributesAsync().get();
|
||||
if (!attributes.HasKey(Constants::SdpServiceNameAttributeId)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Missing SdpServiceNameAttributeId.";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto attributeReader = DataReader::FromBuffer(
|
||||
attributes.Lookup(Constants::SdpServiceNameAttributeId));
|
||||
|
||||
auto attributeType = attributeReader.ReadByte();
|
||||
|
||||
if (attributeType != Constants::SdpServiceNameAttributeType) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Missing SdpServiceNameAttributeType.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
|
||||
//
|
||||
// service_uuid is the canonical textual representation
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
|
||||
// type 3 name-based
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
|
||||
// UUID.
|
||||
//
|
||||
// Returns nullptr error.
|
||||
std::unique_ptr<api::BluetoothServerSocket>
|
||||
BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
const std::string& service_uuid) {
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid was empty.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (service_name.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_name was empty.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto bluetooth_server_socket =
|
||||
std::make_unique<location::nearby::windows::BluetoothServerSocket>(
|
||||
service_name, service_uuid);
|
||||
|
||||
if (bluetooth_server_socket == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to create the server socket.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool radioDiscoverable = bluetooth_adapter_.GetScanMode() ==
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable;
|
||||
|
||||
Exception result = bluetooth_server_socket->StartListening(radioDiscoverable);
|
||||
|
||||
if (result.value != Exception::kSuccess) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to start listening.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::move(bluetooth_server_socket);
|
||||
}
|
||||
|
||||
api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
|
||||
const std::string& mac_address) {
|
||||
return new BluetoothDevice(mac_address);
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartScanning() {
|
||||
if (!IsWatcherStarted()) {
|
||||
// The Start method can only be called when the DeviceWatcher is in the
|
||||
// Created, Stopped or Aborted state.
|
||||
auto status = device_watcher_.Status();
|
||||
|
||||
if (status == DeviceWatcherStatus::Created ||
|
||||
status == DeviceWatcherStatus::Stopped ||
|
||||
status == DeviceWatcherStatus::Aborted) {
|
||||
device_watcher_.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Attempted to start scanning when watcher already started.";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopScanning() {
|
||||
if (IsWatcherRunning()) {
|
||||
device_watcher_.Stop();
|
||||
return true;
|
||||
}
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Attempted to stop scanning when watcher already stopped.";
|
||||
return false;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
DeviceWatcher sender, DeviceInformation deviceInfo) {
|
||||
if (IsWatcherStarted()) {
|
||||
// Represents a Bluetooth device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice?view=winrt-20348
|
||||
std::unique_ptr<winrt::Windows::Devices::Bluetooth::BluetoothDevice>
|
||||
windowsBluetoothDevice;
|
||||
|
||||
// Create an iterator for the internal list
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator
|
||||
it = devices_by_id_.find(deviceInfo.Id());
|
||||
|
||||
// Add to our internal list if necessary
|
||||
if (it == devices_by_id_.end()) {
|
||||
// Create a bluetooth device out of this id
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
|
||||
deviceInfo.Id())
|
||||
.Completed(
|
||||
[this, deviceInfo, wbd = std::move(windowsBluetoothDevice)](
|
||||
auto&& async,
|
||||
winrt::Windows::Foundation::AsyncStatus status) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
std::unique_ptr<BluetoothDevice> bluetoothDevice =
|
||||
std::make_unique<BluetoothDevice>(async.get());
|
||||
|
||||
devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDevice);
|
||||
|
||||
if (discovery_callback_.device_discovered_cb != nullptr) {
|
||||
discovery_callback_.device_discovered_cb(
|
||||
*devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
|
||||
if (IsWatcherStarted()) {
|
||||
// TODO(jfcarroll): Check for device name change
|
||||
}
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
if (IsWatcherStarted()) {
|
||||
if (discovery_callback_.device_lost_cb != nullptr) {
|
||||
discovery_callback_.device_lost_cb(*devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
|
||||
devices_by_id_.erase(deviceInfo.Id());
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::IsWatcherStarted() {
|
||||
if (device_watcher_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceWatcherStatus status = device_watcher_.Status();
|
||||
return (status == DeviceWatcherStatus::Started) ||
|
||||
(status == DeviceWatcherStatus::EnumerationCompleted);
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::IsWatcherRunning() {
|
||||
if (device_watcher_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceWatcherStatus status = device_watcher_.Status();
|
||||
return (status == DeviceWatcherStatus::Started) ||
|
||||
(status == DeviceWatcherStatus::EnumerationCompleted) ||
|
||||
(status == DeviceWatcherStatus::Stopping);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_medium.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <regex> // NOLINT
|
||||
#include <string>
|
||||
|
||||
#include "platform/base/cancellation_flag.h"
|
||||
#include "platform/base/cancellation_flag_listener.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_server_socket.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.Collections.h"
|
||||
#include "platform/impl/windows/generated/winrt/base.h"
|
||||
#include "platform/impl/windows/utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothClassicMedium::BluetoothClassicMedium(
|
||||
api::BluetoothAdapter& bluetoothAdapter)
|
||||
: bluetooth_adapter_(dynamic_cast<BluetoothAdapter&>(bluetoothAdapter)) {
|
||||
InitializeCriticalSection(&critical_section_);
|
||||
|
||||
InitializeDeviceWatcher();
|
||||
|
||||
bluetooth_adapter_.SetOnScanModeChanged(std::bind(
|
||||
&BluetoothClassicMedium::OnScanModeChanged, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
BluetoothClassicMedium::~BluetoothClassicMedium() {}
|
||||
|
||||
void BluetoothClassicMedium::OnScanModeChanged(
|
||||
BluetoothAdapter::ScanMode scanMode) {
|
||||
scan_mode_ = scanMode;
|
||||
bool radioDiscoverable = bluetooth_adapter_.GetScanMode() ==
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable;
|
||||
|
||||
if (bluetooth_server_socket_ != nullptr) {
|
||||
bluetooth_server_socket_->SetScanMode(radioDiscoverable);
|
||||
}
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartDiscovery(
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
discovery_callback_ = discovery_callback;
|
||||
|
||||
if (!IsWatcherStarted()) {
|
||||
result = StartScanning();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopDiscovery() {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (IsWatcherStarted()) {
|
||||
result = StopScanning();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void BluetoothClassicMedium::InitializeDeviceWatcher() {
|
||||
// create watcher
|
||||
device_watcher_ = DeviceInformation::CreateWatcher(
|
||||
BLUETOOTH_SELECTOR, // aqsFilter
|
||||
nullptr, // additionalProperties
|
||||
DeviceInformationKind::AssociationEndpoint); // kind
|
||||
|
||||
// An app must subscribe to all of the added, removed, and updated events to
|
||||
// be notified when there are device additions, removals or updates. If an
|
||||
// app handles only the added event, it will not receive an update if a
|
||||
// device is added to the system after the initial device enumeration
|
||||
// completes. register event handlers before starting the watcher
|
||||
|
||||
// Event that is raised when a device is added to the collection enumerated
|
||||
// by the DeviceWatcher.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.added?view=winrt-20348
|
||||
device_watcher_.Added({this, &BluetoothClassicMedium::DeviceWatcher_Added});
|
||||
|
||||
// Event that is raised when a device is updated in the collection of
|
||||
// enumerated devices.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.updated?view=winrt-20348
|
||||
device_watcher_.Updated(
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Updated});
|
||||
|
||||
// Event that is raised when a device is removed from the collection of
|
||||
// enumerated devices.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher.removed?view=winrt-20348
|
||||
device_watcher_.Removed(
|
||||
{this, &BluetoothClassicMedium::DeviceWatcher_Removed});
|
||||
}
|
||||
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) {
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid not specified.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::regex pattern(
|
||||
"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]"
|
||||
"{12}$");
|
||||
|
||||
// Must check for valid pattern as the guid constructor will throw on an
|
||||
// invalid format
|
||||
if (!regex_match(service_uuid, pattern)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": invalid service_uuid: " << service_uuid;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::guid service(service_uuid);
|
||||
|
||||
if (cancellation_flag == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": cancellation_flag not specified.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BluetoothDevice* currentDevice =
|
||||
dynamic_cast<BluetoothDevice*>(&remote_device);
|
||||
|
||||
if (currentDevice == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to get current device.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::hstring deviceId = winrt::to_hstring(currentDevice->GetId());
|
||||
|
||||
if (!HaveAccess(deviceId)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to gain access to device: "
|
||||
<< winrt::to_string(deviceId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RfcommDeviceService requestedService(
|
||||
GetRequestedService(currentDevice, service));
|
||||
|
||||
if (!CheckSdp(requestedService)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Invalid SDP.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
device_watcher_.Stop();
|
||||
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
std::unique_ptr<BluetoothSocket> rfcommSocket =
|
||||
std::make_unique<BluetoothSocket>();
|
||||
|
||||
location::nearby::CancellationFlagListener cancellationFlagListener(
|
||||
cancellation_flag,
|
||||
[&rfcommSocket]() { rfcommSocket.get()->CancelIOAsync().get(); });
|
||||
|
||||
try {
|
||||
rfcommSocket->Connect(requestedService.ConnectionHostName(),
|
||||
requestedService.ConnectionServiceName());
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception connecting bluetooth async: "
|
||||
<< exception.what();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return rfcommSocket;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::HaveAccess(winrt::hstring deviceId) {
|
||||
DeviceAccessStatus accessStatus =
|
||||
DeviceAccessInformation::CreateFromId(deviceId).CurrentStatus();
|
||||
|
||||
if (accessStatus == DeviceAccessStatus::DeniedByUser ||
|
||||
// This status is most likely caused by app permissions (did not declare
|
||||
// the device in the app's package.appxmanifest)
|
||||
// This status does not cover the case where the device is already opened
|
||||
// by another app.
|
||||
accessStatus == DeviceAccessStatus::DeniedBySystem ||
|
||||
// Most likely the device is opened by another app, but cannot be sure
|
||||
accessStatus == DeviceAccessStatus::Unspecified) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RfcommDeviceService BluetoothClassicMedium::GetRequestedService(
|
||||
BluetoothDevice* device, winrt::guid service) {
|
||||
RfcommServiceId rfcommServiceId = RfcommServiceId::FromUuid(service);
|
||||
|
||||
// Retrieves all Rfcomm Services on the Remote Bluetooth Device matching the
|
||||
// specified RfcommServiceId.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice.getrfcommservicesforidasync?view=winrt-20348
|
||||
IAsyncOperation<RfcommDeviceServicesResult> rfcommServices =
|
||||
device->GetRfcommServicesForIdAsync(rfcommServiceId);
|
||||
|
||||
RfcommDeviceService requestedService(nullptr);
|
||||
|
||||
if (rfcommServices.get().Services().Size() > 0) {
|
||||
requestedService = rfcommServices.get().Services().GetAt(0);
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No services found.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return requestedService;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::CheckSdp(RfcommDeviceService requestedService) {
|
||||
// Do various checks of the SDP record to make sure you are talking to a
|
||||
// device that actually supports the Bluetooth Rfcomm Service
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice.getsdprawattributesasync?view=winrt-20348
|
||||
auto attributes = requestedService.GetSdpRawAttributesAsync().get();
|
||||
if (!attributes.HasKey(Constants::SdpServiceNameAttributeId)) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Missing SdpServiceNameAttributeId.";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto attributeReader = DataReader::FromBuffer(
|
||||
attributes.Lookup(Constants::SdpServiceNameAttributeId));
|
||||
|
||||
auto attributeType = attributeReader.ReadByte();
|
||||
|
||||
if (attributeType != Constants::SdpServiceNameAttributeType) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Missing SdpServiceNameAttributeType.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
|
||||
//
|
||||
// service_uuid is the canonical textual representation
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
|
||||
// type 3 name-based
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
|
||||
// UUID.
|
||||
//
|
||||
// Returns nullptr error.
|
||||
std::unique_ptr<api::BluetoothServerSocket>
|
||||
BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
const std::string& service_uuid) {
|
||||
if (service_uuid.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_uuid was empty.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (service_name.empty()) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": service_name was empty.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto bluetooth_server_socket =
|
||||
std::make_unique<location::nearby::windows::BluetoothServerSocket>(
|
||||
service_name, service_uuid);
|
||||
|
||||
if (bluetooth_server_socket == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to create the server socket.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool radioDiscoverable = bluetooth_adapter_.GetScanMode() ==
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable;
|
||||
|
||||
Exception result = bluetooth_server_socket->StartListening(radioDiscoverable);
|
||||
|
||||
if (result.value != Exception::kSuccess) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to start listening.";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::move(bluetooth_server_socket);
|
||||
}
|
||||
|
||||
api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
|
||||
const std::string& mac_address) {
|
||||
return new BluetoothDevice(mac_address);
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StartScanning() {
|
||||
if (!IsWatcherStarted()) {
|
||||
// The Start method can only be called when the DeviceWatcher is in the
|
||||
// Created, Stopped or Aborted state.
|
||||
auto status = device_watcher_.Status();
|
||||
|
||||
if (status == DeviceWatcherStatus::Created ||
|
||||
status == DeviceWatcherStatus::Stopped ||
|
||||
status == DeviceWatcherStatus::Aborted) {
|
||||
device_watcher_.Start();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Attempted to start scanning when watcher already started.";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::StopScanning() {
|
||||
if (IsWatcherRunning()) {
|
||||
device_watcher_.Stop();
|
||||
return true;
|
||||
}
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Attempted to stop scanning when watcher already stopped.";
|
||||
return false;
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
DeviceWatcher sender, DeviceInformation deviceInfo) {
|
||||
if (IsWatcherStarted()) {
|
||||
// Represents a Bluetooth device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice?view=winrt-20348
|
||||
std::unique_ptr<winrt::Windows::Devices::Bluetooth::BluetoothDevice>
|
||||
windowsBluetoothDevice;
|
||||
|
||||
// Create an iterator for the internal list
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator
|
||||
it = devices_by_id_.find(deviceInfo.Id());
|
||||
|
||||
// Add to our internal list if necessary
|
||||
if (it == devices_by_id_.end()) {
|
||||
// Create a bluetooth device out of this id
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromIdAsync(
|
||||
deviceInfo.Id())
|
||||
.Completed(
|
||||
[this, deviceInfo, wbd = std::move(windowsBluetoothDevice)](
|
||||
auto&& async,
|
||||
winrt::Windows::Foundation::AsyncStatus status) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
std::unique_ptr<BluetoothDevice> bluetoothDevice =
|
||||
std::make_unique<BluetoothDevice>(async.get());
|
||||
|
||||
devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDevice);
|
||||
|
||||
if (discovery_callback_.device_discovered_cb != nullptr) {
|
||||
discovery_callback_.device_discovered_cb(
|
||||
*devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfoUpdate) {
|
||||
if (IsWatcherStarted()) {
|
||||
// TODO(jfcarroll): Check for device name change
|
||||
}
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
if (IsWatcherStarted()) {
|
||||
if (discovery_callback_.device_lost_cb != nullptr) {
|
||||
discovery_callback_.device_lost_cb(*devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
|
||||
devices_by_id_.erase(deviceInfo.Id());
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::IsWatcherStarted() {
|
||||
if (device_watcher_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceWatcherStatus status = device_watcher_.Status();
|
||||
return (status == DeviceWatcherStatus::Started) ||
|
||||
(status == DeviceWatcherStatus::EnumerationCompleted);
|
||||
}
|
||||
|
||||
bool BluetoothClassicMedium::IsWatcherRunning() {
|
||||
if (device_watcher_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceWatcherStatus status = device_watcher_.Status();
|
||||
return (status == DeviceWatcherStatus::Started) ||
|
||||
(status == DeviceWatcherStatus::EnumerationCompleted) ||
|
||||
(status == DeviceWatcherStatus::Stopping);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -1,191 +1,191 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
|
||||
#include "platform/api/bluetooth_classic.h"
|
||||
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_server_socket.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "platform/impl/windows/generated/winrt/base.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Represents a device. This class allows access to well-known device properties
|
||||
// as well as additional properties specified during device enumeration.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformation;
|
||||
|
||||
// Represents the kind of DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationkind?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationKind;
|
||||
|
||||
// Contains updated properties for a DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationupdate?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationUpdate;
|
||||
|
||||
// Enumerates devices dynamically, so that the app receives notifications if
|
||||
// devices are added, removed, or changed after the initial enumeration is
|
||||
// complete.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcher;
|
||||
|
||||
// Describes the state of a DeviceWatcher object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcherstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcherStatus;
|
||||
|
||||
// Represents an instance of a service on a Bluetooth basic rate device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService;
|
||||
|
||||
// Indicates the status of the access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessStatus;
|
||||
|
||||
// Contains the information about access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessInformation;
|
||||
|
||||
// Represents an RFCOMM service ID.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
|
||||
// Reads data from an input stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataReader;
|
||||
|
||||
// Writes data to an output stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
// Bluetooth protocol ID = \"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\"
|
||||
// https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/aep-service-class-ids
|
||||
#define BLUETOOTH_SELECTOR \
|
||||
L"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\""
|
||||
|
||||
// Container of operations that can be performed over the Bluetooth Classic
|
||||
// medium.
|
||||
class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
public:
|
||||
BluetoothClassicMedium(api::BluetoothAdapter& bluetoothAdapter);
|
||||
|
||||
~BluetoothClassicMedium() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
|
||||
bool StartDiscovery(DiscoveryCallback discovery_callback) override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#cancelDiscovery()
|
||||
//
|
||||
// Returns true once discovery is well and truly stopped; after this returns,
|
||||
// there must be no more invocations of the DiscoveryCallback passed in to
|
||||
// StartDiscovery().
|
||||
bool StopDiscovery() override;
|
||||
|
||||
// A combination of
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createInsecureRfcommSocketToServiceRecord
|
||||
// followed by
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#connect().
|
||||
//
|
||||
// service_uuid is the canonical textual representation
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
|
||||
// type 3 name-based
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
|
||||
// UUID.
|
||||
//
|
||||
// On success, returns a new BluetoothSocket.
|
||||
// On error, throw's an exception
|
||||
std::unique_ptr<api::BluetoothSocket> ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
|
||||
//
|
||||
// service_uuid is the canonical textual representation
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
|
||||
// type 3 name-based
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
|
||||
// UUID.
|
||||
//
|
||||
// Returns nullptr error.
|
||||
std::unique_ptr<api::BluetoothServerSocket> ListenForService(
|
||||
const std::string& service_name,
|
||||
const std::string& service_uuid) override;
|
||||
|
||||
api::BluetoothDevice* GetRemoteDevice(
|
||||
const std::string& mac_address) override;
|
||||
|
||||
private:
|
||||
bool StartScanning();
|
||||
bool StopScanning();
|
||||
bool IsWatcherStarted();
|
||||
bool IsWatcherRunning();
|
||||
void InitializeDeviceWatcher();
|
||||
void OnScanModeChanged(BluetoothAdapter::ScanMode scanMode);
|
||||
|
||||
// This is for a coroutine whose return type is winrt::fire_and_forget, which
|
||||
// handles async operations which don't have any dependencies.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/fire-and-forget
|
||||
winrt::fire_and_forget DeviceWatcher_Added(DeviceWatcher sender,
|
||||
DeviceInformation deviceInfo);
|
||||
|
||||
winrt::fire_and_forget DeviceWatcher_Updated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo);
|
||||
|
||||
winrt::fire_and_forget DeviceWatcher_Removed(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo);
|
||||
|
||||
// Check to make sure we can connect if we try
|
||||
bool HaveAccess(winrt::hstring deviceId);
|
||||
|
||||
// Get the service requested
|
||||
RfcommDeviceService GetRequestedService(BluetoothDevice* device,
|
||||
winrt::guid service);
|
||||
|
||||
// Check to see that the device actually handles the requested service
|
||||
bool CheckSdp(RfcommDeviceService requestedService);
|
||||
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback_;
|
||||
|
||||
DeviceWatcher device_watcher_ = nullptr;
|
||||
|
||||
std::unique_ptr<BluetoothSocket> bluetooth_socket_;
|
||||
std::unique_ptr<BluetoothServerSocket> bluetooth_server_socket_;
|
||||
|
||||
std::string service_name_;
|
||||
std::string service_uuid_;
|
||||
|
||||
// hstring is the only type of string winrt understands.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>> devices_by_id_;
|
||||
|
||||
// CRITICAL_SECTION is a lightweight synchronization mechanism
|
||||
// https://docs.microsoft.com/en-us/windows/win32/sync/critical-section-objects
|
||||
CRITICAL_SECTION critical_section_;
|
||||
|
||||
BluetoothAdapter& bluetooth_adapter_;
|
||||
|
||||
BluetoothAdapter::ScanMode scan_mode_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
|
||||
#include "platform/api/bluetooth_classic.h"
|
||||
#include "platform/impl/windows/bluetooth_adapter.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_server_socket.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Enumeration.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "platform/impl/windows/generated/winrt/base.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Represents a device. This class allows access to well-known device properties
|
||||
// as well as additional properties specified during device enumeration.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformation;
|
||||
|
||||
// Represents the kind of DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationkind?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationKind;
|
||||
|
||||
// Contains updated properties for a DeviceInformation object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceinformationupdate?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceInformationUpdate;
|
||||
|
||||
// Enumerates devices dynamically, so that the app receives notifications if
|
||||
// devices are added, removed, or changed after the initial enumeration is
|
||||
// complete.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcher?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcher;
|
||||
|
||||
// Describes the state of a DeviceWatcher object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicewatcherstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceWatcherStatus;
|
||||
|
||||
// Represents an instance of a service on a Bluetooth basic rate device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService;
|
||||
|
||||
// Indicates the status of the access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessstatus?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessStatus;
|
||||
|
||||
// Contains the information about access to a device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.deviceaccessinformation?view=winrt-20348
|
||||
using winrt::Windows::Devices::Enumeration::DeviceAccessInformation;
|
||||
|
||||
// Represents an RFCOMM service ID.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
|
||||
// Reads data from an input stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataReader;
|
||||
|
||||
// Writes data to an output stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
// Bluetooth protocol ID = \"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\"
|
||||
// https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/aep-service-class-ids
|
||||
#define BLUETOOTH_SELECTOR \
|
||||
L"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\""
|
||||
|
||||
// Container of operations that can be performed over the Bluetooth Classic
|
||||
// medium.
|
||||
class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
public:
|
||||
BluetoothClassicMedium(api::BluetoothAdapter& bluetoothAdapter);
|
||||
|
||||
~BluetoothClassicMedium() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
|
||||
bool StartDiscovery(DiscoveryCallback discovery_callback) override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#cancelDiscovery()
|
||||
//
|
||||
// Returns true once discovery is well and truly stopped; after this returns,
|
||||
// there must be no more invocations of the DiscoveryCallback passed in to
|
||||
// StartDiscovery().
|
||||
bool StopDiscovery() override;
|
||||
|
||||
// A combination of
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#createInsecureRfcommSocketToServiceRecord
|
||||
// followed by
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#connect().
|
||||
//
|
||||
// service_uuid is the canonical textual representation
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
|
||||
// type 3 name-based
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
|
||||
// UUID.
|
||||
//
|
||||
// On success, returns a new BluetoothSocket.
|
||||
// On error, throw's an exception
|
||||
std::unique_ptr<api::BluetoothSocket> ConnectToService(
|
||||
api::BluetoothDevice& remote_device, const std::string& service_uuid,
|
||||
CancellationFlag* cancellation_flag) override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#listenUsingInsecureRfcommWithServiceRecord
|
||||
//
|
||||
// service_uuid is the canonical textual representation
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Format) of a
|
||||
// type 3 name-based
|
||||
// (https://en.wikipedia.org/wiki/Universally_unique_identifier#Versions_3_and_5_(namespace_name-based))
|
||||
// UUID.
|
||||
//
|
||||
// Returns nullptr error.
|
||||
std::unique_ptr<api::BluetoothServerSocket> ListenForService(
|
||||
const std::string& service_name,
|
||||
const std::string& service_uuid) override;
|
||||
|
||||
api::BluetoothDevice* GetRemoteDevice(
|
||||
const std::string& mac_address) override;
|
||||
|
||||
private:
|
||||
bool StartScanning();
|
||||
bool StopScanning();
|
||||
bool IsWatcherStarted();
|
||||
bool IsWatcherRunning();
|
||||
void InitializeDeviceWatcher();
|
||||
void OnScanModeChanged(BluetoothAdapter::ScanMode scanMode);
|
||||
|
||||
// This is for a coroutine whose return type is winrt::fire_and_forget, which
|
||||
// handles async operations which don't have any dependencies.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/fire-and-forget
|
||||
winrt::fire_and_forget DeviceWatcher_Added(DeviceWatcher sender,
|
||||
DeviceInformation deviceInfo);
|
||||
|
||||
winrt::fire_and_forget DeviceWatcher_Updated(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo);
|
||||
|
||||
winrt::fire_and_forget DeviceWatcher_Removed(
|
||||
DeviceWatcher sender, DeviceInformationUpdate deviceInfo);
|
||||
|
||||
// Check to make sure we can connect if we try
|
||||
bool HaveAccess(winrt::hstring deviceId);
|
||||
|
||||
// Get the service requested
|
||||
RfcommDeviceService GetRequestedService(BluetoothDevice* device,
|
||||
winrt::guid service);
|
||||
|
||||
// Check to see that the device actually handles the requested service
|
||||
bool CheckSdp(RfcommDeviceService requestedService);
|
||||
|
||||
BluetoothClassicMedium::DiscoveryCallback discovery_callback_;
|
||||
|
||||
DeviceWatcher device_watcher_ = nullptr;
|
||||
|
||||
std::unique_ptr<BluetoothSocket> bluetooth_socket_;
|
||||
std::unique_ptr<BluetoothServerSocket> bluetooth_server_socket_;
|
||||
|
||||
std::string service_name_;
|
||||
std::string service_uuid_;
|
||||
|
||||
// hstring is the only type of string winrt understands.
|
||||
// https://docs.microsoft.com/en-us/uwp/cpp-ref-for-winrt/hstring
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>> devices_by_id_;
|
||||
|
||||
// CRITICAL_SECTION is a lightweight synchronization mechanism
|
||||
// https://docs.microsoft.com/en-us/windows/win32/sync/critical-section-objects
|
||||
CRITICAL_SECTION critical_section_;
|
||||
|
||||
BluetoothAdapter& bluetooth_adapter_;
|
||||
|
||||
BluetoothAdapter::ScanMode scan_mode_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_MEDIUM_H_
|
||||
|
||||
@@ -1,196 +1,196 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_server_socket.h"
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.Collections.h"
|
||||
#include "platform/impl/windows/utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothServerSocket::BluetoothServerSocket(const std::string service_name,
|
||||
const std::string service_uuid)
|
||||
: radio_discoverable_(false),
|
||||
service_name_(service_name),
|
||||
service_uuid_(service_uuid),
|
||||
rfcomm_provider_(nullptr) {
|
||||
InitializeCriticalSection(&critical_section_);
|
||||
}
|
||||
|
||||
BluetoothServerSocket::~BluetoothServerSocket() {}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept()
|
||||
//
|
||||
// Blocks until either:
|
||||
// - at least one incoming connection request is available, or
|
||||
// - ServerSocket is closed.
|
||||
// On success, returns connected socket, ready to exchange data.
|
||||
// Returns nullptr on error.
|
||||
// Once error is reported, it is permanent, and ServerSocket has to be closed.
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() {
|
||||
while (bluetooth_sockets_.empty() && !closed_) {
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&critical_section_);
|
||||
if (!closed_) {
|
||||
std::unique_ptr<BluetoothSocket> bluetoothSocket =
|
||||
std::move(bluetooth_sockets_.front());
|
||||
bluetooth_sockets_.pop();
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return std::move(bluetoothSocket);
|
||||
} else {
|
||||
bluetooth_sockets_ = {};
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Exception BluetoothServerSocket::StartListening(bool radioDiscoverable) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
radio_discoverable_ = radioDiscoverable;
|
||||
|
||||
// Create the StreamSocketListener
|
||||
stream_socket_listener_ = StreamSocketListener();
|
||||
|
||||
// Configure control property
|
||||
stream_socket_listener_.Control().QualityOfService(
|
||||
SocketQualityOfService::LowLatency);
|
||||
|
||||
stream_socket_listener_.Control().KeepAlive(true);
|
||||
|
||||
// Note From the perspective of a StreamSocket, a Parallel Patterns Library
|
||||
// (PPL) completion handler is done executing (and the socket is eligible for
|
||||
// disposal) before the continuation body runs. So, to keep your socket from
|
||||
// being disposed if you want to use it inside a continuation, you'll need to
|
||||
// use one of the techniques described in References to StreamSockets in C++
|
||||
// PPL continuations.
|
||||
// Assign ConnectionReceived event to event handler on the server socket
|
||||
stream_socket_listener_.ConnectionReceived(
|
||||
[this](StreamSocketListener streamSocketListener,
|
||||
StreamSocketListenerConnectionReceivedEventArgs args) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
if (!closed_) {
|
||||
this->bluetooth_sockets_.push(
|
||||
std::make_unique<BluetoothSocket>(args.Socket()));
|
||||
}
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
});
|
||||
|
||||
try {
|
||||
auto rfcommProviderRef =
|
||||
RfcommServiceProvider::CreateAsync(
|
||||
RfcommServiceId::FromUuid(winrt::guid(service_uuid_)))
|
||||
.get();
|
||||
|
||||
rfcomm_provider_ = rfcommProviderRef;
|
||||
|
||||
stream_socket_listener_
|
||||
.BindServiceNameAsync(
|
||||
winrt::to_hstring(rfcomm_provider_.ServiceId().AsString()),
|
||||
SocketProtectionLevel::PlainSocket)
|
||||
.get();
|
||||
|
||||
// Set the SDP attributes and start Bluetooth advertising
|
||||
InitializeServiceSdpAttributes(rfcomm_provider_, service_name_);
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception setting up for listen: "
|
||||
<< exception.what();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
StartAdvertising();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BluetoothServerSocket::StartAdvertising() {
|
||||
try {
|
||||
rfcomm_provider_.StartAdvertising(stream_socket_listener_,
|
||||
radio_discoverable_);
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception calling StartAdvertising: "
|
||||
<< exception.what();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
void BluetoothServerSocket::StopAdvertising() {
|
||||
rfcomm_provider_.StopAdvertising();
|
||||
}
|
||||
|
||||
void BluetoothServerSocket::InitializeServiceSdpAttributes(
|
||||
RfcommServiceProvider rfcommProvider, std::string service_name) {
|
||||
auto sdpWriter = DataWriter();
|
||||
|
||||
// Write the Service Name Attribute.
|
||||
sdpWriter.WriteByte(Constants::SdpServiceNameAttributeType);
|
||||
|
||||
// The length of the UTF-8 encoded Service Name SDP Attribute.
|
||||
sdpWriter.WriteByte(service_name.size());
|
||||
|
||||
// The UTF-8 encoded Service Name value.
|
||||
sdpWriter.UnicodeEncoding(UnicodeEncoding::Utf8);
|
||||
sdpWriter.WriteString(winrt::to_hstring(service_name));
|
||||
|
||||
// Set the SDP Attribute on the RFCOMM Service Provider.
|
||||
rfcommProvider.SdpRawAttributes().Insert(Constants::SdpServiceNameAttributeId,
|
||||
sdpWriter.DetachBuffer());
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close()
|
||||
//
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception BluetoothServerSocket::Close() {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
if (closed_) {
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
rfcomm_provider_.StopAdvertising();
|
||||
closed_ = true;
|
||||
bluetooth_sockets_ = {};
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_server_socket.h"
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
#include <string>
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.Collections.h"
|
||||
#include "platform/impl/windows/utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothServerSocket::BluetoothServerSocket(const std::string service_name,
|
||||
const std::string service_uuid)
|
||||
: radio_discoverable_(false),
|
||||
service_name_(service_name),
|
||||
service_uuid_(service_uuid),
|
||||
rfcomm_provider_(nullptr) {
|
||||
InitializeCriticalSection(&critical_section_);
|
||||
}
|
||||
|
||||
BluetoothServerSocket::~BluetoothServerSocket() {}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept()
|
||||
//
|
||||
// Blocks until either:
|
||||
// - at least one incoming connection request is available, or
|
||||
// - ServerSocket is closed.
|
||||
// On success, returns connected socket, ready to exchange data.
|
||||
// Returns nullptr on error.
|
||||
// Once error is reported, it is permanent, and ServerSocket has to be closed.
|
||||
std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() {
|
||||
while (bluetooth_sockets_.empty() && !closed_) {
|
||||
Sleep(1000);
|
||||
}
|
||||
|
||||
EnterCriticalSection(&critical_section_);
|
||||
if (!closed_) {
|
||||
std::unique_ptr<BluetoothSocket> bluetoothSocket =
|
||||
std::move(bluetooth_sockets_.front());
|
||||
bluetooth_sockets_.pop();
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return std::move(bluetoothSocket);
|
||||
} else {
|
||||
bluetooth_sockets_ = {};
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Exception BluetoothServerSocket::StartListening(bool radioDiscoverable) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
radio_discoverable_ = radioDiscoverable;
|
||||
|
||||
// Create the StreamSocketListener
|
||||
stream_socket_listener_ = StreamSocketListener();
|
||||
|
||||
// Configure control property
|
||||
stream_socket_listener_.Control().QualityOfService(
|
||||
SocketQualityOfService::LowLatency);
|
||||
|
||||
stream_socket_listener_.Control().KeepAlive(true);
|
||||
|
||||
// Note From the perspective of a StreamSocket, a Parallel Patterns Library
|
||||
// (PPL) completion handler is done executing (and the socket is eligible for
|
||||
// disposal) before the continuation body runs. So, to keep your socket from
|
||||
// being disposed if you want to use it inside a continuation, you'll need to
|
||||
// use one of the techniques described in References to StreamSockets in C++
|
||||
// PPL continuations.
|
||||
// Assign ConnectionReceived event to event handler on the server socket
|
||||
stream_socket_listener_.ConnectionReceived(
|
||||
[this](StreamSocketListener streamSocketListener,
|
||||
StreamSocketListenerConnectionReceivedEventArgs args) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
if (!closed_) {
|
||||
this->bluetooth_sockets_.push(
|
||||
std::make_unique<BluetoothSocket>(args.Socket()));
|
||||
}
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
});
|
||||
|
||||
try {
|
||||
auto rfcommProviderRef =
|
||||
RfcommServiceProvider::CreateAsync(
|
||||
RfcommServiceId::FromUuid(winrt::guid(service_uuid_)))
|
||||
.get();
|
||||
|
||||
rfcomm_provider_ = rfcommProviderRef;
|
||||
|
||||
stream_socket_listener_
|
||||
.BindServiceNameAsync(
|
||||
winrt::to_hstring(rfcomm_provider_.ServiceId().AsString()),
|
||||
SocketProtectionLevel::PlainSocket)
|
||||
.get();
|
||||
|
||||
// Set the SDP attributes and start Bluetooth advertising
|
||||
InitializeServiceSdpAttributes(rfcomm_provider_, service_name_);
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception setting up for listen: "
|
||||
<< exception.what();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
StartAdvertising();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BluetoothServerSocket::StartAdvertising() {
|
||||
try {
|
||||
rfcomm_provider_.StartAdvertising(stream_socket_listener_,
|
||||
radio_discoverable_);
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Exception calling StartAdvertising: "
|
||||
<< exception.what();
|
||||
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
void BluetoothServerSocket::StopAdvertising() {
|
||||
rfcomm_provider_.StopAdvertising();
|
||||
}
|
||||
|
||||
void BluetoothServerSocket::InitializeServiceSdpAttributes(
|
||||
RfcommServiceProvider rfcommProvider, std::string service_name) {
|
||||
auto sdpWriter = DataWriter();
|
||||
|
||||
// Write the Service Name Attribute.
|
||||
sdpWriter.WriteByte(Constants::SdpServiceNameAttributeType);
|
||||
|
||||
// The length of the UTF-8 encoded Service Name SDP Attribute.
|
||||
sdpWriter.WriteByte(service_name.size());
|
||||
|
||||
// The UTF-8 encoded Service Name value.
|
||||
sdpWriter.UnicodeEncoding(UnicodeEncoding::Utf8);
|
||||
sdpWriter.WriteString(winrt::to_hstring(service_name));
|
||||
|
||||
// Set the SDP Attribute on the RFCOMM Service Provider.
|
||||
rfcommProvider.SdpRawAttributes().Insert(Constants::SdpServiceNameAttributeId,
|
||||
sdpWriter.DetachBuffer());
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close()
|
||||
//
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception BluetoothServerSocket::Close() {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
if (closed_) {
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
rfcomm_provider_.StopAdvertising();
|
||||
closed_ = true;
|
||||
bluetooth_sockets_ = {};
|
||||
LeaveCriticalSection(&critical_section_);
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -1,129 +1,129 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "platform/api/bluetooth_classic.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "platform/impl/windows/generated/winrt/base.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Supports listening for an incoming network connection using Bluetooth RFCOMM.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistener?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::StreamSocketListener;
|
||||
|
||||
// Provides data for a ConnectionReceived event on a StreamSocketListener
|
||||
// object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistenerconnectionreceivedeventargs?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::
|
||||
StreamSocketListenerConnectionReceivedEventArgs;
|
||||
|
||||
// Represents an asynchronous action.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncaction?view=winrt-20348
|
||||
using winrt::Windows::Foundation::IAsyncAction;
|
||||
|
||||
// Specifies the quality of service for a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketqualityofservice?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::SocketQualityOfService;
|
||||
|
||||
// Represents an instance of a local RFCOMM service.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceprovider?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceProvider;
|
||||
|
||||
// Represents an RFCOMM service ID.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
|
||||
// Writes data to an output stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
// Specifies the type of character encoding for a stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.unicodeencoding?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::UnicodeEncoding;
|
||||
|
||||
// Specifies the level of encryption to use on a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketprotectionlevel?view=winrt-22000
|
||||
using winrt::Windows::Networking::Sockets::SocketProtectionLevel;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html.
|
||||
class BluetoothServerSocket : public api::BluetoothServerSocket {
|
||||
public:
|
||||
BluetoothServerSocket(const std::string service_name,
|
||||
const std::string service_uuid);
|
||||
|
||||
~BluetoothServerSocket() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept()
|
||||
//
|
||||
// Blocks until either:
|
||||
// - at least one incoming connection request is available, or
|
||||
// - ServerSocket is closed.
|
||||
// On success, returns connected socket, ready to exchange data.
|
||||
// Returns nullptr on error.
|
||||
// Once error is reported, it is permanent, and ServerSocket has to be closed.
|
||||
std::unique_ptr<api::BluetoothSocket> Accept() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close()
|
||||
//
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception Close() override;
|
||||
|
||||
Exception StartListening(bool radioDiscoverable);
|
||||
|
||||
void SetScanMode(bool radioDiscoverable) {
|
||||
StopAdvertising();
|
||||
radio_discoverable_ = radioDiscoverable;
|
||||
StartAdvertising();
|
||||
}
|
||||
|
||||
private:
|
||||
void InitializeServiceSdpAttributes(RfcommServiceProvider rfcommProvider,
|
||||
std::string service_name);
|
||||
|
||||
Exception StartAdvertising();
|
||||
void StopAdvertising();
|
||||
|
||||
// This is used to store sockets in case Accept hasn't been called. Once
|
||||
// Accept has been called the socket is popped from the queue and returned to
|
||||
// the caller
|
||||
std::queue<std::unique_ptr<BluetoothSocket>> bluetooth_sockets_;
|
||||
|
||||
StreamSocketListener stream_socket_listener_;
|
||||
winrt::event_token listener_token_;
|
||||
CRITICAL_SECTION critical_section_;
|
||||
bool closed_ = false;
|
||||
bool radio_discoverable_;
|
||||
|
||||
const std::string service_name_;
|
||||
const std::string service_uuid_;
|
||||
|
||||
RfcommServiceProvider rfcomm_provider_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include "platform/api/bluetooth_classic.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.Rfcomm.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "platform/impl/windows/generated/winrt/base.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Supports listening for an incoming network connection using Bluetooth RFCOMM.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistener?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::StreamSocketListener;
|
||||
|
||||
// Provides data for a ConnectionReceived event on a StreamSocketListener
|
||||
// object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocketlistenerconnectionreceivedeventargs?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::
|
||||
StreamSocketListenerConnectionReceivedEventArgs;
|
||||
|
||||
// Represents an asynchronous action.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncaction?view=winrt-20348
|
||||
using winrt::Windows::Foundation::IAsyncAction;
|
||||
|
||||
// Specifies the quality of service for a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketqualityofservice?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::SocketQualityOfService;
|
||||
|
||||
// Represents an instance of a local RFCOMM service.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceprovider?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceProvider;
|
||||
|
||||
// Represents an RFCOMM service ID.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommserviceid?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::Rfcomm::RfcommServiceId;
|
||||
|
||||
// Writes data to an output stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datawriter?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
// Specifies the type of character encoding for a stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.unicodeencoding?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::UnicodeEncoding;
|
||||
|
||||
// Specifies the level of encryption to use on a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketprotectionlevel?view=winrt-22000
|
||||
using winrt::Windows::Networking::Sockets::SocketProtectionLevel;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html.
|
||||
class BluetoothServerSocket : public api::BluetoothServerSocket {
|
||||
public:
|
||||
BluetoothServerSocket(const std::string service_name,
|
||||
const std::string service_uuid);
|
||||
|
||||
~BluetoothServerSocket() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#accept()
|
||||
//
|
||||
// Blocks until either:
|
||||
// - at least one incoming connection request is available, or
|
||||
// - ServerSocket is closed.
|
||||
// On success, returns connected socket, ready to exchange data.
|
||||
// Returns nullptr on error.
|
||||
// Once error is reported, it is permanent, and ServerSocket has to be closed.
|
||||
std::unique_ptr<api::BluetoothSocket> Accept() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothServerSocket.html#close()
|
||||
//
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception Close() override;
|
||||
|
||||
Exception StartListening(bool radioDiscoverable);
|
||||
|
||||
void SetScanMode(bool radioDiscoverable) {
|
||||
StopAdvertising();
|
||||
radio_discoverable_ = radioDiscoverable;
|
||||
StartAdvertising();
|
||||
}
|
||||
|
||||
private:
|
||||
void InitializeServiceSdpAttributes(RfcommServiceProvider rfcommProvider,
|
||||
std::string service_name);
|
||||
|
||||
Exception StartAdvertising();
|
||||
void StopAdvertising();
|
||||
|
||||
// This is used to store sockets in case Accept hasn't been called. Once
|
||||
// Accept has been called the socket is popped from the queue and returned to
|
||||
// the caller
|
||||
std::queue<std::unique_ptr<BluetoothSocket>> bluetooth_sockets_;
|
||||
|
||||
StreamSocketListener stream_socket_listener_;
|
||||
winrt::event_token listener_token_;
|
||||
CRITICAL_SECTION critical_section_;
|
||||
bool closed_ = false;
|
||||
bool radio_discoverable_;
|
||||
|
||||
const std::string service_name_;
|
||||
const std::string service_uuid_;
|
||||
|
||||
RfcommServiceProvider rfcomm_provider_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SERVER_SOCKET_H_
|
||||
|
||||
@@ -1,194 +1,194 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
|
||||
#include "platform/base/logging.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothSocket::BluetoothSocket(StreamSocket streamSocket)
|
||||
: windows_socket_(streamSocket) {
|
||||
bluetooth_device_ = std::make_unique<BluetoothDevice>(
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
|
||||
windows_socket_.Information().RemoteHostName())
|
||||
.get());
|
||||
input_stream_ =
|
||||
std::make_unique<BluetoothInputStream>(windows_socket_.InputStream());
|
||||
output_stream_ =
|
||||
std::make_unique<BluetoothOutputStream>(windows_socket_.OutputStream());
|
||||
}
|
||||
|
||||
BluetoothSocket::BluetoothSocket() {}
|
||||
|
||||
BluetoothSocket::~BluetoothSocket() {}
|
||||
|
||||
// NOTE:
|
||||
// It is an undefined behavior if GetInputStream() or GetOutputStream() is
|
||||
// called for a not-connected BluetoothSocket, i.e. any object that is not
|
||||
// returned by BluetoothClassicMedium::ConnectToService() for client side or
|
||||
// BluetoothServerSocket::Accept() for server side of connection.
|
||||
// Returns the InputStream of this connected BluetoothSocket.
|
||||
InputStream& BluetoothSocket::GetInputStream() { return *input_stream_.get(); }
|
||||
|
||||
// Returns the OutputStream of this connected BluetoothSocket.
|
||||
OutputStream& BluetoothSocket::GetOutputStream() {
|
||||
return *output_stream_.get();
|
||||
}
|
||||
|
||||
// Closes both input and output streams, marks Socket as closed.
|
||||
// After this call object should be treated as not connected.
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception BluetoothSocket::Close() {
|
||||
// The Close method aborts any pending operations and releases all unmanaged
|
||||
// resources associated with the StreamSocket object, including the Input and
|
||||
// Output streams
|
||||
windows_socket_.Close();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#getRemoteDevice()
|
||||
// Returns valid BluetoothDevice pointer if there is a connection, and
|
||||
// nullptr otherwise.
|
||||
api::BluetoothDevice* BluetoothSocket::GetRemoteDevice() {
|
||||
return bluetooth_device_.get();
|
||||
}
|
||||
|
||||
// Starts an asynchronous operation on a StreamSocket object to connect to a
|
||||
// remote network destination specified by a remote hostname and a remote
|
||||
// service name.
|
||||
void BluetoothSocket::Connect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName) {
|
||||
windows_socket_ = winrt::Windows::Networking::Sockets::StreamSocket();
|
||||
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket.connectasync?view=winrt-20348
|
||||
windows_socket_.ConnectAsync(connectionHostName, connectionServiceName).get();
|
||||
|
||||
auto info = windows_socket_.Information();
|
||||
auto hostName = info.RemoteHostName();
|
||||
|
||||
bluetooth_device_ = std::make_unique<BluetoothDevice>(
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
|
||||
windows_socket_.Information().RemoteHostName())
|
||||
.get());
|
||||
|
||||
input_stream_ =
|
||||
std::make_unique<BluetoothInputStream>(windows_socket_.InputStream());
|
||||
output_stream_ =
|
||||
std::make_unique<BluetoothOutputStream>(windows_socket_.OutputStream());
|
||||
}
|
||||
|
||||
BluetoothSocket::BluetoothInputStream::BluetoothInputStream(
|
||||
IInputStream stream) {
|
||||
winrt_stream_ = stream;
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BluetoothSocket::BluetoothInputStream::Read(
|
||||
std::int64_t size) {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
Buffer buffer = Buffer(size);
|
||||
|
||||
winrt_stream_.ReadAsync(buffer, size, InputStreamOptions::Partial).get();
|
||||
|
||||
DataReader dataReader = DataReader::FromBuffer(buffer);
|
||||
|
||||
ByteArray data((char*)buffer.data(), buffer.Length());
|
||||
|
||||
return ExceptionOr(data);
|
||||
}
|
||||
|
||||
IAsyncAction BluetoothSocket::CancelIOAsync() {
|
||||
// Cancels pending reads and writes over a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket.cancelioasync?view=winrt-20348
|
||||
return windows_socket_.CancelIOAsync();
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothInputStream::Close() {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kSuccess}; // Already closed, don't error out
|
||||
}
|
||||
|
||||
try {
|
||||
winrt_stream_.Close();
|
||||
winrt_stream_ = nullptr;
|
||||
} catch (std::exception exception) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
BluetoothSocket::BluetoothOutputStream::BluetoothOutputStream(
|
||||
IOutputStream stream) {
|
||||
winrt_stream_ = stream;
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Write(const ByteArray& data) {
|
||||
Buffer buffer = Buffer(data.size());
|
||||
std::memcpy(buffer.data(), data.data(), data.size());
|
||||
buffer.Length(data.size());
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
try {
|
||||
auto hresult = winrt_stream_.WriteAsync(buffer).get();
|
||||
} catch (winrt::hresult_error const& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": winrt exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Flush() {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
try {
|
||||
winrt_stream_.FlushAsync().get();
|
||||
} catch (std::exception exception) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Close() {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kSuccess}; // Already closed, don't error out
|
||||
}
|
||||
|
||||
try {
|
||||
winrt_stream_.Close();
|
||||
winrt_stream_ = nullptr;
|
||||
} catch (std::exception exception) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/bluetooth_classic_socket.h"
|
||||
|
||||
#include "platform/base/logging.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothSocket::BluetoothSocket(StreamSocket streamSocket)
|
||||
: windows_socket_(streamSocket) {
|
||||
bluetooth_device_ = std::make_unique<BluetoothDevice>(
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
|
||||
windows_socket_.Information().RemoteHostName())
|
||||
.get());
|
||||
input_stream_ =
|
||||
std::make_unique<BluetoothInputStream>(windows_socket_.InputStream());
|
||||
output_stream_ =
|
||||
std::make_unique<BluetoothOutputStream>(windows_socket_.OutputStream());
|
||||
}
|
||||
|
||||
BluetoothSocket::BluetoothSocket() {}
|
||||
|
||||
BluetoothSocket::~BluetoothSocket() {}
|
||||
|
||||
// NOTE:
|
||||
// It is an undefined behavior if GetInputStream() or GetOutputStream() is
|
||||
// called for a not-connected BluetoothSocket, i.e. any object that is not
|
||||
// returned by BluetoothClassicMedium::ConnectToService() for client side or
|
||||
// BluetoothServerSocket::Accept() for server side of connection.
|
||||
// Returns the InputStream of this connected BluetoothSocket.
|
||||
InputStream& BluetoothSocket::GetInputStream() { return *input_stream_.get(); }
|
||||
|
||||
// Returns the OutputStream of this connected BluetoothSocket.
|
||||
OutputStream& BluetoothSocket::GetOutputStream() {
|
||||
return *output_stream_.get();
|
||||
}
|
||||
|
||||
// Closes both input and output streams, marks Socket as closed.
|
||||
// After this call object should be treated as not connected.
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception BluetoothSocket::Close() {
|
||||
// The Close method aborts any pending operations and releases all unmanaged
|
||||
// resources associated with the StreamSocket object, including the Input and
|
||||
// Output streams
|
||||
windows_socket_.Close();
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#getRemoteDevice()
|
||||
// Returns valid BluetoothDevice pointer if there is a connection, and
|
||||
// nullptr otherwise.
|
||||
api::BluetoothDevice* BluetoothSocket::GetRemoteDevice() {
|
||||
return bluetooth_device_.get();
|
||||
}
|
||||
|
||||
// Starts an asynchronous operation on a StreamSocket object to connect to a
|
||||
// remote network destination specified by a remote hostname and a remote
|
||||
// service name.
|
||||
void BluetoothSocket::Connect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName) {
|
||||
windows_socket_ = winrt::Windows::Networking::Sockets::StreamSocket();
|
||||
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket.connectasync?view=winrt-20348
|
||||
windows_socket_.ConnectAsync(connectionHostName, connectionServiceName).get();
|
||||
|
||||
auto info = windows_socket_.Information();
|
||||
auto hostName = info.RemoteHostName();
|
||||
|
||||
bluetooth_device_ = std::make_unique<BluetoothDevice>(
|
||||
winrt::Windows::Devices::Bluetooth::BluetoothDevice::FromHostNameAsync(
|
||||
windows_socket_.Information().RemoteHostName())
|
||||
.get());
|
||||
|
||||
input_stream_ =
|
||||
std::make_unique<BluetoothInputStream>(windows_socket_.InputStream());
|
||||
output_stream_ =
|
||||
std::make_unique<BluetoothOutputStream>(windows_socket_.OutputStream());
|
||||
}
|
||||
|
||||
BluetoothSocket::BluetoothInputStream::BluetoothInputStream(
|
||||
IInputStream stream) {
|
||||
winrt_stream_ = stream;
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> BluetoothSocket::BluetoothInputStream::Read(
|
||||
std::int64_t size) {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
Buffer buffer = Buffer(size);
|
||||
|
||||
winrt_stream_.ReadAsync(buffer, size, InputStreamOptions::Partial).get();
|
||||
|
||||
DataReader dataReader = DataReader::FromBuffer(buffer);
|
||||
|
||||
ByteArray data((char*)buffer.data(), buffer.Length());
|
||||
|
||||
return ExceptionOr(data);
|
||||
}
|
||||
|
||||
IAsyncAction BluetoothSocket::CancelIOAsync() {
|
||||
// Cancels pending reads and writes over a StreamSocket object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket.cancelioasync?view=winrt-20348
|
||||
return windows_socket_.CancelIOAsync();
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothInputStream::Close() {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kSuccess}; // Already closed, don't error out
|
||||
}
|
||||
|
||||
try {
|
||||
winrt_stream_.Close();
|
||||
winrt_stream_ = nullptr;
|
||||
} catch (std::exception exception) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
BluetoothSocket::BluetoothOutputStream::BluetoothOutputStream(
|
||||
IOutputStream stream) {
|
||||
winrt_stream_ = stream;
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Write(const ByteArray& data) {
|
||||
Buffer buffer = Buffer(data.size());
|
||||
std::memcpy(buffer.data(), data.data(), data.size());
|
||||
buffer.Length(data.size());
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
try {
|
||||
auto hresult = winrt_stream_.WriteAsync(buffer).get();
|
||||
} catch (winrt::hresult_error const& ex) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": winrt exception: " << ex.code() << ": "
|
||||
<< winrt::to_string(ex.message());
|
||||
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Flush() {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
try {
|
||||
winrt_stream_.FlushAsync().get();
|
||||
} catch (std::exception exception) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
Exception BluetoothSocket::BluetoothOutputStream::Close() {
|
||||
if (winrt_stream_ == nullptr) {
|
||||
return {Exception::kSuccess}; // Already closed, don't error out
|
||||
}
|
||||
|
||||
try {
|
||||
winrt_stream_.Close();
|
||||
winrt_stream_ = nullptr;
|
||||
} catch (std::exception exception) {
|
||||
return {Exception::kFailed};
|
||||
}
|
||||
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -1,139 +1,139 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
|
||||
#include "platform/api/bluetooth_classic.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Storage.Streams.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Provides data for a hostname or an IP address.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.hostname?view=winrt-20348
|
||||
using winrt::Windows::Networking::HostName;
|
||||
|
||||
// Supports network communication using a stream socket over Bluetooth RFCOMM.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::IStreamSocket;
|
||||
using winrt::Windows::Networking::Sockets::StreamSocket;
|
||||
|
||||
// Provides a default implementation of the IBuffer interface and its related
|
||||
// interfaces.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.buffer?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::Buffer;
|
||||
|
||||
// Represents a sequential stream of bytes to be read.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.iinputstream?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::IInputStream;
|
||||
|
||||
// Represents a sequential stream of bytes to be written.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.ioutputstream?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::IOutputStream;
|
||||
|
||||
// Specifies the read options for an input stream.
|
||||
// This enumeration has a FlagsAttribute attribute that allows a bitwise
|
||||
// combination of its member values.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.inputstreamoptions?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::InputStreamOptions;
|
||||
|
||||
// Reads data from an input stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataReader;
|
||||
|
||||
// Represents an asynchronous action.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncaction?view=winrt-20348
|
||||
using winrt::Windows::Foundation::IAsyncAction;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html.
|
||||
class BluetoothSocket : public api::BluetoothSocket {
|
||||
public:
|
||||
BluetoothSocket();
|
||||
|
||||
BluetoothSocket(StreamSocket streamSocket);
|
||||
|
||||
~BluetoothSocket() override;
|
||||
|
||||
// NOTE:
|
||||
// It is an undefined behavior if GetInputStream() or GetOutputStream() is
|
||||
// called for a not-connected BluetoothSocket, i.e. any object that is not
|
||||
// returned by BluetoothClassicMedium::ConnectToService() for client side or
|
||||
// BluetoothServerSocket::Accept() for server side of connection.
|
||||
|
||||
// Returns the InputStream of this connected BluetoothSocket.
|
||||
InputStream& GetInputStream() override;
|
||||
|
||||
// Returns the OutputStream of this connected BluetoothSocket.
|
||||
OutputStream& GetOutputStream() override;
|
||||
|
||||
// Closes both input and output streams, marks Socket as closed.
|
||||
// After this call object should be treated as not connected.
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception Close() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#getRemoteDevice()
|
||||
// Returns valid BluetoothDevice pointer if there is a connection, and
|
||||
// nullptr otherwise.
|
||||
api::BluetoothDevice* GetRemoteDevice() override;
|
||||
|
||||
// Connect asynchronously to the target remote device
|
||||
void Connect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName);
|
||||
|
||||
IAsyncAction CancelIOAsync();
|
||||
|
||||
private:
|
||||
class BluetoothInputStream : public InputStream {
|
||||
public:
|
||||
BluetoothInputStream(IInputStream stream);
|
||||
~BluetoothInputStream() override = default;
|
||||
|
||||
ExceptionOr<ByteArray> Read(std::int64_t size) override;
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
IInputStream winrt_stream_;
|
||||
};
|
||||
|
||||
class BluetoothOutputStream : public OutputStream {
|
||||
public:
|
||||
BluetoothOutputStream(IOutputStream stream);
|
||||
~BluetoothOutputStream() override = default;
|
||||
|
||||
Exception Write(const ByteArray& data) override;
|
||||
Exception Flush() override;
|
||||
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
IOutputStream winrt_stream_;
|
||||
};
|
||||
|
||||
std::unique_ptr<BluetoothInputStream> input_stream_;
|
||||
std::unique_ptr<BluetoothOutputStream> output_stream_;
|
||||
|
||||
StreamSocket windows_socket_;
|
||||
std::unique_ptr<BluetoothDevice> bluetooth_device_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
|
||||
#include "platform/api/bluetooth_classic.h"
|
||||
#include "platform/impl/windows/bluetooth_classic_device.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Networking.Sockets.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Storage.Streams.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// Provides data for a hostname or an IP address.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.hostname?view=winrt-20348
|
||||
using winrt::Windows::Networking::HostName;
|
||||
|
||||
// Supports network communication using a stream socket over Bluetooth RFCOMM.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.streamsocket?view=winrt-20348
|
||||
using winrt::Windows::Networking::Sockets::IStreamSocket;
|
||||
using winrt::Windows::Networking::Sockets::StreamSocket;
|
||||
|
||||
// Provides a default implementation of the IBuffer interface and its related
|
||||
// interfaces.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.buffer?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::Buffer;
|
||||
|
||||
// Represents a sequential stream of bytes to be read.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.iinputstream?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::IInputStream;
|
||||
|
||||
// Represents a sequential stream of bytes to be written.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.ioutputstream?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::IOutputStream;
|
||||
|
||||
// Specifies the read options for an input stream.
|
||||
// This enumeration has a FlagsAttribute attribute that allows a bitwise
|
||||
// combination of its member values.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.inputstreamoptions?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::InputStreamOptions;
|
||||
|
||||
// Reads data from an input stream.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.storage.streams.datareader?view=winrt-20348
|
||||
using winrt::Windows::Storage::Streams::DataReader;
|
||||
|
||||
// Represents an asynchronous action.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.foundation.iasyncaction?view=winrt-20348
|
||||
using winrt::Windows::Foundation::IAsyncAction;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html.
|
||||
class BluetoothSocket : public api::BluetoothSocket {
|
||||
public:
|
||||
BluetoothSocket();
|
||||
|
||||
BluetoothSocket(StreamSocket streamSocket);
|
||||
|
||||
~BluetoothSocket() override;
|
||||
|
||||
// NOTE:
|
||||
// It is an undefined behavior if GetInputStream() or GetOutputStream() is
|
||||
// called for a not-connected BluetoothSocket, i.e. any object that is not
|
||||
// returned by BluetoothClassicMedium::ConnectToService() for client side or
|
||||
// BluetoothServerSocket::Accept() for server side of connection.
|
||||
|
||||
// Returns the InputStream of this connected BluetoothSocket.
|
||||
InputStream& GetInputStream() override;
|
||||
|
||||
// Returns the OutputStream of this connected BluetoothSocket.
|
||||
OutputStream& GetOutputStream() override;
|
||||
|
||||
// Closes both input and output streams, marks Socket as closed.
|
||||
// After this call object should be treated as not connected.
|
||||
// Returns Exception::kIo on error, Exception::kSuccess otherwise.
|
||||
Exception Close() override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothSocket.html#getRemoteDevice()
|
||||
// Returns valid BluetoothDevice pointer if there is a connection, and
|
||||
// nullptr otherwise.
|
||||
api::BluetoothDevice* GetRemoteDevice() override;
|
||||
|
||||
// Connect asynchronously to the target remote device
|
||||
void Connect(HostName connectionHostName,
|
||||
winrt::hstring connectionServiceName);
|
||||
|
||||
IAsyncAction CancelIOAsync();
|
||||
|
||||
private:
|
||||
class BluetoothInputStream : public InputStream {
|
||||
public:
|
||||
BluetoothInputStream(IInputStream stream);
|
||||
~BluetoothInputStream() override = default;
|
||||
|
||||
ExceptionOr<ByteArray> Read(std::int64_t size) override;
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
IInputStream winrt_stream_;
|
||||
};
|
||||
|
||||
class BluetoothOutputStream : public OutputStream {
|
||||
public:
|
||||
BluetoothOutputStream(IOutputStream stream);
|
||||
~BluetoothOutputStream() override = default;
|
||||
|
||||
Exception Write(const ByteArray& data) override;
|
||||
Exception Flush() override;
|
||||
|
||||
Exception Close() override;
|
||||
|
||||
private:
|
||||
IOutputStream winrt_stream_;
|
||||
};
|
||||
|
||||
std::unique_ptr<BluetoothInputStream> input_stream_;
|
||||
std::unique_ptr<BluetoothOutputStream> output_stream_;
|
||||
|
||||
StreamSocket windows_socket_;
|
||||
std::unique_ptr<BluetoothDevice> bluetooth_device_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_BLUETOOTH_CLASSIC_SOCKET_H_
|
||||
|
||||
@@ -1,104 +1,104 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/condition_variable.h"
|
||||
|
||||
#include <future> // NOLINT
|
||||
|
||||
#include "absl/time/clock.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/impl/windows/mutex.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class ConditionVariableTests : public testing::Test {
|
||||
public:
|
||||
class ConditionVariableTest {
|
||||
public:
|
||||
ConditionVariableTest() {}
|
||||
|
||||
std::future<bool> WaitForEvent(bool timedWait, // NOLINT
|
||||
const absl::Duration* timeout) {
|
||||
return std::async(
|
||||
std::launch::async,
|
||||
[this, timedWait, timeout]() mutable {
|
||||
std::thread::id currentThread = std::this_thread::get_id();
|
||||
|
||||
if (timedWait == true) {
|
||||
auto result = this->condition_variable_actual_.Wait(*timeout);
|
||||
if (result.value == location::nearby::Exception::kSuccess) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this->condition_variable_actual_.Wait();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void PostEvent() {
|
||||
std::lock_guard<std::mutex> guard(mutex_actual_.GetWindowsMutex());
|
||||
condition_variable_actual_.Notify();
|
||||
}
|
||||
|
||||
private:
|
||||
location::nearby::windows::Mutex mutex_actual_ =
|
||||
location::nearby::windows::Mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRegular);
|
||||
location::nearby::windows::Mutex& mutex_ = mutex_actual_;
|
||||
location::nearby::windows::ConditionVariable condition_variable_actual_ =
|
||||
location::nearby::windows::ConditionVariable(&mutex_);
|
||||
location::nearby::windows::ConditionVariable& condition_variable_ =
|
||||
condition_variable_actual_;
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(ConditionVariableTests, SuccessfulCreation) {
|
||||
// Arrange
|
||||
ConditionVariableTest conditionVariableTest;
|
||||
|
||||
auto result = conditionVariableTest.WaitForEvent(false, nullptr);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
// Act
|
||||
conditionVariableTest.PostEvent();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get());
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariableTests, TimedCreation) {
|
||||
// Arrange
|
||||
ConditionVariableTest conditionVariableTest;
|
||||
const absl::Duration duration = absl::Milliseconds(100);
|
||||
|
||||
// Act
|
||||
auto result = conditionVariableTest.WaitForEvent(true, &duration);
|
||||
|
||||
// Assert
|
||||
ASSERT_FALSE(result.get()); // Timed out
|
||||
|
||||
// Act
|
||||
result = conditionVariableTest.WaitForEvent(true, &duration);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
conditionVariableTest.PostEvent();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get()); // Didn't timeout
|
||||
}
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/condition_variable.h"
|
||||
|
||||
#include <future> // NOLINT
|
||||
|
||||
#include "absl/time/clock.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/impl/windows/mutex.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class ConditionVariableTests : public testing::Test {
|
||||
public:
|
||||
class ConditionVariableTest {
|
||||
public:
|
||||
ConditionVariableTest() {}
|
||||
|
||||
std::future<bool> WaitForEvent(bool timedWait, // NOLINT
|
||||
const absl::Duration* timeout) {
|
||||
return std::async(
|
||||
std::launch::async,
|
||||
[this, timedWait, timeout]() mutable {
|
||||
std::thread::id currentThread = std::this_thread::get_id();
|
||||
|
||||
if (timedWait == true) {
|
||||
auto result = this->condition_variable_actual_.Wait(*timeout);
|
||||
if (result.value == location::nearby::Exception::kSuccess) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this->condition_variable_actual_.Wait();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void PostEvent() {
|
||||
std::lock_guard<std::mutex> guard(mutex_actual_.GetWindowsMutex());
|
||||
condition_variable_actual_.Notify();
|
||||
}
|
||||
|
||||
private:
|
||||
location::nearby::windows::Mutex mutex_actual_ =
|
||||
location::nearby::windows::Mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRegular);
|
||||
location::nearby::windows::Mutex& mutex_ = mutex_actual_;
|
||||
location::nearby::windows::ConditionVariable condition_variable_actual_ =
|
||||
location::nearby::windows::ConditionVariable(&mutex_);
|
||||
location::nearby::windows::ConditionVariable& condition_variable_ =
|
||||
condition_variable_actual_;
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(ConditionVariableTests, SuccessfulCreation) {
|
||||
// Arrange
|
||||
ConditionVariableTest conditionVariableTest;
|
||||
|
||||
auto result = conditionVariableTest.WaitForEvent(false, nullptr);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
// Act
|
||||
conditionVariableTest.PostEvent();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get());
|
||||
}
|
||||
|
||||
TEST_F(ConditionVariableTests, TimedCreation) {
|
||||
// Arrange
|
||||
ConditionVariableTest conditionVariableTest;
|
||||
const absl::Duration duration = absl::Milliseconds(100);
|
||||
|
||||
// Act
|
||||
auto result = conditionVariableTest.WaitForEvent(true, &duration);
|
||||
|
||||
// Assert
|
||||
ASSERT_FALSE(result.get()); // Timed out
|
||||
|
||||
// Act
|
||||
result = conditionVariableTest.WaitForEvent(true, &duration);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
conditionVariableTest.PostEvent();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get()); // Didn't timeout
|
||||
}
|
||||
|
||||
@@ -1,186 +1,186 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/shared/count_down_latch.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "platform/api/platform.h"
|
||||
|
||||
class CountDownLatchTests : public testing::Test {
|
||||
public:
|
||||
class TestData {
|
||||
public:
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch>& countDownLatch;
|
||||
LONG volatile& count;
|
||||
};
|
||||
|
||||
class CountDownLatchTest {
|
||||
public:
|
||||
static DWORD ThreadProcCountDown(LPVOID lpParam) {
|
||||
TestData* testData = static_cast<TestData*>(lpParam);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
InterlockedIncrement(&testData->count);
|
||||
testData->countDownLatch->CountDown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD ThreadProcAwait(LPVOID lpParam) {
|
||||
TestData* testData = static_cast<TestData*>(lpParam);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
testData->countDownLatch->Await();
|
||||
InterlockedIncrement(&testData->count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
CountDownLatchTests() {}
|
||||
};
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchAwaitSucceeds) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(3);
|
||||
|
||||
HANDLE hThreads[3];
|
||||
DWORD dwThreadID;
|
||||
|
||||
TestData testData{countDownLatch, count};
|
||||
|
||||
// Setup 3 threads
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// TODO: More complex scenarios may require use of a parameter
|
||||
// to the thread procedure, such as an event per thread to
|
||||
// be used for synchronization.
|
||||
hThreads[i] = CreateThread(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
CountDownLatchTest::ThreadProcCountDown, // name of the thread function
|
||||
&testData, // no thread parameters
|
||||
0, // default startup flags
|
||||
&dwThreadID);
|
||||
|
||||
EXPECT_TRUE(hThreads[i] != NULL);
|
||||
}
|
||||
|
||||
// Act
|
||||
location::nearby::Exception result = countDownLatch->Await();
|
||||
|
||||
//
|
||||
// Assert
|
||||
EXPECT_EQ(result.value, location::nearby::Exception::kSuccess);
|
||||
EXPECT_EQ(count, 3);
|
||||
}
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchAwaitTimeoutTimesOut) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(3);
|
||||
|
||||
// Act
|
||||
location::nearby::ExceptionOr<bool> result =
|
||||
countDownLatch->Await(absl::Milliseconds(5));
|
||||
|
||||
Sleep(40);
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result.GetResult());
|
||||
// TODO(jfcarroll)I think there's a bug in the shared version of this, it's
|
||||
// not returning a timeout exception, need to look at it some more.
|
||||
// EXPECT_EQ(result.GetException().value,
|
||||
// location::nearby::Exception::kTimeout);
|
||||
}
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchAwaitNoTimeoutSucceeds) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(3);
|
||||
|
||||
TestData testData{countDownLatch, count};
|
||||
|
||||
HANDLE hThreads[3];
|
||||
DWORD dwThreadID;
|
||||
|
||||
// Setup 3 threads
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// TODO: More complex scenarios may require use of a parameter
|
||||
// to the thread procedure, such as an event per thread to
|
||||
// be used for synchronization.
|
||||
hThreads[i] = CreateThread(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
CountDownLatchTest::ThreadProcCountDown, // name of the thread function
|
||||
&testData, // no thread parameters
|
||||
0, // default startup flags
|
||||
&dwThreadID);
|
||||
|
||||
EXPECT_TRUE(hThreads[i] != NULL);
|
||||
}
|
||||
|
||||
WaitForMultipleObjects(3, hThreads, true, INFINITE);
|
||||
// Act
|
||||
location::nearby::ExceptionOr<bool> result =
|
||||
countDownLatch->Await(absl::Milliseconds(100));
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(result.GetResult());
|
||||
EXPECT_EQ(result.GetException().value, location::nearby::Exception::kSuccess);
|
||||
EXPECT_EQ(count, 3);
|
||||
}
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchCountDownBeforeAwaitSucceeds) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(1);
|
||||
|
||||
HANDLE hThread;
|
||||
DWORD dwThreadID;
|
||||
|
||||
TestData testData{countDownLatch, count};
|
||||
|
||||
hThread = CreateThread(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
CountDownLatchTest::ThreadProcAwait, // name of the thread function
|
||||
&testData, // no thread parameters
|
||||
0, // default startup flags
|
||||
&dwThreadID);
|
||||
|
||||
EXPECT_TRUE(hThread != NULL);
|
||||
|
||||
// Act
|
||||
countDownLatch->CountDown(); // This countdown occurs before the thread has a
|
||||
// chance to run
|
||||
|
||||
if (hThread != NULL) {
|
||||
WaitForSingleObject(hThread,
|
||||
INFINITE); // This will wait till the thread exits
|
||||
}
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(count, 1);
|
||||
}
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/shared/count_down_latch.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "platform/api/platform.h"
|
||||
|
||||
class CountDownLatchTests : public testing::Test {
|
||||
public:
|
||||
class TestData {
|
||||
public:
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch>& countDownLatch;
|
||||
LONG volatile& count;
|
||||
};
|
||||
|
||||
class CountDownLatchTest {
|
||||
public:
|
||||
static DWORD ThreadProcCountDown(LPVOID lpParam) {
|
||||
TestData* testData = static_cast<TestData*>(lpParam);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
InterlockedIncrement(&testData->count);
|
||||
testData->countDownLatch->CountDown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD ThreadProcAwait(LPVOID lpParam) {
|
||||
TestData* testData = static_cast<TestData*>(lpParam);
|
||||
|
||||
Sleep(1);
|
||||
|
||||
testData->countDownLatch->Await();
|
||||
InterlockedIncrement(&testData->count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
CountDownLatchTests() {}
|
||||
};
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchAwaitSucceeds) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(3);
|
||||
|
||||
HANDLE hThreads[3];
|
||||
DWORD dwThreadID;
|
||||
|
||||
TestData testData{countDownLatch, count};
|
||||
|
||||
// Setup 3 threads
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// TODO: More complex scenarios may require use of a parameter
|
||||
// to the thread procedure, such as an event per thread to
|
||||
// be used for synchronization.
|
||||
hThreads[i] = CreateThread(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
CountDownLatchTest::ThreadProcCountDown, // name of the thread function
|
||||
&testData, // no thread parameters
|
||||
0, // default startup flags
|
||||
&dwThreadID);
|
||||
|
||||
EXPECT_TRUE(hThreads[i] != NULL);
|
||||
}
|
||||
|
||||
// Act
|
||||
location::nearby::Exception result = countDownLatch->Await();
|
||||
|
||||
//
|
||||
// Assert
|
||||
EXPECT_EQ(result.value, location::nearby::Exception::kSuccess);
|
||||
EXPECT_EQ(count, 3);
|
||||
}
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchAwaitTimeoutTimesOut) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(3);
|
||||
|
||||
// Act
|
||||
location::nearby::ExceptionOr<bool> result =
|
||||
countDownLatch->Await(absl::Milliseconds(5));
|
||||
|
||||
Sleep(40);
|
||||
|
||||
// Assert
|
||||
EXPECT_FALSE(result.GetResult());
|
||||
// TODO(jfcarroll)I think there's a bug in the shared version of this, it's
|
||||
// not returning a timeout exception, need to look at it some more.
|
||||
// EXPECT_EQ(result.GetException().value,
|
||||
// location::nearby::Exception::kTimeout);
|
||||
}
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchAwaitNoTimeoutSucceeds) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(3);
|
||||
|
||||
TestData testData{countDownLatch, count};
|
||||
|
||||
HANDLE hThreads[3];
|
||||
DWORD dwThreadID;
|
||||
|
||||
// Setup 3 threads
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// TODO: More complex scenarios may require use of a parameter
|
||||
// to the thread procedure, such as an event per thread to
|
||||
// be used for synchronization.
|
||||
hThreads[i] = CreateThread(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
CountDownLatchTest::ThreadProcCountDown, // name of the thread function
|
||||
&testData, // no thread parameters
|
||||
0, // default startup flags
|
||||
&dwThreadID);
|
||||
|
||||
EXPECT_TRUE(hThreads[i] != NULL);
|
||||
}
|
||||
|
||||
WaitForMultipleObjects(3, hThreads, true, INFINITE);
|
||||
// Act
|
||||
location::nearby::ExceptionOr<bool> result =
|
||||
countDownLatch->Await(absl::Milliseconds(100));
|
||||
|
||||
// Assert
|
||||
EXPECT_TRUE(result.GetResult());
|
||||
EXPECT_EQ(result.GetException().value, location::nearby::Exception::kSuccess);
|
||||
EXPECT_EQ(count, 3);
|
||||
}
|
||||
|
||||
TEST_F(CountDownLatchTests, CountDownLatchCountDownBeforeAwaitSucceeds) {
|
||||
// Arrange
|
||||
LONG volatile count = 0;
|
||||
std::unique_ptr<location::nearby::api::CountDownLatch> countDownLatch =
|
||||
location::nearby::api::ImplementationPlatform::CreateCountDownLatch(1);
|
||||
|
||||
HANDLE hThread;
|
||||
DWORD dwThreadID;
|
||||
|
||||
TestData testData{countDownLatch, count};
|
||||
|
||||
hThread = CreateThread(
|
||||
NULL, // default security
|
||||
0, // default stack size
|
||||
CountDownLatchTest::ThreadProcAwait, // name of the thread function
|
||||
&testData, // no thread parameters
|
||||
0, // default startup flags
|
||||
&dwThreadID);
|
||||
|
||||
EXPECT_TRUE(hThread != NULL);
|
||||
|
||||
// Act
|
||||
countDownLatch->CountDown(); // This countdown occurs before the thread has a
|
||||
// chance to run
|
||||
|
||||
if (hThread != NULL) {
|
||||
WaitForSingleObject(hThread,
|
||||
INFINITE); // This will wait till the thread exits
|
||||
}
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(count, 1);
|
||||
}
|
||||
|
||||
@@ -1,348 +1,348 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/executor.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "platform/impl/windows/test_data.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
executor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorAfterShutdownFails) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
executor->Shutdown();
|
||||
|
||||
// Act
|
||||
executor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorExecuteNullSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
executor->Execute(nullptr);
|
||||
executor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
executor->Execute(nullptr);
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_ALL_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 5; index++) {
|
||||
executor->Execute([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output.append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
auto workerThreadId = threadIds->at(1);
|
||||
for (int index = 1; index < threadIds->size(); index++) {
|
||||
ASSERT_EQ(threadIds->at(index), workerThreadId);
|
||||
}
|
||||
|
||||
// We should of run them in the order submitted
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorSingleTaskSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(2);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
executor->Execute([output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run the task
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(2);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 5; index++) {
|
||||
executor->Execute([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s %d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output->append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorSingleTaskAfterShutdownFails) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(2);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Act
|
||||
executor->Execute([output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run the task
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorNegativeThreadsThrows) {
|
||||
// Arrange
|
||||
// Act
|
||||
// Assert
|
||||
EXPECT_THROW(
|
||||
{
|
||||
try {
|
||||
auto result =
|
||||
std::make_unique<location::nearby::windows::Executor>(-1);
|
||||
} catch (const std::invalid_argument::exception& e) {
|
||||
// and this tests that it has the correct message
|
||||
EXPECT_STREQ(INVALID_ARGUMENT_TEXT, e.what());
|
||||
throw;
|
||||
}
|
||||
},
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorTooManyThreadsThrows) {
|
||||
// Arrange
|
||||
// Act
|
||||
// Assert
|
||||
EXPECT_THROW(
|
||||
{
|
||||
try {
|
||||
auto result =
|
||||
std::make_unique<location::nearby::windows::Executor>(65);
|
||||
} catch (const location::nearby::windows::ThreadPoolException& e) {
|
||||
// and this tests that it has the correct message
|
||||
EXPECT_STREQ(THREADPOOL_MAX_SIZE_TEXT, e.what());
|
||||
throw;
|
||||
}
|
||||
},
|
||||
location::nearby::windows::ThreadPoolException);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests,
|
||||
MultiThreadedExecutorMultipleTasksLargeNumberOfThreadsSucceeds) {
|
||||
// Arrange
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(
|
||||
MAXIMUM_WAIT_OBJECTS - 1);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::vector<DWORD> threadIds = std::vector<DWORD>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds.push_back(GetCurrentThreadId());
|
||||
|
||||
CRITICAL_SECTION testCriticalSection;
|
||||
InitializeCriticalSection(&testCriticalSection);
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 250; index++) {
|
||||
executor->Execute(
|
||||
[output, &threadIds, index, &testCriticalSection]() mutable {
|
||||
DWORD id = GetCurrentThreadId();
|
||||
|
||||
EnterCriticalSection(&testCriticalSection);
|
||||
|
||||
threadIds.push_back(id);
|
||||
output->append(RUNNABLE_TEXT);
|
||||
output->append(std::to_string(index));
|
||||
output->append(RUNNABLE_SEPARATOR_TEXT);
|
||||
|
||||
LeaveCriticalSection(&testCriticalSection);
|
||||
// Using rand since this is in a critical section
|
||||
// and windows doesn't have a rand_r anyway
|
||||
auto sleepTime = (std::rand() % 101) + 1; // NOLINT
|
||||
|
||||
Sleep(sleepTime);
|
||||
});
|
||||
}
|
||||
|
||||
executor->Shutdown();
|
||||
DeleteCriticalSection(&testCriticalSection);
|
||||
|
||||
// Assert
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds.at(0));
|
||||
|
||||
std::sort(threadIds.begin(), threadIds.end());
|
||||
int64_t uniqueIds =
|
||||
std::unique(threadIds.begin(), threadIds.end()) - threadIds.begin();
|
||||
|
||||
ASSERT_EQ(uniqueIds, 64);
|
||||
// We should've run 1 time on the main thread, and 200 times on the
|
||||
// workerThreads
|
||||
ASSERT_EQ(threadIds.size(), 251);
|
||||
}
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/executor.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
#include "platform/impl/windows/test_data.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
executor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorAfterShutdownFails) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
executor->Shutdown();
|
||||
|
||||
// Act
|
||||
executor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorExecuteNullSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
executor->Execute(nullptr);
|
||||
executor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
executor->Execute(nullptr);
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, SingleThreadedExecutorMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_ALL_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 5; index++) {
|
||||
executor->Execute([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output.append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
auto workerThreadId = threadIds->at(1);
|
||||
for (int index = 1; index < threadIds->size(); index++) {
|
||||
ASSERT_EQ(threadIds->at(index), workerThreadId);
|
||||
}
|
||||
|
||||
// We should of run them in the order submitted
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorSingleTaskSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(2);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
executor->Execute([output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run the task
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(2);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 5; index++) {
|
||||
executor->Execute([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s %d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output->append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorSingleTaskAfterShutdownFails) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(2);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
executor->Shutdown();
|
||||
|
||||
// Act
|
||||
executor->Execute([output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run the task
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorNegativeThreadsThrows) {
|
||||
// Arrange
|
||||
// Act
|
||||
// Assert
|
||||
EXPECT_THROW(
|
||||
{
|
||||
try {
|
||||
auto result =
|
||||
std::make_unique<location::nearby::windows::Executor>(-1);
|
||||
} catch (const std::invalid_argument::exception& e) {
|
||||
// and this tests that it has the correct message
|
||||
EXPECT_STREQ(INVALID_ARGUMENT_TEXT, e.what());
|
||||
throw;
|
||||
}
|
||||
},
|
||||
std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests, MultiThreadedExecutorTooManyThreadsThrows) {
|
||||
// Arrange
|
||||
// Act
|
||||
// Assert
|
||||
EXPECT_THROW(
|
||||
{
|
||||
try {
|
||||
auto result =
|
||||
std::make_unique<location::nearby::windows::Executor>(65);
|
||||
} catch (const location::nearby::windows::ThreadPoolException& e) {
|
||||
// and this tests that it has the correct message
|
||||
EXPECT_STREQ(THREADPOOL_MAX_SIZE_TEXT, e.what());
|
||||
throw;
|
||||
}
|
||||
},
|
||||
location::nearby::windows::ThreadPoolException);
|
||||
}
|
||||
|
||||
TEST(ExecutorTests,
|
||||
MultiThreadedExecutorMultipleTasksLargeNumberOfThreadsSucceeds) {
|
||||
// Arrange
|
||||
std::unique_ptr<location::nearby::windows::Executor> executor =
|
||||
std::make_unique<location::nearby::windows::Executor>(
|
||||
MAXIMUM_WAIT_OBJECTS - 1);
|
||||
|
||||
// Container to note threads that ran
|
||||
std::vector<DWORD> threadIds = std::vector<DWORD>();
|
||||
|
||||
std::shared_ptr<std::string> output = std::make_shared<std::string>();
|
||||
|
||||
threadIds.push_back(GetCurrentThreadId());
|
||||
|
||||
CRITICAL_SECTION testCriticalSection;
|
||||
InitializeCriticalSection(&testCriticalSection);
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 250; index++) {
|
||||
executor->Execute(
|
||||
[output, &threadIds, index, &testCriticalSection]() mutable {
|
||||
DWORD id = GetCurrentThreadId();
|
||||
|
||||
EnterCriticalSection(&testCriticalSection);
|
||||
|
||||
threadIds.push_back(id);
|
||||
output->append(RUNNABLE_TEXT);
|
||||
output->append(std::to_string(index));
|
||||
output->append(RUNNABLE_SEPARATOR_TEXT);
|
||||
|
||||
LeaveCriticalSection(&testCriticalSection);
|
||||
// Using rand since this is in a critical section
|
||||
// and windows doesn't have a rand_r anyway
|
||||
auto sleepTime = (std::rand() % 101) + 1; // NOLINT
|
||||
|
||||
Sleep(sleepTime);
|
||||
});
|
||||
}
|
||||
|
||||
executor->Shutdown();
|
||||
DeleteCriticalSection(&testCriticalSection);
|
||||
|
||||
// Assert
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds.at(0));
|
||||
|
||||
std::sort(threadIds.begin(), threadIds.end());
|
||||
int64_t uniqueIds =
|
||||
std::unique(threadIds.begin(), threadIds.end()) - threadIds.begin();
|
||||
|
||||
ASSERT_EQ(uniqueIds, 64);
|
||||
// We should've run 1 time on the main thread, and 200 times on the
|
||||
// workerThreads
|
||||
ASSERT_EQ(threadIds.size(), 251);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ cc_library(
|
||||
],
|
||||
textual_hdrs = glob(["**/*.h"]),
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/connections/windows:__subpackages__",
|
||||
"//third_party/nearby/connections/windows:__subpackages__",
|
||||
"//platform/impl/windows:__subpackages__",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -1,152 +1,152 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/input_file.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/base/payload_id.h"
|
||||
#include "platform/impl/windows/test_utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
class InputFileTests : public testing::Test {
|
||||
protected:
|
||||
// You can define per-test set-up logic as usual.
|
||||
void SetUp() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
|
||||
hFile_ = CreateFileA(
|
||||
test_utils::GetPayloadPath(payloadId).c_str(), // name of the write
|
||||
GENERIC_WRITE, // open for writing
|
||||
0, // do not share
|
||||
NULL, // default security
|
||||
CREATE_ALWAYS, // create new file only
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file
|
||||
NULL); // no attr. template
|
||||
|
||||
if (hFile_ == INVALID_HANDLE_VALUE) {
|
||||
NEARBY_LOG(ERROR,
|
||||
"Failed to create OutputFile with payloadId: %s and error: %d",
|
||||
test_utils::GetPayloadPath(payloadId).c_str(), GetLastError());
|
||||
}
|
||||
|
||||
const char* buffer = TEST_STRING;
|
||||
DWORD bytesWritten;
|
||||
|
||||
WriteFile(hFile_, buffer, lstrlenA(buffer) * sizeof(char), &bytesWritten,
|
||||
nullptr);
|
||||
|
||||
CloseHandle(hFile_);
|
||||
}
|
||||
|
||||
// You can define per-test tear-down logic as usual.
|
||||
void TearDown() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
BOOL FileExists(const char* szPath) {
|
||||
DWORD dwAttrib = GetFileAttributesA(szPath);
|
||||
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE hFile_ = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulCreation) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
EXPECT_NE(inputFile, nullptr);
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulGetFilePath) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
std::string fileName;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
fileName = inputFile->GetFilePath();
|
||||
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
|
||||
EXPECT_EQ(fileName, test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulGetTotalSize) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
int64_t size = -1;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
size = inputFile->GetTotalSize();
|
||||
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
|
||||
EXPECT_EQ(size, strlen(TEST_STRING));
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulRead) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
auto fileSize = inputFile->GetTotalSize();
|
||||
auto dataRead = inputFile->Read(fileSize);
|
||||
|
||||
EXPECT_TRUE(dataRead.ok());
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
|
||||
EXPECT_STREQ(std::string(dataRead.result()).c_str(), TEST_STRING);
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, FailedRead) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
auto fileSize = inputFile->GetTotalSize();
|
||||
EXPECT_NE(fileSize, -1);
|
||||
|
||||
auto dataRead = inputFile->Read(fileSize);
|
||||
EXPECT_TRUE(dataRead.ok());
|
||||
|
||||
dataRead = inputFile->Read(fileSize);
|
||||
std::string data = std::string(dataRead.result());
|
||||
|
||||
inputFile->Close();
|
||||
|
||||
EXPECT_STREQ(data.c_str(), "");
|
||||
}
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/input_file.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/base/payload_id.h"
|
||||
#include "platform/impl/windows/test_utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
class InputFileTests : public testing::Test {
|
||||
protected:
|
||||
// You can define per-test set-up logic as usual.
|
||||
void SetUp() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
|
||||
hFile_ = CreateFileA(
|
||||
test_utils::GetPayloadPath(payloadId).c_str(), // name of the write
|
||||
GENERIC_WRITE, // open for writing
|
||||
0, // do not share
|
||||
NULL, // default security
|
||||
CREATE_ALWAYS, // create new file only
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file
|
||||
NULL); // no attr. template
|
||||
|
||||
if (hFile_ == INVALID_HANDLE_VALUE) {
|
||||
NEARBY_LOG(ERROR,
|
||||
"Failed to create OutputFile with payloadId: %s and error: %d",
|
||||
test_utils::GetPayloadPath(payloadId).c_str(), GetLastError());
|
||||
}
|
||||
|
||||
const char* buffer = TEST_STRING;
|
||||
DWORD bytesWritten;
|
||||
|
||||
WriteFile(hFile_, buffer, lstrlenA(buffer) * sizeof(char), &bytesWritten,
|
||||
nullptr);
|
||||
|
||||
CloseHandle(hFile_);
|
||||
}
|
||||
|
||||
// You can define per-test tear-down logic as usual.
|
||||
void TearDown() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
BOOL FileExists(const char* szPath) {
|
||||
DWORD dwAttrib = GetFileAttributesA(szPath);
|
||||
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE hFile_ = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulCreation) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
EXPECT_NE(inputFile, nullptr);
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulGetFilePath) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
std::string fileName;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
fileName = inputFile->GetFilePath();
|
||||
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
|
||||
EXPECT_EQ(fileName, test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulGetTotalSize) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
int64_t size = -1;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
size = inputFile->GetTotalSize();
|
||||
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
|
||||
EXPECT_EQ(size, strlen(TEST_STRING));
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, SuccessfulRead) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
auto fileSize = inputFile->GetTotalSize();
|
||||
auto dataRead = inputFile->Read(fileSize);
|
||||
|
||||
EXPECT_TRUE(dataRead.ok());
|
||||
EXPECT_EQ(inputFile->Close(),
|
||||
location::nearby::Exception{location::nearby::Exception::kSuccess});
|
||||
|
||||
EXPECT_STREQ(std::string(dataRead.result()).c_str(), TEST_STRING);
|
||||
}
|
||||
|
||||
TEST_F(InputFileTests, FailedRead) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::InputFile> inputFile = nullptr;
|
||||
|
||||
inputFile = location::nearby::api::ImplementationPlatform::CreateInputFile(
|
||||
payloadId, strlen(TEST_STRING));
|
||||
|
||||
auto fileSize = inputFile->GetTotalSize();
|
||||
EXPECT_NE(fileSize, -1);
|
||||
|
||||
auto dataRead = inputFile->Read(fileSize);
|
||||
EXPECT_TRUE(dataRead.ok());
|
||||
|
||||
dataRead = inputFile->Read(fileSize);
|
||||
std::string data = std::string(dataRead.result());
|
||||
|
||||
inputFile->Close();
|
||||
|
||||
EXPECT_STREQ(data.c_str(), "");
|
||||
}
|
||||
|
||||
@@ -1,109 +1,109 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/mutex.h"
|
||||
|
||||
#include <future> // NOLINT
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class MutexTests : public testing::Test {
|
||||
public:
|
||||
class MutexTest {
|
||||
public:
|
||||
MutexTest(location::nearby::windows::Mutex& mutex) : mutex_(mutex) {}
|
||||
|
||||
std::future<bool> WaitForLock() { // NOLINT
|
||||
return std::async(
|
||||
std::launch::async,
|
||||
// for this lambda you need C++14
|
||||
[this]() mutable {
|
||||
std::unique_lock<std::mutex> lck(mutex_.GetWindowsMutex());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void PostEvent() {
|
||||
std::lock_guard<std::mutex> guard(mutex_.GetWindowsMutex());
|
||||
mutex_.Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
location::nearby::windows::Mutex& mutex_;
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(MutexTests, SuccessfulRecursiveCreation) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex = location::nearby::windows::Mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRecursive);
|
||||
|
||||
// Act
|
||||
std::recursive_mutex& actual = mutex.GetWindowsRecursiveMutex();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(actual.native_handle() != nullptr);
|
||||
}
|
||||
|
||||
TEST_F(MutexTests, SuccessfulCreation) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRegular);
|
||||
|
||||
// Act
|
||||
std::mutex& actual = mutex.GetWindowsMutex();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(actual.native_handle() != nullptr);
|
||||
}
|
||||
|
||||
TEST_F(MutexTests, SuccessfulSignal) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRegular);
|
||||
|
||||
location::nearby::windows::Mutex& mutexRef = mutex;
|
||||
MutexTest mutexTest(mutexRef);
|
||||
|
||||
mutex.Lock();
|
||||
|
||||
// Act
|
||||
auto result = mutexTest.WaitForLock();
|
||||
mutex.Unlock();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get());
|
||||
}
|
||||
|
||||
TEST_F(MutexTests, SuccessfulRecursiveSignal) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRecursive);
|
||||
|
||||
location::nearby::windows::Mutex& mutexRef = mutex;
|
||||
MutexTest mutexTest(mutexRef);
|
||||
|
||||
mutex.Lock();
|
||||
mutex.Lock();
|
||||
mutex.Lock();
|
||||
|
||||
// Act
|
||||
auto result = mutexTest.WaitForLock();
|
||||
mutex.Unlock();
|
||||
mutex.Unlock();
|
||||
mutex.Unlock();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get());
|
||||
}
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/mutex.h"
|
||||
|
||||
#include <future> // NOLINT
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
class MutexTests : public testing::Test {
|
||||
public:
|
||||
class MutexTest {
|
||||
public:
|
||||
MutexTest(location::nearby::windows::Mutex& mutex) : mutex_(mutex) {}
|
||||
|
||||
std::future<bool> WaitForLock() { // NOLINT
|
||||
return std::async(
|
||||
std::launch::async,
|
||||
// for this lambda you need C++14
|
||||
[this]() mutable {
|
||||
std::unique_lock<std::mutex> lck(mutex_.GetWindowsMutex());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void PostEvent() {
|
||||
std::lock_guard<std::mutex> guard(mutex_.GetWindowsMutex());
|
||||
mutex_.Unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
location::nearby::windows::Mutex& mutex_;
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(MutexTests, SuccessfulRecursiveCreation) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex = location::nearby::windows::Mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRecursive);
|
||||
|
||||
// Act
|
||||
std::recursive_mutex& actual = mutex.GetWindowsRecursiveMutex();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(actual.native_handle() != nullptr);
|
||||
}
|
||||
|
||||
TEST_F(MutexTests, SuccessfulCreation) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRegular);
|
||||
|
||||
// Act
|
||||
std::mutex& actual = mutex.GetWindowsMutex();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(actual.native_handle() != nullptr);
|
||||
}
|
||||
|
||||
TEST_F(MutexTests, SuccessfulSignal) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRegular);
|
||||
|
||||
location::nearby::windows::Mutex& mutexRef = mutex;
|
||||
MutexTest mutexTest(mutexRef);
|
||||
|
||||
mutex.Lock();
|
||||
|
||||
// Act
|
||||
auto result = mutexTest.WaitForLock();
|
||||
mutex.Unlock();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get());
|
||||
}
|
||||
|
||||
TEST_F(MutexTests, SuccessfulRecursiveSignal) {
|
||||
// Arrange
|
||||
location::nearby::windows::Mutex mutex(
|
||||
location::nearby::windows::Mutex::Mode::kRecursive);
|
||||
|
||||
location::nearby::windows::Mutex& mutexRef = mutex;
|
||||
MutexTest mutexTest(mutexRef);
|
||||
|
||||
mutex.Lock();
|
||||
mutex.Lock();
|
||||
mutex.Lock();
|
||||
|
||||
// Act
|
||||
auto result = mutexTest.WaitForLock();
|
||||
mutex.Unlock();
|
||||
mutex.Unlock();
|
||||
mutex.Unlock();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(result.get());
|
||||
}
|
||||
|
||||
@@ -1,90 +1,90 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/output_file.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "platform/api/platform.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/base/payload_id.h"
|
||||
#include "platform/impl/windows/test_utils.h"
|
||||
|
||||
class OutputFileTests : public testing::Test {
|
||||
protected:
|
||||
// You can define per-test set-up logic as usual.
|
||||
void SetUp() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// You can define per-test tear-down logic as usual.
|
||||
void TearDown() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
BOOL FileExists(const char* szPath) {
|
||||
DWORD dwAttrib = GetFileAttributesA(szPath);
|
||||
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(OutputFileTests, SuccessfulCreation) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
outputFile =
|
||||
location::nearby::api::ImplementationPlatform::CreateOutputFile(
|
||||
payloadId));
|
||||
|
||||
EXPECT_NE(outputFile, nullptr);
|
||||
EXPECT_NO_THROW(outputFile->Close());
|
||||
}
|
||||
|
||||
TEST_F(OutputFileTests, SuccessfulClose) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
outputFile =
|
||||
location::nearby::api::ImplementationPlatform::CreateOutputFile(
|
||||
payloadId));
|
||||
|
||||
EXPECT_NO_THROW(outputFile->Close());
|
||||
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
|
||||
TEST_F(OutputFileTests, SuccessfulWrite) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
location::nearby::ByteArray data(std::string(TEST_STRING));
|
||||
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
outputFile =
|
||||
location::nearby::api::ImplementationPlatform::CreateOutputFile(
|
||||
payloadId));
|
||||
|
||||
EXPECT_NO_THROW(outputFile->Write(data));
|
||||
EXPECT_NO_THROW(outputFile->Close());
|
||||
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/output_file.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "platform/api/platform.h"
|
||||
#include "platform/base/exception.h"
|
||||
#include "platform/base/payload_id.h"
|
||||
#include "platform/impl/windows/test_utils.h"
|
||||
|
||||
class OutputFileTests : public testing::Test {
|
||||
protected:
|
||||
// You can define per-test set-up logic as usual.
|
||||
void SetUp() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// You can define per-test tear-down logic as usual.
|
||||
void TearDown() override {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
if (FileExists(test_utils::GetPayloadPath(payloadId).c_str())) {
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
BOOL FileExists(const char* szPath) {
|
||||
DWORD dwAttrib = GetFileAttributesA(szPath);
|
||||
|
||||
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||||
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(OutputFileTests, SuccessfulCreation) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
outputFile =
|
||||
location::nearby::api::ImplementationPlatform::CreateOutputFile(
|
||||
payloadId));
|
||||
|
||||
EXPECT_NE(outputFile, nullptr);
|
||||
EXPECT_NO_THROW(outputFile->Close());
|
||||
}
|
||||
|
||||
TEST_F(OutputFileTests, SuccessfulClose) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
outputFile =
|
||||
location::nearby::api::ImplementationPlatform::CreateOutputFile(
|
||||
payloadId));
|
||||
|
||||
EXPECT_NO_THROW(outputFile->Close());
|
||||
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
|
||||
TEST_F(OutputFileTests, SuccessfulWrite) {
|
||||
location::nearby::PayloadId payloadId(TEST_PAYLOAD_ID);
|
||||
location::nearby::ByteArray data(std::string(TEST_STRING));
|
||||
std::unique_ptr<location::nearby::api::OutputFile> outputFile = nullptr;
|
||||
|
||||
EXPECT_NO_THROW(
|
||||
outputFile =
|
||||
location::nearby::api::ImplementationPlatform::CreateOutputFile(
|
||||
payloadId));
|
||||
|
||||
EXPECT_NO_THROW(outputFile->Write(data));
|
||||
EXPECT_NO_THROW(outputFile->Close());
|
||||
|
||||
DeleteFileA(test_utils::GetPayloadPath(payloadId).c_str());
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_RUNNER_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_RUNNER_H_
|
||||
|
||||
#include "platform/base/runnable.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
class ThreadPool;
|
||||
|
||||
class Runner {
|
||||
public:
|
||||
Runner(std::function<void()> runnable)
|
||||
: thread_pool_(nullptr), runnable_(runnable) {}
|
||||
void Run() { runnable_(); }
|
||||
~Runner(){}
|
||||
ThreadPool* thread_pool_;
|
||||
|
||||
private:
|
||||
std::function<void()> runnable_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_RUNNER_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_RUNNER_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_RUNNER_H_
|
||||
|
||||
#include "platform/base/runnable.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
class ThreadPool;
|
||||
|
||||
class Runner {
|
||||
public:
|
||||
Runner(std::function<void()> runnable)
|
||||
: thread_pool_(nullptr), runnable_(runnable) {}
|
||||
void Run() { runnable_(); }
|
||||
~Runner(){}
|
||||
ThreadPool* thread_pool_;
|
||||
|
||||
private:
|
||||
std::function<void()> runnable_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_RUNNER_H_
|
||||
|
||||
@@ -1,174 +1,174 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "platform/impl/windows/scheduled_executor.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "platform/impl/windows/test_data.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(ScheduledExecutorTests, ExecuteSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
submittableExecutor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, ScheduleSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
std::chrono::system_clock::time_point timeNow =
|
||||
std::chrono::system_clock::now();
|
||||
std::chrono::system_clock::time_point timeExecuted;
|
||||
|
||||
// Act
|
||||
submittableExecutor->Schedule(
|
||||
[&output, &threadIds, &timeExecuted]() {
|
||||
timeExecuted = std::chrono::system_clock::now();
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
},
|
||||
absl::Milliseconds(50));
|
||||
|
||||
SleepEx(100, true); // Yield the thread
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
auto difference = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
timeExecuted - timeNow)
|
||||
.count();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_TRUE(difference >= 50) << "difference was: " << difference;
|
||||
ASSERT_TRUE(difference < 100) << "difference was: " << difference;
|
||||
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, CancelSucceeds) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
auto cancelable = submittableExecutor->Schedule(
|
||||
[&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
},
|
||||
absl::Milliseconds(1000));
|
||||
|
||||
SleepEx(100, true); // Yield the thread
|
||||
|
||||
auto actual = cancelable->Cancel();
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(actual);
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, CancelAfterStartedFails) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
auto cancelable = submittableExecutor->Schedule(
|
||||
[&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
},
|
||||
absl::Milliseconds(100));
|
||||
|
||||
SleepEx(1000, true); // Yield the thread
|
||||
|
||||
auto actual = cancelable->Cancel();
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
ASSERT_FALSE(actual);
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "platform/impl/windows/scheduled_executor.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "platform/impl/windows/test_data.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(ScheduledExecutorTests, ExecuteSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
submittableExecutor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, ScheduleSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
std::chrono::system_clock::time_point timeNow =
|
||||
std::chrono::system_clock::now();
|
||||
std::chrono::system_clock::time_point timeExecuted;
|
||||
|
||||
// Act
|
||||
submittableExecutor->Schedule(
|
||||
[&output, &threadIds, &timeExecuted]() {
|
||||
timeExecuted = std::chrono::system_clock::now();
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
},
|
||||
absl::Milliseconds(50));
|
||||
|
||||
SleepEx(100, true); // Yield the thread
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
auto difference = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
timeExecuted - timeNow)
|
||||
.count();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_TRUE(difference >= 50) << "difference was: " << difference;
|
||||
ASSERT_TRUE(difference < 100) << "difference was: " << difference;
|
||||
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, CancelSucceeds) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
auto cancelable = submittableExecutor->Schedule(
|
||||
[&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
},
|
||||
absl::Milliseconds(1000));
|
||||
|
||||
SleepEx(100, true); // Yield the thread
|
||||
|
||||
auto actual = cancelable->Cancel();
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
ASSERT_TRUE(actual);
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(ScheduledExecutorTests, CancelAfterStartedFails) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::ScheduledExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::ScheduledExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
auto cancelable = submittableExecutor->Schedule(
|
||||
[&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
},
|
||||
absl::Milliseconds(100));
|
||||
|
||||
SleepEx(1000, true); // Yield the thread
|
||||
|
||||
auto actual = cancelable->Cancel();
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
ASSERT_FALSE(actual);
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/submittable_executor.h"
|
||||
|
||||
#include "platform/impl/windows/executor.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
SubmittableExecutor::SubmittableExecutor() : SubmittableExecutor(1) {}
|
||||
|
||||
SubmittableExecutor::SubmittableExecutor(int32_t max_concurrancy)
|
||||
: executor_(std::make_unique<nearby::windows::Executor>(max_concurrancy)),
|
||||
shut_down_(false) {}
|
||||
|
||||
bool SubmittableExecutor::DoSubmit(Runnable&& wrapped_callable) {
|
||||
if (!shut_down_) {
|
||||
executor_->Execute(std::move(wrapped_callable));
|
||||
return true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << "Error: " << __func__
|
||||
<< ": Attempt to DoSubmit on a shutdown executor.";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-
|
||||
void SubmittableExecutor::Execute(Runnable&& runnable) {
|
||||
if (!shut_down_) {
|
||||
executor_->Execute(std::move(runnable));
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR) << "Error: " << __func__
|
||||
<< ": Attempt to Execute on a shutdown executor.";
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--
|
||||
void SubmittableExecutor::Shutdown() {
|
||||
if (!shut_down_) {
|
||||
executor_->Shutdown();
|
||||
shut_down_ = true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << "Error: " << __func__
|
||||
<< ": Attempt to Shutdown on a shutdown executor.";
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/submittable_executor.h"
|
||||
|
||||
#include "platform/impl/windows/executor.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
SubmittableExecutor::SubmittableExecutor() : SubmittableExecutor(1) {}
|
||||
|
||||
SubmittableExecutor::SubmittableExecutor(int32_t max_concurrancy)
|
||||
: executor_(std::make_unique<nearby::windows::Executor>(max_concurrancy)),
|
||||
shut_down_(false) {}
|
||||
|
||||
bool SubmittableExecutor::DoSubmit(Runnable&& wrapped_callable) {
|
||||
if (!shut_down_) {
|
||||
executor_->Execute(std::move(wrapped_callable));
|
||||
return true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << "Error: " << __func__
|
||||
<< ": Attempt to DoSubmit on a shutdown executor.";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html#execute-java.lang.Runnable-
|
||||
void SubmittableExecutor::Execute(Runnable&& runnable) {
|
||||
if (!shut_down_) {
|
||||
executor_->Execute(std::move(runnable));
|
||||
} else {
|
||||
NEARBY_LOGS(ERROR) << "Error: " << __func__
|
||||
<< ": Attempt to Execute on a shutdown executor.";
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown--
|
||||
void SubmittableExecutor::Shutdown() {
|
||||
if (!shut_down_) {
|
||||
executor_->Shutdown();
|
||||
shut_down_ = true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << "Error: " << __func__
|
||||
<< ": Attempt to Shutdown on a shutdown executor.";
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -1,240 +1,240 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "platform/impl/windows/submittable_executor.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "platform/impl/windows/test_data.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedExecuteSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
submittableExecutor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedExecuteAfterShutdownFails) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Act
|
||||
submittableExecutor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 0 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedDoSubmitSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
auto result = submittableExecutor->DoSubmit([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've said we were going to run this one
|
||||
ASSERT_TRUE(result);
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests,
|
||||
SingleThreadedDoSubmitAfterShutdownReturnsFalse) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Act
|
||||
auto result = submittableExecutor->DoSubmit([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've said we were going to run this one
|
||||
ASSERT_FALSE(result);
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedExecuteMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_ALL_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 5; index++) {
|
||||
submittableExecutor->Execute([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output->append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
auto workerThreadId = threadIds->at(1);
|
||||
for (int index = 1; index < threadIds->size(); index++) {
|
||||
ASSERT_EQ(threadIds->at(index), workerThreadId);
|
||||
}
|
||||
|
||||
// We should of run them in the order submitted
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedDoSubmitMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_ALL_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
bool result = true;
|
||||
for (int index = 0; index < 5; index++) {
|
||||
result &= submittableExecutor->DoSubmit([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output->append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// All of these should have submitted
|
||||
ASSERT_TRUE(result);
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
auto workerThreadId = threadIds->at(1);
|
||||
for (int index = 1; index < threadIds->size(); index++) {
|
||||
ASSERT_EQ(threadIds->at(index), workerThreadId);
|
||||
}
|
||||
|
||||
// We should of run them in the order submitted
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "platform/impl/windows/submittable_executor.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "platform/impl/windows/test_data.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedExecuteSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
submittableExecutor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedExecuteAfterShutdownFails) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Act
|
||||
submittableExecutor->Execute([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 0 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedDoSubmitSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_0_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::string output = std::string();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
auto result = submittableExecutor->DoSubmit([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output.append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've said we were going to run this one
|
||||
ASSERT_TRUE(result);
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 2);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(output, expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests,
|
||||
SingleThreadedDoSubmitAfterShutdownReturnsFalse) {
|
||||
// Arrange
|
||||
std::string expected("");
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Act
|
||||
auto result = submittableExecutor->DoSubmit([&output, &threadIds]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
output->append(RUNNABLE_0_TEXT.c_str());
|
||||
});
|
||||
|
||||
// Assert
|
||||
// We should've said we were going to run this one
|
||||
ASSERT_FALSE(result);
|
||||
// We should've run 1 time on the main thread, and 1 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 1);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedExecuteMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_ALL_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
for (int index = 0; index < 5; index++) {
|
||||
submittableExecutor->Execute([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output->append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
auto workerThreadId = threadIds->at(1);
|
||||
for (int index = 1; index < threadIds->size(); index++) {
|
||||
ASSERT_EQ(threadIds->at(index), workerThreadId);
|
||||
}
|
||||
|
||||
// We should of run them in the order submitted
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
TEST(SubmittableExecutorTests, SingleThreadedDoSubmitMultipleTasksSucceeds) {
|
||||
// Arrange
|
||||
std::string expected(RUNNABLE_ALL_TEXT.c_str());
|
||||
|
||||
std::unique_ptr<location::nearby::windows::SubmittableExecutor>
|
||||
submittableExecutor =
|
||||
std::make_unique<location::nearby::windows::SubmittableExecutor>();
|
||||
std::unique_ptr<std::string> output = std::make_unique<std::string>();
|
||||
// Container to note threads that ran
|
||||
std::unique_ptr<std::vector<DWORD>> threadIds =
|
||||
std::make_unique<std::vector<DWORD>>();
|
||||
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
|
||||
// Act
|
||||
bool result = true;
|
||||
for (int index = 0; index < 5; index++) {
|
||||
result &= submittableExecutor->DoSubmit([&output, &threadIds, index]() {
|
||||
threadIds->push_back(GetCurrentThreadId());
|
||||
char buffer[128];
|
||||
snprintf(buffer, sizeof(buffer), "%s%d, ", RUNNABLE_TEXT.c_str(), index);
|
||||
output->append(std::string(buffer));
|
||||
});
|
||||
}
|
||||
|
||||
submittableExecutor->Shutdown();
|
||||
|
||||
// Assert
|
||||
// All of these should have submitted
|
||||
ASSERT_TRUE(result);
|
||||
// We should've run 1 time on the main thread, and 5 times on the
|
||||
// workerThread
|
||||
ASSERT_EQ(threadIds->size(), 6);
|
||||
// We should still be on the main thread
|
||||
ASSERT_EQ(GetCurrentThreadId(), threadIds->at(0));
|
||||
// We should've run all runnables on the worker thread
|
||||
auto workerThreadId = threadIds->at(1);
|
||||
for (int index = 1; index < threadIds->size(); index++) {
|
||||
ASSERT_EQ(threadIds->at(index), workerThreadId);
|
||||
}
|
||||
|
||||
// We should of run them in the order submitted
|
||||
ASSERT_EQ(*output.get(), expected);
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_TEST_DATA_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_TEST_DATA_H_
|
||||
|
||||
#define INVALID_ARGUMENT_TEXT "max_concurrency"
|
||||
#define THREADPOOL_MAX_SIZE_TEXT "Thread pool max size exceeded."
|
||||
#define RUNNABLE_TEXT std::string("runnable ")
|
||||
#define RUNNABLE_0_TEXT RUNNABLE_TEXT + std::string("0")
|
||||
#define RUNNABLE_1_TEXT RUNNABLE_TEXT + std::string("1")
|
||||
#define RUNNABLE_2_TEXT RUNNABLE_TEXT + std::string("2")
|
||||
#define RUNNABLE_3_TEXT RUNNABLE_TEXT + std::string("3")
|
||||
#define RUNNABLE_4_TEXT RUNNABLE_TEXT + std::string("4")
|
||||
#define RUNNABLE_SEPARATOR_TEXT std::string(", ")
|
||||
#define RUNNABLE_ALL_TEXT \
|
||||
(RUNNABLE_0_TEXT + RUNNABLE_SEPARATOR_TEXT + RUNNABLE_1_TEXT + \
|
||||
RUNNABLE_SEPARATOR_TEXT + RUNNABLE_2_TEXT + RUNNABLE_SEPARATOR_TEXT + \
|
||||
RUNNABLE_3_TEXT + RUNNABLE_SEPARATOR_TEXT + RUNNABLE_4_TEXT + \
|
||||
RUNNABLE_SEPARATOR_TEXT)
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_TEST_DATA_H_
|
||||
|
||||
// Copyright 2021 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_TEST_DATA_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_TEST_DATA_H_
|
||||
|
||||
#define INVALID_ARGUMENT_TEXT "max_concurrency"
|
||||
#define THREADPOOL_MAX_SIZE_TEXT "Thread pool max size exceeded."
|
||||
#define RUNNABLE_TEXT std::string("runnable ")
|
||||
#define RUNNABLE_0_TEXT RUNNABLE_TEXT + std::string("0")
|
||||
#define RUNNABLE_1_TEXT RUNNABLE_TEXT + std::string("1")
|
||||
#define RUNNABLE_2_TEXT RUNNABLE_TEXT + std::string("2")
|
||||
#define RUNNABLE_3_TEXT RUNNABLE_TEXT + std::string("3")
|
||||
#define RUNNABLE_4_TEXT RUNNABLE_TEXT + std::string("4")
|
||||
#define RUNNABLE_SEPARATOR_TEXT std::string(", ")
|
||||
#define RUNNABLE_ALL_TEXT \
|
||||
(RUNNABLE_0_TEXT + RUNNABLE_SEPARATOR_TEXT + RUNNABLE_1_TEXT + \
|
||||
RUNNABLE_SEPARATOR_TEXT + RUNNABLE_2_TEXT + RUNNABLE_SEPARATOR_TEXT + \
|
||||
RUNNABLE_3_TEXT + RUNNABLE_SEPARATOR_TEXT + RUNNABLE_4_TEXT + \
|
||||
RUNNABLE_SEPARATOR_TEXT)
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_TEST_DATA_H_
|
||||
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/test_utils.h"
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
namespace test_utils {
|
||||
std::wstring StringToWideString(const std::string& s) {
|
||||
int len;
|
||||
int slength = (int)s.length() + 1;
|
||||
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
|
||||
wchar_t* buf = new wchar_t[len];
|
||||
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
|
||||
std::wstring r(buf);
|
||||
delete[] buf;
|
||||
return r;
|
||||
}
|
||||
|
||||
std::string GetPayloadPath(location::nearby::PayloadId payload_id) {
|
||||
PWSTR basePath;
|
||||
|
||||
// Retrieves the full path of a known folder identified by the folder's
|
||||
// KNOWNFOLDERID.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
|
||||
SHGetKnownFolderPath(
|
||||
FOLDERID_Downloads, // rfid: A reference to the KNOWNFOLDERID that
|
||||
// identifies the folder.
|
||||
0, // dwFlags: Flags that specify special retrieval options.
|
||||
NULL, // hToken: An access token that represents a particular user.
|
||||
&basePath); // ppszPath: When this method returns, contains the address
|
||||
// of a pointer to a null-terminated Unicode string that
|
||||
// specifies the path of the known folder. The calling
|
||||
// process is responsible for freeing this resource once it
|
||||
// is no longer needed by calling CoTaskMemFree, whether
|
||||
// SHGetKnownFolderPath succeeds or not.
|
||||
|
||||
char* fullpathUTF8 = new char((wcslen(basePath) + 1) * sizeof(char));
|
||||
wcstombs(fullpathUTF8, basePath, (wcslen(basePath) + 1) * sizeof(char));
|
||||
std::string fullPath = std::string(fullpathUTF8);
|
||||
auto retval = absl::StrCat(fullPath += "/", payload_id);
|
||||
return retval;
|
||||
}
|
||||
} // namespace test_utils
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/test_utils.h"
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
namespace test_utils {
|
||||
std::wstring StringToWideString(const std::string& s) {
|
||||
int len;
|
||||
int slength = (int)s.length() + 1;
|
||||
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
|
||||
wchar_t* buf = new wchar_t[len];
|
||||
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
|
||||
std::wstring r(buf);
|
||||
delete[] buf;
|
||||
return r;
|
||||
}
|
||||
|
||||
std::string GetPayloadPath(location::nearby::PayloadId payload_id) {
|
||||
PWSTR basePath;
|
||||
|
||||
// Retrieves the full path of a known folder identified by the folder's
|
||||
// KNOWNFOLDERID.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
|
||||
SHGetKnownFolderPath(
|
||||
FOLDERID_Downloads, // rfid: A reference to the KNOWNFOLDERID that
|
||||
// identifies the folder.
|
||||
0, // dwFlags: Flags that specify special retrieval options.
|
||||
NULL, // hToken: An access token that represents a particular user.
|
||||
&basePath); // ppszPath: When this method returns, contains the address
|
||||
// of a pointer to a null-terminated Unicode string that
|
||||
// specifies the path of the known folder. The calling
|
||||
// process is responsible for freeing this resource once it
|
||||
// is no longer needed by calling CoTaskMemFree, whether
|
||||
// SHGetKnownFolderPath succeeds or not.
|
||||
|
||||
char* fullpathUTF8 = new char((wcslen(basePath) + 1) * sizeof(char));
|
||||
wcstombs(fullpathUTF8, basePath, (wcslen(basePath) + 1) * sizeof(char));
|
||||
std::string fullPath = std::string(fullpathUTF8);
|
||||
auto retval = absl::StrCat(fullPath += "/", payload_id);
|
||||
return retval;
|
||||
}
|
||||
} // namespace test_utils
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <xstring>
|
||||
|
||||
#include "platform/base/payload_id.h"
|
||||
|
||||
#define TEST_BUFFER_SIZE 256
|
||||
#define TEST_PAYLOAD_ID 64l
|
||||
#define TEST_STRING \
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas " \
|
||||
"eleifend nisl at magna maximus, id finibus mauris ultrices. Mauris " \
|
||||
"interdum efficitur turpis eget auctor. Nullam commodo metus et ante " \
|
||||
"bibendum molestie. Donec iaculis ante nec diam rutrum egestas. Proin " \
|
||||
"maximus metus luctus rutrum congue. Integer et eros nunc. Etiam purus " \
|
||||
"neque, tincidunt eu elementum in, pharetra sit amet magna. Quisque " \
|
||||
"consequat aliquam aliquam. Vestibulum ante ipsum primis in faucibus orci " \
|
||||
"luctus et ultrices posuere cubilia curae; Maecenas a semper eros, a " \
|
||||
"auctor mi. In luctus diam sem, eu pretium nisi porttitor ac. Sed cursus, " \
|
||||
"arcu in bibendum feugiat, leo erat finibus massa, ut tincidunt magna nunc " \
|
||||
"eu tellus. Cras feugiat ornare vestibulum. Nullam at ipsum vestibulum " \
|
||||
"sapien luctus dictum ac vel ligula."
|
||||
|
||||
namespace test_utils {
|
||||
std::wstring StringToWideString(const std::string& s);
|
||||
std::string GetPayloadPath(location::nearby::PayloadId payload_id);
|
||||
} // namespace test_utils
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <xstring>
|
||||
|
||||
#include "platform/base/payload_id.h"
|
||||
|
||||
#define TEST_BUFFER_SIZE 256
|
||||
#define TEST_PAYLOAD_ID 64l
|
||||
#define TEST_STRING \
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas " \
|
||||
"eleifend nisl at magna maximus, id finibus mauris ultrices. Mauris " \
|
||||
"interdum efficitur turpis eget auctor. Nullam commodo metus et ante " \
|
||||
"bibendum molestie. Donec iaculis ante nec diam rutrum egestas. Proin " \
|
||||
"maximus metus luctus rutrum congue. Integer et eros nunc. Etiam purus " \
|
||||
"neque, tincidunt eu elementum in, pharetra sit amet magna. Quisque " \
|
||||
"consequat aliquam aliquam. Vestibulum ante ipsum primis in faucibus orci " \
|
||||
"luctus et ultrices posuere cubilia curae; Maecenas a semper eros, a " \
|
||||
"auctor mi. In luctus diam sem, eu pretium nisi porttitor ac. Sed cursus, " \
|
||||
"arcu in bibendum feugiat, leo erat finibus massa, ut tincidunt magna nunc " \
|
||||
"eu tellus. Cras feugiat ornare vestibulum. Nullam at ipsum vestibulum " \
|
||||
"sapien luctus dictum ac vel ligula."
|
||||
|
||||
namespace test_utils {
|
||||
std::wstring StringToWideString(const std::string& s);
|
||||
std::string GetPayloadPath(location::nearby::PayloadId payload_id);
|
||||
} // namespace test_utils
|
||||
|
||||
#endif // PLATFORM_IMPL_WINDOWS_TEST_UTILS_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,106 +1,106 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_THREAD_POOL_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_THREAD_POOL_H_
|
||||
#include <windows.h>
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "platform/impl/windows/runner.h"
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// This is the number of threads that will be started initially if the pool
|
||||
// size is greater than 4, or if the pool size is greater than the number
|
||||
// of cores present, including virtual cores
|
||||
#define STARTUP_THREAD_COUNT 4
|
||||
|
||||
class ThreadPoolException : public std::runtime_error {
|
||||
public:
|
||||
ThreadPoolException() : std::runtime_error("") {}
|
||||
ThreadPoolException(const std::string& message)
|
||||
: std::runtime_error(message), message_(message) {}
|
||||
virtual const char* what() const throw() {
|
||||
return message_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string message_;
|
||||
};
|
||||
|
||||
// all functions passed in by clients will be initially stored in this list.
|
||||
typedef std::list<std::unique_ptr<Runner>> FunctionList;
|
||||
// info about threads in the pool will be saved using this struct.
|
||||
typedef struct tagThreadData {
|
||||
bool free;
|
||||
HANDLE wait_handle;
|
||||
HANDLE thread_handle;
|
||||
DWORD thread_id;
|
||||
} ThreadData;
|
||||
// info about all threads belonging to this pool will be stored in this map
|
||||
typedef std::map<DWORD, std::unique_ptr<ThreadData>>
|
||||
ThreadMap;
|
||||
enum class State {
|
||||
Ready, // has been created
|
||||
Destroying, // in the process of getting destroyed, no request is processed /
|
||||
// accepted
|
||||
Destroyed // Destroyed, no threads are available, request can still be queued
|
||||
};
|
||||
class ThreadPool {
|
||||
public:
|
||||
ThreadPool(int nPoolSize, bool bCreateNow);
|
||||
virtual ~ThreadPool();
|
||||
bool Create(); // creates the thread pool
|
||||
void Destroy(); // destroy the thread pool
|
||||
int GetPoolSize();
|
||||
void SetPoolSize(int);
|
||||
bool Run(std::unique_ptr<Runner> runObject);
|
||||
bool CheckThreadStop();
|
||||
int GetWorkingThreadCount();
|
||||
State GetState();
|
||||
|
||||
private:
|
||||
static DWORD WINAPI _ThreadProc(LPVOID);
|
||||
std::unique_ptr<FunctionList> function_list_;
|
||||
std::unique_ptr<ThreadMap> thread_map_;
|
||||
HANDLE* thread_handles_ = nullptr;
|
||||
int pool_size_;
|
||||
int wait_for_threads_to_die_ms_; // In milli-seconds
|
||||
std::string pool_name_; // To assist in logging and debug
|
||||
HANDLE notify_shutdown_; // notifies threads that a new function
|
||||
// is added
|
||||
volatile State pool_state_;
|
||||
static __declspec(
|
||||
align(8)) volatile long instance_; // NOLINT Windows function takes
|
||||
// volatile long
|
||||
CRITICAL_SECTION critical_section_;
|
||||
|
||||
bool GetThreadProc(DWORD dwThreadId, std::unique_ptr<Runner>&& runner);
|
||||
void FinishNotify(DWORD dwThreadId);
|
||||
void BusyNotify(DWORD dwThreadId);
|
||||
void ReleaseMemory();
|
||||
HANDLE GetWaitHandle(DWORD dwThreadId);
|
||||
HANDLE GetShutdownHandle();
|
||||
void AddRunner(std::unique_ptr<Runner> runner);
|
||||
DWORD CreateThreadPoolThread(HANDLE* handles);
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
#endif // PLATFORM_IMPL_WINDOWS_THREAD_POOL_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_THREAD_POOL_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_THREAD_POOL_H_
|
||||
#include <windows.h>
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "platform/impl/windows/runner.h"
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// This is the number of threads that will be started initially if the pool
|
||||
// size is greater than 4, or if the pool size is greater than the number
|
||||
// of cores present, including virtual cores
|
||||
#define STARTUP_THREAD_COUNT 4
|
||||
|
||||
class ThreadPoolException : public std::runtime_error {
|
||||
public:
|
||||
ThreadPoolException() : std::runtime_error("") {}
|
||||
ThreadPoolException(const std::string& message)
|
||||
: std::runtime_error(message), message_(message) {}
|
||||
virtual const char* what() const throw() {
|
||||
return message_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string message_;
|
||||
};
|
||||
|
||||
// all functions passed in by clients will be initially stored in this list.
|
||||
typedef std::list<std::unique_ptr<Runner>> FunctionList;
|
||||
// info about threads in the pool will be saved using this struct.
|
||||
typedef struct tagThreadData {
|
||||
bool free;
|
||||
HANDLE wait_handle;
|
||||
HANDLE thread_handle;
|
||||
DWORD thread_id;
|
||||
} ThreadData;
|
||||
// info about all threads belonging to this pool will be stored in this map
|
||||
typedef std::map<DWORD, std::unique_ptr<ThreadData>>
|
||||
ThreadMap;
|
||||
enum class State {
|
||||
Ready, // has been created
|
||||
Destroying, // in the process of getting destroyed, no request is processed /
|
||||
// accepted
|
||||
Destroyed // Destroyed, no threads are available, request can still be queued
|
||||
};
|
||||
class ThreadPool {
|
||||
public:
|
||||
ThreadPool(int nPoolSize, bool bCreateNow);
|
||||
virtual ~ThreadPool();
|
||||
bool Create(); // creates the thread pool
|
||||
void Destroy(); // destroy the thread pool
|
||||
int GetPoolSize();
|
||||
void SetPoolSize(int);
|
||||
bool Run(std::unique_ptr<Runner> runObject);
|
||||
bool CheckThreadStop();
|
||||
int GetWorkingThreadCount();
|
||||
State GetState();
|
||||
|
||||
private:
|
||||
static DWORD WINAPI _ThreadProc(LPVOID);
|
||||
std::unique_ptr<FunctionList> function_list_;
|
||||
std::unique_ptr<ThreadMap> thread_map_;
|
||||
HANDLE* thread_handles_ = nullptr;
|
||||
int pool_size_;
|
||||
int wait_for_threads_to_die_ms_; // In milli-seconds
|
||||
std::string pool_name_; // To assist in logging and debug
|
||||
HANDLE notify_shutdown_; // notifies threads that a new function
|
||||
// is added
|
||||
volatile State pool_state_;
|
||||
static __declspec(
|
||||
align(8)) volatile long instance_; // NOLINT Windows function takes
|
||||
// volatile long
|
||||
CRITICAL_SECTION critical_section_;
|
||||
|
||||
bool GetThreadProc(DWORD dwThreadId, std::unique_ptr<Runner>&& runner);
|
||||
void FinishNotify(DWORD dwThreadId);
|
||||
void BusyNotify(DWORD dwThreadId);
|
||||
void ReleaseMemory();
|
||||
HANDLE GetWaitHandle(DWORD dwThreadId);
|
||||
HANDLE GetShutdownHandle();
|
||||
void AddRunner(std::unique_ptr<Runner> runner);
|
||||
DWORD CreateThreadPoolThread(HANDLE* handles);
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
#endif // PLATFORM_IMPL_WINDOWS_THREAD_POOL_H_
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/utils.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using location::nearby::windows::uint64_to_mac_address_string;
|
||||
|
||||
TEST(UtilsTests, MacAddressToString) {
|
||||
// Arrange
|
||||
const uint64_t input = 0x000034363bc78c71;
|
||||
std::string expected = "34:36:3B:C7:8C:71";
|
||||
|
||||
// Act
|
||||
std::string result = uint64_to_mac_address_string(input);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "platform/impl/windows/utils.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using location::nearby::windows::uint64_to_mac_address_string;
|
||||
|
||||
TEST(UtilsTests, MacAddressToString) {
|
||||
// Arrange
|
||||
const uint64_t input = 0x000034363bc78c71;
|
||||
std::string expected = "34:36:3B:C7:8C:71";
|
||||
|
||||
// Act
|
||||
std::string result = uint64_to_mac_address_string(input);
|
||||
|
||||
// Assert
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef CORE_CONFIG_H_
|
||||
#define CORE_CONFIG_H_
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
#ifdef _WIN32 // These storage class specifiers only matter to win32 dll
|
||||
// builds.
|
||||
#ifdef CORE_ADAPTER_DLL
|
||||
#define DLL_API \
|
||||
__declspec(dllexport) // If we're building the core, we're exporting.
|
||||
#else // !CORE_ADAPTER_DLL
|
||||
#define DLL_API \
|
||||
__declspec(dllimport) // If we're not building the core, we're importing.
|
||||
#endif // CORE_ADAPTER_DLL
|
||||
#else // !_WIN32
|
||||
#define DLL_API // We're not building a win32 dll, leave the source unchanged.
|
||||
#endif // _WIN32
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // CORE_CONFIG_H_
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef CORE_CONFIG_H_
|
||||
#define CORE_CONFIG_H_
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
|
||||
#ifdef _WIN32 // These storage class specifiers only matter to win32 dll
|
||||
// builds.
|
||||
#ifdef CORE_ADAPTER_DLL
|
||||
#define DLL_API \
|
||||
__declspec(dllexport) // If we're building the core, we're exporting.
|
||||
#else // !CORE_ADAPTER_DLL
|
||||
#define DLL_API \
|
||||
__declspec(dllimport) // If we're not building the core, we're importing.
|
||||
#endif // CORE_ADAPTER_DLL
|
||||
#else // !_WIN32
|
||||
#define DLL_API // We're not building a win32 dll, leave the source unchanged.
|
||||
#endif // _WIN32
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // CORE_CONFIG_H_
|
||||
|
||||
Reference in New Issue
Block a user