Patch recent cls from nearby_connections;

Sync github to replace nearby_connections with nearby.

PiperOrigin-RevId: 411609608
This commit is contained in:
hais
2021-11-22 11:38:39 -08:00
committed by Copybara-Service
parent b829cd62c4
commit a192cd3e32
93 changed files with 4596 additions and 4598 deletions
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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",
+5 -5
View File
@@ -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",
],
)
+3 -3
View File
@@ -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 {
+2 -2
View File
@@ -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 {
+3 -3
View File
@@ -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
View File
@@ -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",
+34 -34
View File
@@ -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",
],
)
+20 -20
View File
@@ -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
View File
@@ -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_
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -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
}
+186 -186
View File
@@ -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);
}
+348 -348
View File
@@ -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);
}
+1 -1
View File
@@ -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__",
],
)
+152 -152
View File
@@ -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(), "");
}
+109 -109
View File
@@ -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());
}
+90 -90
View File
@@ -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());
}
+42 -42
View File
@@ -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);
}
+34 -34
View File
@@ -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_
+57 -57
View File
@@ -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
+47 -47
View File
@@ -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
+106 -106
View File
@@ -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_
+31 -31
View File
@@ -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);
}
+38 -38
View File
@@ -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_