mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
No changes to public files
PiperOrigin-RevId: 392585608
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
licenses(["notice"])
|
||||
# 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.
|
||||
|
||||
cc_library(
|
||||
name = "analytics",
|
||||
srcs = [
|
||||
"analytics_recorder.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"analytics_recorder.h",
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//core:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//absl/container:btree",
|
||||
"//absl/time",
|
||||
"//core:core_types",
|
||||
"//core:event_logger",
|
||||
"//platform/base",
|
||||
"//platform/public:logging",
|
||||
"//platform/public:types",
|
||||
"//proto:connections_enums_portable_proto",
|
||||
"//third_party/nearby_connections/proto/analytics:connections_log_cc_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "analytics_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"analytics_recorder_test.cc",
|
||||
],
|
||||
shard_count = 16,
|
||||
deps = [
|
||||
":analytics",
|
||||
"//testing/base/public:gunit_main",
|
||||
"//absl/time",
|
||||
"//platform/impl/g3", # build_cleaner: keep
|
||||
"//platform/public:logging",
|
||||
"//platform/public:types",
|
||||
"//proto:connections_enums_portable_proto",
|
||||
"//third_party/nearby_connections/proto/analytics:connections_log_cc_proto",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,493 @@
|
||||
// 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 "third_party/nearby_connections/cpp/analytics/analytics_recorder.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/time/time.h"
|
||||
#include "platform/public/logging.h"
|
||||
#include "platform/public/mutex_lock.h"
|
||||
#include "platform/public/system_clock.h"
|
||||
#include "proto/analytics/connections_log.proto.h"
|
||||
#include "proto/connections_enums.proto.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
|
||||
using ConnectionsLog = ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ClientSession = ConnectionsLog::ClientSession;
|
||||
using StrategySession = ConnectionsLog::StrategySession;
|
||||
using AdvertisingPhase = ConnectionsLog::AdvertisingPhase;
|
||||
using DiscoveryPhase = ConnectionsLog::DiscoveryPhase;
|
||||
using DiscoveredEndpoint = ConnectionsLog::DiscoveredEndpoint;
|
||||
using ConnectionRequest = ConnectionsLog::ConnectionRequest;
|
||||
using ConnectionRequestResponse =
|
||||
::location::nearby::proto::connections::ConnectionRequestResponse;
|
||||
using ConnectionStrategy =
|
||||
::location::nearby::proto::connections::ConnectionsStrategy;
|
||||
using EventType = ::location::nearby::proto::connections::EventType;
|
||||
using Medium = ::location::nearby::proto::connections::Medium;
|
||||
using SessionRole = ::location::nearby::proto::connections::SessionRole;
|
||||
|
||||
// These definitions are necessary before C++17.
|
||||
constexpr absl::string_view AnalyticsRecorder::kVersion;
|
||||
|
||||
AnalyticsRecorder::AnalyticsRecorder(EventLogger *event_logger)
|
||||
: event_logger_(event_logger) {
|
||||
started_client_session_time_ = SystemClock::ElapsedRealtime();
|
||||
NEARBY_LOGS(INFO) << "AnalyticsRecorder ctor event_logger_=" << event_logger_;
|
||||
MutexLock lock(&mutex_);
|
||||
if (CanRecordAnalyticsLocked("OnStartClientSession")) {
|
||||
LogEvent(::location::nearby::proto::connections::START_CLIENT_SESSION);
|
||||
}
|
||||
}
|
||||
|
||||
AnalyticsRecorder::~AnalyticsRecorder() {
|
||||
MutexLock lock(&mutex_);
|
||||
incoming_connection_requests_.clear();
|
||||
outgoing_connection_requests_.clear();
|
||||
serial_executor_.Shutdown();
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnStartAdvertising(connections::Strategy strategy,
|
||||
const std::vector<Medium> &mediums) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnStartAdvertising")) {
|
||||
return;
|
||||
}
|
||||
if (!strategy.IsValid()) {
|
||||
NEARBY_LOGS(INFO) << "AnalyticsRecorder OnStartAdvertising with unknown "
|
||||
"strategy, bail out.";
|
||||
return;
|
||||
}
|
||||
// Initialize/update a StrategySession.
|
||||
UpdateStrategySessionLocked(
|
||||
strategy, ::location::nearby::proto::connections::ADVERTISER);
|
||||
|
||||
// Initialize and set a AdvertisingPhase.
|
||||
started_advertising_phase_time_ = SystemClock::ElapsedRealtime();
|
||||
current_advertising_phase_ = std::make_unique<AdvertisingPhase>();
|
||||
absl::c_copy(mediums, RepeatedFieldBackInserter(
|
||||
current_advertising_phase_->mutable_medium()));
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnStopAdvertising() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnStopAdvertising")) {
|
||||
return;
|
||||
}
|
||||
RecordAdvertisingPhaseDurationLocked();
|
||||
}
|
||||
void AnalyticsRecorder::OnStartDiscovery(connections::Strategy strategy,
|
||||
const std::vector<Medium> &mediums) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnStartDiscovery")) {
|
||||
return;
|
||||
}
|
||||
if (!strategy.IsValid()) {
|
||||
NEARBY_LOGS(INFO) << "AnalyticsRecorder OnStartDiscovery unknown "
|
||||
"strategy enter, bail out.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize/update a StrategySession.
|
||||
UpdateStrategySessionLocked(
|
||||
strategy, ::location::nearby::proto::connections::DISCOVERER);
|
||||
|
||||
// Initialize and set a DiscoveryPhase.
|
||||
started_discovery_phase_time_ = SystemClock::ElapsedRealtime();
|
||||
current_discovery_phase_ = std::make_unique<DiscoveryPhase>();
|
||||
for (auto medium : mediums) {
|
||||
current_discovery_phase_->add_medium(medium);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnStopDiscovery() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnStopDiscovery")) {
|
||||
return;
|
||||
}
|
||||
RecordDiscoveryPhaseDurationLocked();
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnEndpointFound(Medium medium) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnEndpointFound")) {
|
||||
return;
|
||||
}
|
||||
if (current_discovery_phase_ == nullptr) {
|
||||
NEARBY_LOGS(INFO) << "Unable to record discovered endpoint due to null "
|
||||
"current_discovery_phase_";
|
||||
return;
|
||||
}
|
||||
DiscoveredEndpoint *discovered_endpoint =
|
||||
current_discovery_phase_->add_discovered_endpoint();
|
||||
discovered_endpoint->set_medium(medium);
|
||||
discovered_endpoint->set_latency_millis(absl::ToInt64Milliseconds(
|
||||
SystemClock::ElapsedRealtime() - started_discovery_phase_time_));
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnConnectionRequestReceived(
|
||||
const std::string &remote_endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnConnectionRequestReceived")) {
|
||||
return;
|
||||
}
|
||||
absl::Time current_time = SystemClock::ElapsedRealtime();
|
||||
auto connection_request(std::make_unique<ConnectionRequest>());
|
||||
connection_request->set_duration_millis(absl::ToUnixMillis(current_time));
|
||||
connection_request->set_request_delay_millis(absl::ToInt64Milliseconds(
|
||||
current_time - started_advertising_phase_time_));
|
||||
incoming_connection_requests_.emplace(remote_endpoint_id,
|
||||
std::move(connection_request));
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnConnectionRequestSent(
|
||||
const std::string &remote_endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnConnectionRequestSent")) {
|
||||
return;
|
||||
}
|
||||
absl::Time current_time = SystemClock::ElapsedRealtime();
|
||||
auto connection_request(std::make_unique<ConnectionRequest>());
|
||||
connection_request->set_duration_millis(absl::ToUnixMillis(current_time));
|
||||
connection_request->set_request_delay_millis(
|
||||
absl::ToInt64Milliseconds(current_time - started_discovery_phase_time_));
|
||||
outgoing_connection_requests_.emplace(remote_endpoint_id,
|
||||
std::move(connection_request));
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnRemoteEndpointAccepted(
|
||||
const std::string &remote_endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnRemoteEndpointAccepted")) {
|
||||
return;
|
||||
}
|
||||
RemoteEndpointRespondedLocked(
|
||||
remote_endpoint_id, ::location::nearby::proto::connections::ACCEPTED);
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnLocalEndpointAccepted(
|
||||
const std::string &remote_endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnLocalEndpointAccepted")) {
|
||||
return;
|
||||
}
|
||||
LocalEndpointRespondedLocked(
|
||||
remote_endpoint_id, ::location::nearby::proto::connections::ACCEPTED);
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnRemoteEndpointRejected(
|
||||
const std::string &remote_endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnRemoteEndpointRejected")) {
|
||||
return;
|
||||
}
|
||||
RemoteEndpointRespondedLocked(
|
||||
remote_endpoint_id, ::location::nearby::proto::connections::REJECTED);
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::OnLocalEndpointRejected(
|
||||
const std::string &remote_endpoint_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("OnLocalEndpointRejected")) {
|
||||
return;
|
||||
}
|
||||
LocalEndpointRespondedLocked(
|
||||
remote_endpoint_id, ::location::nearby::proto::connections::REJECTED);
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::LogSession() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!CanRecordAnalyticsLocked("LogSession")) {
|
||||
return;
|
||||
}
|
||||
FinishStrategySessionLocked();
|
||||
client_session_->set_duration_millis(absl::ToInt64Milliseconds(
|
||||
SystemClock::ElapsedRealtime() - started_client_session_time_));
|
||||
LogClientSession();
|
||||
LogEvent(::location::nearby::proto::connections::STOP_CLIENT_SESSION);
|
||||
session_was_logged_ = true;
|
||||
}
|
||||
|
||||
bool AnalyticsRecorder::CanRecordAnalyticsLocked(
|
||||
const std::string &method_name) {
|
||||
NEARBY_LOGS(VERBOSE) << "AnalyticsRecorder LogEvent " << method_name
|
||||
<< " is calling.";
|
||||
if (event_logger_ == nullptr) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "AnalyticsRecorder CanRecordAnalytics Unexpected call "
|
||||
<< method_name << " due to event_logger is null.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (session_was_logged_) {
|
||||
NEARBY_LOGS(WARNING)
|
||||
<< "AnalyticsRecorder CanRecordAnalytics Unexpected call "
|
||||
<< method_name << " after session has already been logged.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::LogClientSession() {
|
||||
serial_executor_.Execute(
|
||||
"analytics-recorder", [this]() {
|
||||
ConnectionsLog connections_log;
|
||||
connections_log.set_event_type(
|
||||
::location::nearby::proto::connections::CLIENT_SESSION);
|
||||
connections_log.set_allocated_client_session(client_session_.release());
|
||||
connections_log.set_version(kVersion);
|
||||
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< "AnalyticsRecorder LogClientSession connections_log="
|
||||
<< connections_log.DebugString();
|
||||
|
||||
event_logger_->Log(connections_log);
|
||||
});
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::LogEvent(EventType event_type) {
|
||||
serial_executor_.Execute("analytics-recorder", [this, event_type]() {
|
||||
ConnectionsLog connections_log;
|
||||
connections_log.set_event_type(event_type);
|
||||
connections_log.set_version(kVersion);
|
||||
|
||||
NEARBY_LOGS(VERBOSE) << "AnalyticsRecorder LogEvent connections_log="
|
||||
<< connections_log.DebugString();
|
||||
|
||||
event_logger_->Log(connections_log);
|
||||
});
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::UpdateStrategySessionLocked(
|
||||
connections::Strategy strategy, SessionRole role) {
|
||||
// If we're not switching strategies, just update the current StrategySession
|
||||
// with the new role.
|
||||
if (strategy == current_strategy_) {
|
||||
if (absl::c_linear_search(current_strategy_session_->role(), role)) {
|
||||
// We've already acted as this role before, so make sure we've finished
|
||||
// recording the previous round.
|
||||
switch (role) {
|
||||
case ::location::nearby::proto::connections::ADVERTISER:
|
||||
FinishAdvertisingPhaseLocked();
|
||||
break;
|
||||
case ::location::nearby::proto::connections::DISCOVERER:
|
||||
FinishDiscoveryPhaseLocked();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
current_strategy_session_->add_role(role);
|
||||
}
|
||||
} else {
|
||||
// Otherwise, we're starting a new Strategy.
|
||||
current_strategy_ = strategy;
|
||||
FinishStrategySessionLocked();
|
||||
LogEvent(::location::nearby::proto::connections::START_STRATEGY_SESSION);
|
||||
current_strategy_session_ = std::make_unique<StrategySession>();
|
||||
started_strategy_session_time_ = SystemClock::ElapsedRealtime();
|
||||
current_strategy_session_->set_strategy(
|
||||
StrategyToConnectionStrategy(strategy));
|
||||
current_strategy_session_->add_role(role);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::RecordAdvertisingPhaseDurationLocked() const {
|
||||
if (current_advertising_phase_ == nullptr) {
|
||||
NEARBY_LOGS(INFO) << "Unable to record advertising phase duration due to "
|
||||
"null current_advertising_phase_";
|
||||
return;
|
||||
}
|
||||
if (!current_advertising_phase_->has_duration_millis()) {
|
||||
current_advertising_phase_->set_duration_millis(absl::ToInt64Milliseconds(
|
||||
SystemClock::ElapsedRealtime() - started_advertising_phase_time_));
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::FinishAdvertisingPhaseLocked() {
|
||||
if (current_advertising_phase_ != nullptr) {
|
||||
for (const auto &item : incoming_connection_requests_) {
|
||||
// ConnectionRequests still pending have been ignored by the local or
|
||||
// remote (or both) endpoints.
|
||||
auto &connection_request = item.second;
|
||||
MarkConnectionRequestIgnoredLocked(connection_request.get());
|
||||
UpdateAdvertiserConnectionRequestLocked(connection_request.get());
|
||||
}
|
||||
RecordAdvertisingPhaseDurationLocked();
|
||||
*current_strategy_session_->add_advertising_phase() =
|
||||
*std::move(current_advertising_phase_);
|
||||
}
|
||||
incoming_connection_requests_.clear();
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::RecordDiscoveryPhaseDurationLocked() const {
|
||||
if (current_discovery_phase_ == nullptr) {
|
||||
NEARBY_LOGS(INFO) << "Unable to record discovery phase duration due to "
|
||||
"null current_discovery_phase_";
|
||||
return;
|
||||
}
|
||||
if (!current_discovery_phase_->has_duration_millis()) {
|
||||
current_discovery_phase_->set_duration_millis(absl::ToInt64Milliseconds(
|
||||
SystemClock::ElapsedRealtime() - started_discovery_phase_time_));
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::FinishDiscoveryPhaseLocked() {
|
||||
if (current_discovery_phase_ != nullptr) {
|
||||
for (const auto &item : outgoing_connection_requests_) {
|
||||
// ConnectionRequests still pending have been ignored by the local or
|
||||
// remote (or both) endpoints.
|
||||
auto &connection_request = item.second;
|
||||
MarkConnectionRequestIgnoredLocked(connection_request.get());
|
||||
UpdateDiscovererConnectionRequestLocked(connection_request.get());
|
||||
}
|
||||
RecordDiscoveryPhaseDurationLocked();
|
||||
*current_strategy_session_->add_discovery_phase() =
|
||||
*std::move(current_discovery_phase_);
|
||||
}
|
||||
outgoing_connection_requests_.clear();
|
||||
}
|
||||
|
||||
bool AnalyticsRecorder::UpdateAdvertiserConnectionRequestLocked(
|
||||
ConnectionRequest *request) {
|
||||
if (current_advertising_phase_ == nullptr) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Unable to record advertiser connection request due to null "
|
||||
"current_advertising_phase_";
|
||||
return false;
|
||||
}
|
||||
if (BothEndpointsRespondedLocked(request)) {
|
||||
request->set_duration_millis(
|
||||
absl::ToUnixMillis(SystemClock::ElapsedRealtime()) -
|
||||
request->duration_millis());
|
||||
*current_advertising_phase_->add_received_connection_request() =
|
||||
*std::move(request);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AnalyticsRecorder::UpdateDiscovererConnectionRequestLocked(
|
||||
ConnectionRequest *request) {
|
||||
if (current_discovery_phase_ == nullptr) {
|
||||
NEARBY_LOGS(INFO) << "Unable to record discoverer connection request due "
|
||||
"to null current_discovery_phase_.";
|
||||
return false;
|
||||
}
|
||||
if (BothEndpointsRespondedLocked(request) ||
|
||||
request->local_response() ==
|
||||
::location::nearby::proto::connections::NOT_SENT) {
|
||||
request->set_duration_millis(
|
||||
absl::ToUnixMillis(SystemClock::ElapsedRealtime()) -
|
||||
request->duration_millis());
|
||||
*current_discovery_phase_->add_sent_connection_request() =
|
||||
*std::move(request);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AnalyticsRecorder::BothEndpointsRespondedLocked(
|
||||
ConnectionRequest *request) {
|
||||
return request->has_local_response() && request->has_remote_response();
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::LocalEndpointRespondedLocked(
|
||||
const std::string &remote_endpoint_id, ConnectionRequestResponse response) {
|
||||
auto out = outgoing_connection_requests_.find(remote_endpoint_id);
|
||||
if (out != outgoing_connection_requests_.end()) {
|
||||
ConnectionRequest *connection_request = out->second.get();
|
||||
connection_request->set_local_response(response);
|
||||
if (UpdateDiscovererConnectionRequestLocked(connection_request)) {
|
||||
outgoing_connection_requests_.erase(out);
|
||||
}
|
||||
}
|
||||
auto in = incoming_connection_requests_.find(remote_endpoint_id);
|
||||
if (in != incoming_connection_requests_.end()) {
|
||||
ConnectionRequest *connection_request = in->second.get();
|
||||
connection_request->set_local_response(response);
|
||||
if (UpdateAdvertiserConnectionRequestLocked(connection_request)) {
|
||||
incoming_connection_requests_.erase(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::RemoteEndpointRespondedLocked(
|
||||
const std::string &remote_endpoint_id, ConnectionRequestResponse response) {
|
||||
auto out = outgoing_connection_requests_.find(remote_endpoint_id);
|
||||
if (out != outgoing_connection_requests_.end()) {
|
||||
ConnectionRequest *connection_request = out->second.get();
|
||||
connection_request->set_remote_response(response);
|
||||
if (UpdateDiscovererConnectionRequestLocked(connection_request)) {
|
||||
outgoing_connection_requests_.erase(out);
|
||||
}
|
||||
}
|
||||
auto in = incoming_connection_requests_.find(remote_endpoint_id);
|
||||
if (in != incoming_connection_requests_.end()) {
|
||||
ConnectionRequest *connection_request = in->second.get();
|
||||
connection_request->set_remote_response(response);
|
||||
if (UpdateAdvertiserConnectionRequestLocked(connection_request)) {
|
||||
incoming_connection_requests_.erase(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::MarkConnectionRequestIgnoredLocked(
|
||||
ConnectionRequest *request) {
|
||||
if (!request->has_local_response()) {
|
||||
request->set_local_response(
|
||||
::location::nearby::proto::connections::IGNORED);
|
||||
}
|
||||
if (!request->has_remote_response()) {
|
||||
request->set_remote_response(
|
||||
::location::nearby::proto::connections::IGNORED);
|
||||
}
|
||||
}
|
||||
|
||||
void AnalyticsRecorder::FinishStrategySessionLocked() {
|
||||
if (current_strategy_session_ != nullptr) {
|
||||
FinishAdvertisingPhaseLocked();
|
||||
FinishDiscoveryPhaseLocked();
|
||||
|
||||
// Add the StrategySession in ClientSession
|
||||
current_strategy_session_->set_duration_millis(absl::ToInt64Milliseconds(
|
||||
SystemClock::ElapsedRealtime() - SystemClock::ElapsedRealtime()));
|
||||
*client_session_->add_strategy_session() =
|
||||
*std::move(current_strategy_session_);
|
||||
LogEvent(::location::nearby::proto::connections::STOP_STRATEGY_SESSION);
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionStrategy AnalyticsRecorder::StrategyToConnectionStrategy(
|
||||
connections::Strategy strategy) {
|
||||
if (strategy == connections::Strategy::kP2pCluster) {
|
||||
return ::location::nearby::proto::connections::P2P_CLUSTER;
|
||||
}
|
||||
if (strategy == connections::Strategy::kP2pStar) {
|
||||
return ::location::nearby::proto::connections::P2P_STAR;
|
||||
}
|
||||
if (strategy == connections::Strategy::kP2pPointToPoint) {
|
||||
return ::location::nearby::proto::connections::P2P_POINT_TO_POINT;
|
||||
}
|
||||
return ::location::nearby::proto::connections::UNKNOWN_STRATEGY;
|
||||
}
|
||||
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -0,0 +1,170 @@
|
||||
// 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 ANALYTICS_ANALYTICS_RECORDER_H_
|
||||
#define ANALYTICS_ANALYTICS_RECORDER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "core/event_logger.h"
|
||||
#include "core/strategy.h"
|
||||
#include "platform/public/mutex.h"
|
||||
#include "platform/public/single_thread_executor.h"
|
||||
#include "proto/analytics/connections_log.proto.h"
|
||||
#include "proto/connections_enums.proto.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
|
||||
class AnalyticsRecorder {
|
||||
public:
|
||||
static constexpr absl::string_view kVersion = "v1.0.0";
|
||||
|
||||
explicit AnalyticsRecorder(EventLogger *event_logger);
|
||||
virtual ~AnalyticsRecorder();
|
||||
|
||||
// Advertising phase
|
||||
void OnStartAdvertising(
|
||||
connections::Strategy strategy,
|
||||
const std::vector<::location::nearby::proto::connections::Medium>
|
||||
&mediums) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnStopAdvertising() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Discovery phase
|
||||
void OnStartDiscovery(
|
||||
connections::Strategy strategy,
|
||||
const std::vector<::location::nearby::proto::connections::Medium>
|
||||
&mediums) ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnStopDiscovery() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnEndpointFound(::location::nearby::proto::connections::Medium medium)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Connection request
|
||||
void OnConnectionRequestReceived(const std::string &remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnConnectionRequestSent(const std::string &remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnRemoteEndpointAccepted(const std::string &remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnLocalEndpointAccepted(const std::string &remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnRemoteEndpointRejected(const std::string &remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
void OnLocalEndpointRejected(const std::string &remote_endpoint_id)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Invokes event_logger_.Log() at the end of life of client. Log action is
|
||||
// called in a separate thread to allow synchronous potentially lengthy
|
||||
// execution.
|
||||
void LogSession() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
bool CanRecordAnalyticsLocked(const std::string &method_name)
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Callbacks the ConnectionsLog proto byte array data to the EventLogger with
|
||||
// ClientSession sub-proto.
|
||||
void LogClientSession();
|
||||
// Callbacks the ConnectionsLog proto byte array data to the EventLogger.
|
||||
void LogEvent(::location::nearby::proto::connections::EventType event_type);
|
||||
|
||||
void UpdateStrategySessionLocked(
|
||||
connections::Strategy strategy,
|
||||
::location::nearby::proto::connections::SessionRole role)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void RecordAdvertisingPhaseDurationLocked() const
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void FinishAdvertisingPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void RecordDiscoveryPhaseDurationLocked() const
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void FinishDiscoveryPhaseLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
bool UpdateAdvertiserConnectionRequestLocked(
|
||||
::location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest
|
||||
*request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
bool UpdateDiscovererConnectionRequestLocked(
|
||||
::location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest
|
||||
*request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
bool BothEndpointsRespondedLocked(
|
||||
::location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest
|
||||
*request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void LocalEndpointRespondedLocked(
|
||||
const std::string &remote_endpoint_id,
|
||||
::location::nearby::proto::connections::ConnectionRequestResponse
|
||||
response) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void RemoteEndpointRespondedLocked(
|
||||
const std::string &remote_endpoint_id,
|
||||
::location::nearby::proto::connections::ConnectionRequestResponse
|
||||
response) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
void MarkConnectionRequestIgnoredLocked(
|
||||
::location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest
|
||||
*request) ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
void FinishStrategySessionLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
::location::nearby::proto::connections::ConnectionsStrategy
|
||||
StrategyToConnectionStrategy(connections::Strategy strategy);
|
||||
|
||||
// Not owned by AnalyticsRecorder. Pointer must refer to a valid object
|
||||
// that outlives the one constructed.
|
||||
EventLogger *event_logger_;
|
||||
|
||||
SingleThreadExecutor serial_executor_;
|
||||
// Protects all sub-protos reading and writing in ConnectionLog.
|
||||
Mutex mutex_;
|
||||
|
||||
// ClientSession
|
||||
std::unique_ptr<
|
||||
::location::nearby::analytics::proto::ConnectionsLog::ClientSession>
|
||||
client_session_ = std::make_unique<::location::nearby::analytics::proto::
|
||||
ConnectionsLog::ClientSession>();
|
||||
absl::Time started_client_session_time_;
|
||||
bool session_was_logged_ ABSL_GUARDED_BY(mutex_) = false;
|
||||
|
||||
// Current StrategySession
|
||||
connections::Strategy current_strategy_ ABSL_GUARDED_BY(mutex_) =
|
||||
connections::Strategy::kNone;
|
||||
std::unique_ptr<
|
||||
::location::nearby::analytics::proto::ConnectionsLog::StrategySession>
|
||||
current_strategy_session_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::Time started_strategy_session_time_ ABSL_GUARDED_BY(mutex_);
|
||||
|
||||
// Current AdvertisingPhase
|
||||
std::unique_ptr<
|
||||
::location::nearby::analytics::proto::ConnectionsLog::AdvertisingPhase>
|
||||
current_advertising_phase_;
|
||||
absl::Time started_advertising_phase_time_;
|
||||
|
||||
// Current DiscoveryPhase
|
||||
std::unique_ptr<
|
||||
::location::nearby::analytics::proto::ConnectionsLog::DiscoveryPhase>
|
||||
current_discovery_phase_;
|
||||
absl::Time started_discovery_phase_time_;
|
||||
|
||||
absl::btree_map<std::string,
|
||||
std::unique_ptr<::location::nearby::analytics::proto::
|
||||
ConnectionsLog::ConnectionRequest>>
|
||||
incoming_connection_requests_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::btree_map<std::string,
|
||||
std::unique_ptr<::location::nearby::analytics::proto::
|
||||
ConnectionsLog::ConnectionRequest>>
|
||||
outgoing_connection_requests_ ABSL_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
#endif // ANALYTICS_ANALYTICS_RECORDER_H_
|
||||
@@ -0,0 +1,464 @@
|
||||
// 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 "third_party/nearby_connections/cpp/analytics/analytics_recorder.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "platform/public/count_down_latch.h"
|
||||
#include "platform/public/logging.h"
|
||||
#include "proto/analytics/connections_log.proto.h"
|
||||
#include "proto/connections_enums.proto.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace analytics {
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::proto::connections::ACCEPTED;
|
||||
using ::location::nearby::proto::connections::BLE;
|
||||
using ::location::nearby::proto::connections::BLUETOOTH;
|
||||
using ::location::nearby::proto::connections::CLIENT_SESSION;
|
||||
using ::location::nearby::proto::connections::ConnectionRequestResponse;
|
||||
using ::location::nearby::proto::connections::EventType;
|
||||
using ::location::nearby::proto::connections::IGNORED;
|
||||
using ::location::nearby::proto::connections::Medium;
|
||||
using ::location::nearby::proto::connections::REJECTED;
|
||||
using ::location::nearby::proto::connections::START_STRATEGY_SESSION;
|
||||
using ::location::nearby::proto::connections::STOP_CLIENT_SESSION;
|
||||
using ::location::nearby::proto::connections::STOP_STRATEGY_SESSION;
|
||||
using ::testing::Contains;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::UnorderedElementsAreArray;
|
||||
|
||||
using ::location::nearby::analytics::proto::ConnectionsLog;
|
||||
using ClientSession =
|
||||
::location::nearby::analytics::proto::ConnectionsLog::ClientSession;
|
||||
using StrategySession =
|
||||
::location::nearby::analytics::proto::ConnectionsLog::StrategySession;
|
||||
using AdvertisingPhase =
|
||||
::location::nearby::analytics::proto::ConnectionsLog::AdvertisingPhase;
|
||||
using DiscoveryPhase =
|
||||
::location::nearby::analytics::proto::ConnectionsLog::DiscoveryPhase;
|
||||
using DiscoveredEndpoint =
|
||||
::location::nearby::analytics::proto::ConnectionsLog::DiscoveredEndpoint;
|
||||
using ConnectionRequest =
|
||||
::location::nearby::analytics::proto::ConnectionsLog::ConnectionRequest;
|
||||
|
||||
constexpr absl::Duration kDefaultTimeout = absl::Milliseconds(1000);
|
||||
|
||||
class FakeEventLogger : public EventLogger {
|
||||
public:
|
||||
explicit FakeEventLogger(CountDownLatch& client_session_done_latch)
|
||||
: client_session_done_latch_(client_session_done_latch) {}
|
||||
|
||||
void Log(const ConnectionsLog& connections_log) override {
|
||||
EventType event_type = connections_log.event_type();
|
||||
logged_event_types_.push_back(event_type);
|
||||
if (event_type == CLIENT_SESSION) {
|
||||
logged_client_session_count_++;
|
||||
logged_client_session_ = connections_log.client_session();
|
||||
}
|
||||
if (event_type == STOP_CLIENT_SESSION) {
|
||||
client_session_done_latch_.CountDown();
|
||||
}
|
||||
}
|
||||
|
||||
int GetLoggedClientSessionCount() const {
|
||||
return logged_client_session_count_;
|
||||
}
|
||||
|
||||
const ClientSession& GetLoggedClientSession() {
|
||||
return logged_client_session_;
|
||||
}
|
||||
|
||||
std::vector<EventType> GetLoggedEventTypes() { return logged_event_types_; }
|
||||
|
||||
private:
|
||||
int logged_client_session_count_ = 0;
|
||||
CountDownLatch& client_session_done_latch_;
|
||||
ClientSession logged_client_session_;
|
||||
std::vector<EventType> logged_event_types_;
|
||||
};
|
||||
|
||||
TEST(AnalyticsRecorderTest, SessionOnlyLoggedOnceWorks) {
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
analytics_recorder.LogSession();
|
||||
analytics_recorder.LogSession();
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
// Only called once.
|
||||
EXPECT_EQ(event_logger.GetLoggedClientSessionCount(), 1);
|
||||
}
|
||||
|
||||
TEST(AnalyticsRecorderTest, SetFieldsCorrectlyForNestedAdvertisingCalls) {
|
||||
connections::Strategy strategy = connections::Strategy::kP2pStar;
|
||||
std::vector<Medium> mediums = {BLE, BLUETOOTH};
|
||||
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.OnStartAdvertising(strategy, mediums);
|
||||
analytics_recorder.OnStopAdvertising();
|
||||
analytics_recorder.OnStartAdvertising(strategy, {BLUETOOTH});
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
const ClientSession& client_session = event_logger.GetLoggedClientSession();
|
||||
ASSERT_EQ(client_session.strategy_session_size(), 1);
|
||||
ASSERT_EQ(client_session.strategy_session(0).advertising_phase_size(), 2);
|
||||
EXPECT_THAT(client_session.strategy_session(0).advertising_phase(0).medium(),
|
||||
UnorderedElementsAreArray(mediums));
|
||||
EXPECT_THAT(client_session.strategy_session(0).advertising_phase(1).medium(),
|
||||
ElementsAre(BLUETOOTH));
|
||||
}
|
||||
|
||||
TEST(AnalyticsRecorderTest, SetFieldsCorrectlyForNestedDiscoveryCalls) {
|
||||
connections::Strategy strategy = connections::Strategy::kP2pStar;
|
||||
std::vector<Medium> mediums = {BLE, BLUETOOTH};
|
||||
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.OnStartDiscovery(strategy, mediums);
|
||||
analytics_recorder.OnStopDiscovery();
|
||||
analytics_recorder.OnEndpointFound(BLUETOOTH);
|
||||
analytics_recorder.OnEndpointFound(BLE);
|
||||
analytics_recorder.OnStartDiscovery(strategy, {BLUETOOTH});
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
const ClientSession& client_session = event_logger.GetLoggedClientSession();
|
||||
EXPECT_EQ(client_session.strategy_session_size(), 1);
|
||||
EXPECT_EQ(client_session.strategy_session(0).discovery_phase_size(), 2);
|
||||
EXPECT_THAT(client_session.strategy_session(0).discovery_phase(0).medium(),
|
||||
UnorderedElementsAreArray(mediums));
|
||||
EXPECT_EQ(client_session.strategy_session(0)
|
||||
.discovery_phase(0)
|
||||
.discovered_endpoint_size(),
|
||||
2);
|
||||
EXPECT_EQ(client_session.strategy_session(0)
|
||||
.discovery_phase(0)
|
||||
.discovered_endpoint(0)
|
||||
.medium(),
|
||||
BLUETOOTH);
|
||||
EXPECT_EQ(client_session.strategy_session(0)
|
||||
.discovery_phase(0)
|
||||
.discovered_endpoint(1)
|
||||
.medium(),
|
||||
BLE);
|
||||
EXPECT_THAT(client_session.strategy_session(0).discovery_phase(1).medium(),
|
||||
ElementsAre(BLUETOOTH));
|
||||
}
|
||||
|
||||
TEST(AnalyticsRecorderTest,
|
||||
OneStrategySessionForMultipleRoundsOfDiscoveryAdvertising) {
|
||||
connections::Strategy strategy = connections::Strategy::kP2pStar;
|
||||
std::vector<Medium> mediums = {BLE, BLUETOOTH};
|
||||
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.OnStartAdvertising(strategy, mediums);
|
||||
analytics_recorder.OnStartDiscovery(strategy, mediums);
|
||||
analytics_recorder.OnStopAdvertising();
|
||||
analytics_recorder.OnStopDiscovery();
|
||||
analytics_recorder.OnStartAdvertising(strategy, mediums);
|
||||
analytics_recorder.OnStopAdvertising();
|
||||
analytics_recorder.OnStartDiscovery(strategy, mediums);
|
||||
analytics_recorder.OnStopDiscovery();
|
||||
analytics_recorder.OnStartDiscovery(strategy, mediums);
|
||||
analytics_recorder.OnStartAdvertising(strategy, mediums);
|
||||
analytics_recorder.OnStopDiscovery();
|
||||
analytics_recorder.OnStopAdvertising();
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
std::vector<EventType> event_types = event_logger.GetLoggedEventTypes();
|
||||
EXPECT_THAT(event_types, Contains(START_STRATEGY_SESSION).Times(1));
|
||||
EXPECT_THAT(event_types, Contains(STOP_STRATEGY_SESSION).Times(1));
|
||||
const ClientSession& client_session = event_logger.GetLoggedClientSession();
|
||||
EXPECT_EQ(client_session.strategy_session_size(), 1);
|
||||
EXPECT_EQ(client_session.strategy_session(0).advertising_phase_size(), 3);
|
||||
EXPECT_EQ(client_session.strategy_session(0).discovery_phase_size(), 3);
|
||||
}
|
||||
|
||||
TEST(AnalyticsRecorderTest, AdvertiserConnectionRequestsWorks) {
|
||||
connections::Strategy strategy = connections::Strategy::kP2pStar;
|
||||
std::vector<Medium> mediums = {BLE, BLUETOOTH};
|
||||
std::string endpoint_id_0("endpoint_id_0");
|
||||
std::string endpoint_id_1("endpoint_id_1");
|
||||
std::string endpoint_id_2("endpoint_id_2");
|
||||
std::string endpoint_id_3("endpoint_id_3");
|
||||
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.OnStartAdvertising(strategy, mediums);
|
||||
analytics_recorder.OnConnectionRequestReceived(endpoint_id_0);
|
||||
analytics_recorder.OnLocalEndpointAccepted(endpoint_id_0);
|
||||
analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_0);
|
||||
|
||||
analytics_recorder.OnConnectionRequestReceived(endpoint_id_1);
|
||||
analytics_recorder.OnLocalEndpointAccepted(endpoint_id_1);
|
||||
analytics_recorder.OnRemoteEndpointRejected(endpoint_id_1);
|
||||
|
||||
analytics_recorder.OnConnectionRequestReceived(endpoint_id_2);
|
||||
analytics_recorder.OnLocalEndpointRejected(endpoint_id_2);
|
||||
analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_2);
|
||||
|
||||
analytics_recorder.OnConnectionRequestReceived(endpoint_id_3);
|
||||
analytics_recorder.OnLocalEndpointRejected(endpoint_id_3);
|
||||
analytics_recorder.OnRemoteEndpointRejected(endpoint_id_3);
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
const ClientSession& client_session = event_logger.GetLoggedClientSession();
|
||||
StrategySession strategy_session = client_session.strategy_session(0);
|
||||
EXPECT_EQ(strategy_session.advertising_phase_size(), 1);
|
||||
EXPECT_EQ(
|
||||
strategy_session.advertising_phase(0).received_connection_request_size(),
|
||||
4);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(0)
|
||||
.local_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(0)
|
||||
.remote_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(1)
|
||||
.local_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(1)
|
||||
.remote_response(),
|
||||
REJECTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(2)
|
||||
.local_response(),
|
||||
REJECTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(2)
|
||||
.remote_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(3)
|
||||
.local_response(),
|
||||
REJECTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(3)
|
||||
.remote_response(),
|
||||
REJECTED);
|
||||
}
|
||||
|
||||
TEST(AnalyticsRecorderTest, DiscoveryConnectionRequestsWorks) {
|
||||
connections::Strategy strategy = connections::Strategy::kP2pStar;
|
||||
std::vector<Medium> mediums = {BLE, BLUETOOTH};
|
||||
|
||||
std::string endpoint_id_0("endpoint_id_0");
|
||||
std::string endpoint_id_1("endpoint_id_1");
|
||||
std::string endpoint_id_2("endpoint_id_2");
|
||||
std::string endpoint_id_3("endpoint_id_3");
|
||||
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.OnStartDiscovery(strategy, mediums);
|
||||
|
||||
analytics_recorder.OnConnectionRequestSent(endpoint_id_0);
|
||||
analytics_recorder.OnLocalEndpointAccepted(endpoint_id_0);
|
||||
analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_0);
|
||||
|
||||
analytics_recorder.OnConnectionRequestSent(endpoint_id_1);
|
||||
analytics_recorder.OnLocalEndpointAccepted(endpoint_id_1);
|
||||
analytics_recorder.OnRemoteEndpointRejected(endpoint_id_1);
|
||||
|
||||
analytics_recorder.OnConnectionRequestSent(endpoint_id_2);
|
||||
analytics_recorder.OnLocalEndpointRejected(endpoint_id_2);
|
||||
analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_2);
|
||||
|
||||
analytics_recorder.OnConnectionRequestSent(endpoint_id_3);
|
||||
analytics_recorder.OnLocalEndpointRejected(endpoint_id_3);
|
||||
analytics_recorder.OnRemoteEndpointRejected(endpoint_id_3);
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
const ClientSession& client_session = event_logger.GetLoggedClientSession();
|
||||
StrategySession strategy_session = client_session.strategy_session(0);
|
||||
EXPECT_EQ(strategy_session.discovery_phase_size(), 1);
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0).sent_connection_request_size(),
|
||||
4);
|
||||
auto& sent_connection_request_0 =
|
||||
strategy_session.discovery_phase(0).sent_connection_request(0);
|
||||
EXPECT_EQ(sent_connection_request_0.local_response(), ACCEPTED);
|
||||
EXPECT_EQ(sent_connection_request_0.remote_response(), ACCEPTED);
|
||||
auto& sent_connection_request_1 =
|
||||
strategy_session.discovery_phase(0).sent_connection_request(1);
|
||||
EXPECT_EQ(sent_connection_request_1.local_response(), ACCEPTED);
|
||||
EXPECT_EQ(sent_connection_request_1.remote_response(), REJECTED);
|
||||
auto& sent_connection_request_2 =
|
||||
strategy_session.discovery_phase(0).sent_connection_request(2);
|
||||
EXPECT_EQ(sent_connection_request_2.local_response(), REJECTED);
|
||||
EXPECT_EQ(sent_connection_request_2.remote_response(), ACCEPTED);
|
||||
auto& sent_connection_request_3 =
|
||||
strategy_session.discovery_phase(0).sent_connection_request(3);
|
||||
EXPECT_EQ(sent_connection_request_3.local_response(), REJECTED);
|
||||
EXPECT_EQ(sent_connection_request_3.remote_response(), REJECTED);
|
||||
}
|
||||
|
||||
TEST(AnalyticsRecorderTest,
|
||||
AdvertiserUnfinishedConnectionRequestsIncludedAsIgnored) {
|
||||
connections::Strategy strategy = connections::Strategy::kP2pStar;
|
||||
std::vector<Medium> mediums = {BLE, BLUETOOTH};
|
||||
std::string endpoint_id_0("endpoint_id_0");
|
||||
std::string endpoint_id_1("endpoint_id_1");
|
||||
std::string endpoint_id_2("endpoint_id_2");
|
||||
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.OnStartAdvertising(strategy, mediums);
|
||||
// Ignored by local.
|
||||
analytics_recorder.OnConnectionRequestReceived(endpoint_id_0);
|
||||
analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_0);
|
||||
|
||||
// Ignored by remote.
|
||||
analytics_recorder.OnConnectionRequestReceived(endpoint_id_1);
|
||||
analytics_recorder.OnLocalEndpointAccepted(endpoint_id_1);
|
||||
|
||||
// Ignored by both.
|
||||
analytics_recorder.OnConnectionRequestReceived(endpoint_id_2);
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
const ClientSession& client_session = event_logger.GetLoggedClientSession();
|
||||
StrategySession strategy_session = client_session.strategy_session(0);
|
||||
EXPECT_EQ(strategy_session.advertising_phase_size(), 1);
|
||||
EXPECT_EQ(
|
||||
strategy_session.advertising_phase(0).received_connection_request_size(),
|
||||
3);
|
||||
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(0)
|
||||
.local_response(),
|
||||
IGNORED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(0)
|
||||
.remote_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(1)
|
||||
.local_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(1)
|
||||
.remote_response(),
|
||||
IGNORED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(2)
|
||||
.local_response(),
|
||||
IGNORED);
|
||||
EXPECT_EQ(strategy_session.advertising_phase(0)
|
||||
.received_connection_request(2)
|
||||
.remote_response(),
|
||||
IGNORED);
|
||||
}
|
||||
|
||||
TEST(AnalyticsRecorderTest,
|
||||
DiscovererUnfinishedConnectionRequestsIncludedAsIgnored) {
|
||||
connections::Strategy strategy = connections::Strategy::kP2pStar;
|
||||
std::vector<Medium> mediums = {BLE, BLUETOOTH};
|
||||
std::string endpoint_id_0("endpoint_id_0");
|
||||
std::string endpoint_id_1("endpoint_id_1");
|
||||
std::string endpoint_id_2("endpoint_id_2");
|
||||
|
||||
CountDownLatch client_session_done_latch(1);
|
||||
FakeEventLogger event_logger(client_session_done_latch);
|
||||
AnalyticsRecorder analytics_recorder(&event_logger);
|
||||
|
||||
analytics_recorder.OnStartDiscovery(strategy, mediums);
|
||||
|
||||
// Ignored by local.
|
||||
analytics_recorder.OnConnectionRequestSent(endpoint_id_0);
|
||||
analytics_recorder.OnRemoteEndpointAccepted(endpoint_id_0);
|
||||
|
||||
// Ignored by remote.
|
||||
analytics_recorder.OnConnectionRequestSent(endpoint_id_1);
|
||||
analytics_recorder.OnLocalEndpointAccepted(endpoint_id_1);
|
||||
|
||||
// Ignored by both.
|
||||
analytics_recorder.OnConnectionRequestSent(endpoint_id_2);
|
||||
|
||||
analytics_recorder.LogSession();
|
||||
EXPECT_TRUE(client_session_done_latch.Await(kDefaultTimeout).result());
|
||||
|
||||
const ClientSession& client_session = event_logger.GetLoggedClientSession();
|
||||
StrategySession strategy_session = client_session.strategy_session(0);
|
||||
EXPECT_EQ(strategy_session.discovery_phase_size(), 1);
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0).sent_connection_request_size(),
|
||||
3);
|
||||
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0)
|
||||
.sent_connection_request(0)
|
||||
.local_response(),
|
||||
IGNORED);
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0)
|
||||
.sent_connection_request(0)
|
||||
.remote_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0)
|
||||
.sent_connection_request(1)
|
||||
.local_response(),
|
||||
ACCEPTED);
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0)
|
||||
.sent_connection_request(1)
|
||||
.remote_response(),
|
||||
IGNORED);
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0)
|
||||
.sent_connection_request(2)
|
||||
.local_response(),
|
||||
IGNORED);
|
||||
EXPECT_EQ(strategy_session.discovery_phase(0)
|
||||
.sent_connection_request(2)
|
||||
.remote_response(),
|
||||
IGNORED);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace analytics
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
+6
-1
@@ -55,6 +55,7 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
|
||||
"//third_party/nearby_connections/cpp/analytics:__subpackages__",
|
||||
"//core:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
@@ -72,8 +73,12 @@ cc_library(
|
||||
hdrs = [
|
||||
"event_logger.h",
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/analytics:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//logs/proto/location/nearby:nearby_client_log_cc_proto",
|
||||
"//third_party/nearby_connections/proto/analytics:connections_log_cc_proto",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
#ifndef CORE_CORE_H_
|
||||
#define CORE_CORE_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "core/event_logger.h"
|
||||
#include "core/internal/client_proxy.h"
|
||||
#include "core/internal/service_controller.h"
|
||||
#include "core/internal/service_controller_router.h"
|
||||
@@ -34,6 +36,9 @@ namespace connections {
|
||||
class Core {
|
||||
public:
|
||||
explicit Core(ServiceControllerRouter* router);
|
||||
// Client needs to call this constructor if analytics logger is needed.
|
||||
Core(analytics::EventLogger* event_logger, ServiceControllerRouter* router)
|
||||
: client_(event_logger), router_(router) {}
|
||||
~Core();
|
||||
Core(Core&&);
|
||||
Core& operator=(Core&&);
|
||||
|
||||
@@ -15,11 +15,10 @@
|
||||
#ifndef CORE_EVENT_LOGGER_H_
|
||||
#define CORE_EVENT_LOGGER_H_
|
||||
|
||||
#include "logs/proto/location/nearby/nearby_client_log.proto.h"
|
||||
#include "proto/analytics/connections_log.proto.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace connections {
|
||||
namespace analytics {
|
||||
|
||||
// Allows callers to log |ConnectionsLog| collected at Nearby Connections
|
||||
@@ -30,11 +29,10 @@ class EventLogger {
|
||||
|
||||
// Logs |ConnectionsLog| details. Might block to do I/O, e.g. upload
|
||||
// synchronously to some metrics server.
|
||||
virtual void Log(const logs::ConnectionsLog& connections_log) = 0;
|
||||
virtual void Log(const proto::ConnectionsLog& connections_log) = 0;
|
||||
};
|
||||
|
||||
} // namespace analytics
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ cc_library(
|
||||
"//absl/strings",
|
||||
"//absl/time",
|
||||
"//absl/types:span",
|
||||
"//third_party/nearby_connections/cpp/analytics",
|
||||
"//core:core_types",
|
||||
"//core/internal/mediums",
|
||||
"//core/internal/mediums:utils",
|
||||
@@ -194,6 +195,7 @@ cc_test(
|
||||
"//absl/synchronization",
|
||||
"//absl/time",
|
||||
"//absl/types:span",
|
||||
"//third_party/nearby_connections/cpp/analytics",
|
||||
"//core:core_types",
|
||||
"//core/internal/mediums",
|
||||
"//core/internal/mediums:utils",
|
||||
|
||||
@@ -25,9 +25,11 @@
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "absl/types/span.h"
|
||||
#include "core/internal/mediums/utils.h"
|
||||
#include "core/internal/offline_frames.h"
|
||||
#include "core/internal/pcp_handler.h"
|
||||
#include "core/options.h"
|
||||
#include "platform/base/base64_utils.h"
|
||||
#include "platform/base/bluetooth_utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
#include "platform/public/system_clock.h"
|
||||
@@ -342,6 +344,7 @@ void BasePcpHandler::OnEncryptionSuccessRunnable(
|
||||
}
|
||||
|
||||
connection_info.SetCryptoContext(std::move(ukey2));
|
||||
connection_info.connection_token = GetHashedConnectionToken(raw_auth_token);
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Register encrypted connection; wait for response; endpoint_id="
|
||||
<< endpoint_id;
|
||||
@@ -382,7 +385,8 @@ void BasePcpHandler::OnEncryptionSuccessRunnable(
|
||||
.keep_alive_timeout_millis =
|
||||
connection_info.options.keep_alive_timeout_millis,
|
||||
},
|
||||
std::move(connection_info.channel), connection_info.listener);
|
||||
std::move(connection_info.channel), connection_info.listener,
|
||||
connection_info.connection_token);
|
||||
|
||||
if (auto future_status = connection_info.result.lock()) {
|
||||
NEARBY_LOGS(INFO) << "Connection established; Finalising future OK.";
|
||||
@@ -629,9 +633,12 @@ BasePcpHandler::GetDiscoveredEndpoints(
|
||||
return result;
|
||||
}
|
||||
|
||||
void BasePcpHandler::PendingConnectionInfo::SetCryptoContext(
|
||||
std::unique_ptr<UKey2Handshake> ukey2) {
|
||||
this->ukey2 = std::move(ukey2);
|
||||
mediums::PeerId BasePcpHandler::CreatePeerIdFromAdvertisement(
|
||||
const std::string& service_id, const std::string& endpoint_id,
|
||||
const ByteArray& endpoint_info) {
|
||||
std::string seed =
|
||||
absl::StrCat(service_id, endpoint_id, std::string(endpoint_info));
|
||||
return mediums::PeerId::FromSeed(ByteArray(std::move(seed)));
|
||||
}
|
||||
|
||||
bool BasePcpHandler::HasOutgoingConnections(ClientProxy* client) const {
|
||||
@@ -1415,8 +1422,21 @@ ExceptionOr<OfflineFrame> BasePcpHandler::ReadConnectionRequestFrame(
|
||||
return wrapped_frame;
|
||||
}
|
||||
|
||||
std::string BasePcpHandler::GetHashedConnectionToken(
|
||||
const ByteArray& token_bytes) {
|
||||
auto token = std::string(token_bytes);
|
||||
return location::nearby::Base64Utils::Encode(
|
||||
Utils::Sha256Hash(token, token.size()))
|
||||
.substr(0, kConnectionTokenLength);
|
||||
}
|
||||
|
||||
///////////////////// BasePcpHandler::PendingConnectionInfo ///////////////////
|
||||
|
||||
void BasePcpHandler::PendingConnectionInfo::SetCryptoContext(
|
||||
std::unique_ptr<UKey2Handshake> ukey2) {
|
||||
this->ukey2 = std::move(ukey2);
|
||||
}
|
||||
|
||||
BasePcpHandler::PendingConnectionInfo::~PendingConnectionInfo() {
|
||||
auto future_status = result.lock();
|
||||
if (future_status && !future_status->IsSet()) {
|
||||
@@ -1443,14 +1463,6 @@ void BasePcpHandler::PendingConnectionInfo::LocalEndpointRejectedConnection(
|
||||
client->LocalEndpointRejectedConnection(endpoint_id);
|
||||
}
|
||||
|
||||
mediums::PeerId BasePcpHandler::CreatePeerIdFromAdvertisement(
|
||||
const std::string& service_id, const std::string& endpoint_id,
|
||||
const ByteArray& endpoint_info) {
|
||||
std::string seed =
|
||||
absl::StrCat(service_id, endpoint_id, std::string(endpoint_info));
|
||||
return mediums::PeerId::FromSeed(ByteArray(std::move(seed)));
|
||||
}
|
||||
|
||||
} // namespace connections
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -348,6 +348,9 @@ class BasePcpHandler : public PcpHandler,
|
||||
// accepted. Crypto context is passed over to channel_manager_ before
|
||||
// switching to connected state, where Payload may be exchanged.
|
||||
std::unique_ptr<securegcm::UKey2Handshake> ukey2;
|
||||
|
||||
// Used in AnalyticsRecorder for devices connection tracking.
|
||||
std::string connection_token;
|
||||
};
|
||||
|
||||
// @EncryptionRunnerThread
|
||||
@@ -382,6 +385,7 @@ class BasePcpHandler : public PcpHandler,
|
||||
absl::Seconds(2);
|
||||
static constexpr absl::Duration kRejectedConnectionCloseDelay =
|
||||
absl::Seconds(2);
|
||||
static constexpr int kConnectionTokenLength = 8;
|
||||
|
||||
void OnConnectionResponse(ClientProxy* client, const std::string& endpoint_id,
|
||||
const OfflineFrame& frame);
|
||||
@@ -446,6 +450,10 @@ class BasePcpHandler : public PcpHandler,
|
||||
ExceptionOr<OfflineFrame> ReadConnectionRequestFrame(
|
||||
EndpointChannel* channel);
|
||||
|
||||
// Returns an 8 characters length hashed string generated via a token byte
|
||||
// array.
|
||||
std::string GetHashedConnectionToken(const ByteArray& token_bytes);
|
||||
|
||||
void WaitForLatch(const std::string& method_name, CountDownLatch* latch);
|
||||
Status WaitForResult(const std::string& method_name, std::int64_t client_id,
|
||||
Future<Status>* future);
|
||||
|
||||
@@ -15,7 +15,9 @@
|
||||
#include "core/internal/client_proxy.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
@@ -41,7 +43,12 @@ constexpr char kEndpointIdChars[] = {
|
||||
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
|
||||
ClientProxy::ClientProxy() : client_id_(Prng().NextInt64()) {}
|
||||
ClientProxy::ClientProxy(analytics::EventLogger* event_logger)
|
||||
: client_id_(Prng().NextInt64()) {
|
||||
NEARBY_LOGS(INFO) << "ClientProxy ctor event_logger=" << event_logger;
|
||||
analytics_recorder_ =
|
||||
std::make_unique<analytics::AnalyticsRecorder>(event_logger);
|
||||
}
|
||||
|
||||
ClientProxy::~ClientProxy() { Reset(); }
|
||||
|
||||
@@ -58,6 +65,14 @@ std::string ClientProxy::GetLocalEndpointId() {
|
||||
return local_endpoint_id_;
|
||||
}
|
||||
|
||||
std::string ClientProxy::GetConnectionToken(const std::string& endpoint_id) {
|
||||
Connection* item = LookupConnection(endpoint_id);
|
||||
if (item != nullptr) {
|
||||
return item->connection_token;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string ClientProxy::GenerateLocalEndpointId() {
|
||||
if (high_vis_mode_) {
|
||||
if (!local_high_vis_mode_cache_endpoint_id_.empty()) {
|
||||
@@ -82,6 +97,7 @@ void ClientProxy::Reset() {
|
||||
StoppedDiscovery();
|
||||
RemoveAllEndpoints();
|
||||
ExitHighVisibilityMode();
|
||||
analytics_recorder_->LogSession();
|
||||
}
|
||||
|
||||
void ClientProxy::StartedAdvertising(
|
||||
@@ -104,6 +120,10 @@ void ClientProxy::StartedAdvertising(
|
||||
|
||||
advertising_info_ = {service_id, listener};
|
||||
advertising_options_ = advertising_options;
|
||||
|
||||
const std::vector<proto::connections::Medium> medium_vector(mediums.begin(),
|
||||
mediums.end());
|
||||
analytics_recorder_->OnStartAdvertising(strategy, medium_vector);
|
||||
}
|
||||
|
||||
void ClientProxy::StoppedAdvertising() {
|
||||
@@ -113,6 +133,7 @@ void ClientProxy::StoppedAdvertising() {
|
||||
|
||||
if (IsAdvertising()) {
|
||||
advertising_info_.Clear();
|
||||
analytics_recorder_->OnStopAdvertising();
|
||||
}
|
||||
// advertising_options_ is purposefully not cleared here.
|
||||
ResetLocalEndpointIdIfNeeded();
|
||||
@@ -146,6 +167,10 @@ void ClientProxy::StartedDiscovery(
|
||||
MutexLock lock(&mutex_);
|
||||
discovery_info_ = DiscoveryInfo{service_id, listener};
|
||||
discovery_options_ = discovery_options;
|
||||
|
||||
const std::vector<proto::connections::Medium> medium_vector(mediums.begin(),
|
||||
mediums.end());
|
||||
analytics_recorder_->OnStartDiscovery(strategy, medium_vector);
|
||||
}
|
||||
|
||||
void ClientProxy::StoppedDiscovery() {
|
||||
@@ -154,6 +179,7 @@ void ClientProxy::StoppedDiscovery() {
|
||||
if (IsDiscovering()) {
|
||||
discovered_endpoint_ids_.clear();
|
||||
discovery_info_.Clear();
|
||||
analytics_recorder_->OnStopDiscovery();
|
||||
}
|
||||
// discovery_options_ is purposefully not cleared here.
|
||||
ResetLocalEndpointIdIfNeeded();
|
||||
@@ -203,6 +229,7 @@ void ClientProxy::OnEndpointFound(const std::string& service_id,
|
||||
discovered_endpoint_ids_.insert(endpoint_id);
|
||||
discovery_info_.listener.endpoint_found_cb(endpoint_id, endpoint_info,
|
||||
service_id);
|
||||
analytics_recorder_->OnEndpointFound(medium);
|
||||
}
|
||||
|
||||
void ClientProxy::OnEndpointLost(const std::string& service_id,
|
||||
@@ -234,7 +261,8 @@ void ClientProxy::OnEndpointLost(const std::string& service_id,
|
||||
void ClientProxy::OnConnectionInitiated(const std::string& endpoint_id,
|
||||
const ConnectionResponseInfo& info,
|
||||
const ConnectionOptions& options,
|
||||
const ConnectionListener& listener) {
|
||||
const ConnectionListener& listener,
|
||||
const std::string& connection_token) {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
// Whether this is incoming or outgoing, the local and remote endpoints both
|
||||
@@ -245,6 +273,7 @@ void ClientProxy::OnConnectionInitiated(const std::string& endpoint_id,
|
||||
.is_incoming = info.is_incoming_connection,
|
||||
.connection_listener = listener,
|
||||
.connection_options = options,
|
||||
.connection_token = connection_token,
|
||||
});
|
||||
// Instead of using structured binding which is nice, but banned
|
||||
// (can not use c++17 features, until chromium does) we unpack manually.
|
||||
@@ -265,6 +294,9 @@ void ClientProxy::OnConnectionInitiated(const std::string& endpoint_id,
|
||||
if (info.is_incoming_connection) {
|
||||
// Add CancellationFlag for advertisers once encryption succeeds.
|
||||
AddCancellationFlag(endpoint_id);
|
||||
analytics_recorder_->OnConnectionRequestReceived(endpoint_id);
|
||||
} else {
|
||||
analytics_recorder_->OnConnectionRequestSent(endpoint_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,6 +481,7 @@ void ClientProxy::LocalEndpointAcceptedConnection(
|
||||
if (item != nullptr) {
|
||||
item->payload_listener = listener;
|
||||
}
|
||||
analytics_recorder_->OnLocalEndpointAccepted(endpoint_id);
|
||||
}
|
||||
|
||||
void ClientProxy::LocalEndpointRejectedConnection(
|
||||
@@ -463,6 +496,7 @@ void ClientProxy::LocalEndpointRejectedConnection(
|
||||
}
|
||||
|
||||
AppendConnectionStatus(endpoint_id, Connection::kLocalEndpointRejected);
|
||||
analytics_recorder_->OnLocalEndpointRejected(endpoint_id);
|
||||
}
|
||||
|
||||
void ClientProxy::RemoteEndpointAcceptedConnection(
|
||||
@@ -477,6 +511,7 @@ void ClientProxy::RemoteEndpointAcceptedConnection(
|
||||
}
|
||||
|
||||
AppendConnectionStatus(endpoint_id, Connection::kRemoteEndpointAccepted);
|
||||
analytics_recorder_->OnRemoteEndpointAccepted(endpoint_id);
|
||||
}
|
||||
|
||||
void ClientProxy::RemoteEndpointRejectedConnection(
|
||||
@@ -491,6 +526,7 @@ void ClientProxy::RemoteEndpointRejectedConnection(
|
||||
}
|
||||
|
||||
AppendConnectionStatus(endpoint_id, Connection::kRemoteEndpointRejected);
|
||||
analytics_recorder_->OnRemoteEndpointRejected(endpoint_id);
|
||||
}
|
||||
|
||||
bool ClientProxy::IsConnectionAccepted(const std::string& endpoint_id) const {
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
#define CORE_INTERNAL_CLIENT_PROXY_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "third_party/nearby_connections/cpp/analytics/analytics_recorder.h"
|
||||
#include "core/listeners.h"
|
||||
#include "core/options.h"
|
||||
#include "core/status.h"
|
||||
@@ -46,7 +48,7 @@ class ClientProxy final {
|
||||
static constexpr absl::Duration
|
||||
kHighPowerAdvertisementEndpointIdCacheTimeout = absl::Seconds(30);
|
||||
|
||||
ClientProxy();
|
||||
explicit ClientProxy(analytics::EventLogger* event_logger = nullptr);
|
||||
~ClientProxy();
|
||||
ClientProxy(ClientProxy&&) = default;
|
||||
ClientProxy& operator=(ClientProxy&&) = default;
|
||||
@@ -55,6 +57,8 @@ class ClientProxy final {
|
||||
|
||||
std::string GetLocalEndpointId();
|
||||
|
||||
std::string GetConnectionToken(const std::string& endpoint_id);
|
||||
|
||||
// Clears all the runtime state of this client.
|
||||
void Reset();
|
||||
|
||||
@@ -98,7 +102,8 @@ class ClientProxy final {
|
||||
void OnConnectionInitiated(const std::string& endpoint_id,
|
||||
const ConnectionResponseInfo& info,
|
||||
const ConnectionOptions& options,
|
||||
const ConnectionListener& listener);
|
||||
const ConnectionListener& listener,
|
||||
const std::string& connection_token);
|
||||
|
||||
// Proxies to the client's ConnectionListener::OnAccepted() callback.
|
||||
void OnConnectionAccepted(const std::string& endpoint_id);
|
||||
@@ -205,6 +210,7 @@ class ClientProxy final {
|
||||
ConnectionListener connection_listener;
|
||||
PayloadListener payload_listener;
|
||||
ConnectionOptions connection_options;
|
||||
std::string connection_token;
|
||||
};
|
||||
|
||||
struct AdvertisingInfo {
|
||||
@@ -298,6 +304,10 @@ class ClientProxy final {
|
||||
// A default cancellation flag with isCancelled set be true.
|
||||
std::unique_ptr<CancellationFlag> default_cancellation_flag_ =
|
||||
std::make_unique<CancellationFlag>(true);
|
||||
|
||||
// An analytics logger with |EventLogger| provided by client, which is default
|
||||
// nullptr as no-op.
|
||||
std::unique_ptr<analytics::AnalyticsRecorder> analytics_recorder_;
|
||||
};
|
||||
|
||||
} // namespace connections
|
||||
|
||||
@@ -131,10 +131,11 @@ class ClientProxyTest : public ::testing::TestWithParam<FeatureFlags> {
|
||||
EXPECT_CALL(mock_discovery_connection_.initiated_cb, Call).Times(1);
|
||||
const std::string auth_token{"auth_token"};
|
||||
const ByteArray raw_auth_token{auth_token};
|
||||
const std::string connection_token{"conntokn"};
|
||||
advertising_connection_info_.remote_endpoint_info = endpoint.info;
|
||||
client->OnConnectionInitiated(endpoint.id, advertising_connection_info_,
|
||||
connection_options_,
|
||||
discovery_connection_listener_);
|
||||
client->OnConnectionInitiated(
|
||||
endpoint.id, advertising_connection_info_, connection_options_,
|
||||
discovery_connection_listener_, connection_token);
|
||||
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint.id));
|
||||
}
|
||||
|
||||
|
||||
@@ -353,7 +353,8 @@ void EndpointManager::RegisterEndpoint(ClientProxy* client,
|
||||
const ConnectionResponseInfo& info,
|
||||
const ConnectionOptions& options,
|
||||
std::unique_ptr<EndpointChannel> channel,
|
||||
const ConnectionListener& listener) {
|
||||
const ConnectionListener& listener,
|
||||
const std::string& connection_token) {
|
||||
CountDownLatch latch(1);
|
||||
|
||||
// NOTE (unique_ptr<> capture):
|
||||
@@ -366,6 +367,7 @@ void EndpointManager::RegisterEndpoint(ClientProxy* client,
|
||||
channel = channel.release(),
|
||||
&endpoint_id, &info,
|
||||
&options, &listener,
|
||||
&connection_token,
|
||||
&latch]() {
|
||||
if (endpoints_.contains(endpoint_id)) {
|
||||
NEARBY_LOGS(WARNING) << "Registering duplicate endpoint " << endpoint_id;
|
||||
@@ -440,7 +442,8 @@ void EndpointManager::RegisterEndpoint(ClientProxy* client,
|
||||
|
||||
// It's now time to let the client know of this new connection so that
|
||||
// they can accept or reject it.
|
||||
client->OnConnectionInitiated(endpoint_id, info, options, listener);
|
||||
client->OnConnectionInitiated(endpoint_id, info, options, listener,
|
||||
connection_token);
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
|
||||
@@ -103,7 +103,8 @@ class EndpointManager {
|
||||
const ConnectionResponseInfo& info,
|
||||
const ConnectionOptions& options,
|
||||
std::unique_ptr<EndpointChannel> channel,
|
||||
const ConnectionListener& listener);
|
||||
const ConnectionListener& listener,
|
||||
const std::string& connection_token);
|
||||
// Called when a client explicitly asks to disconnect from this endpoint. In
|
||||
// this case, we do not notify the client of onDisconnected().
|
||||
void UnregisterEndpoint(ClientProxy* client, const std::string& endpoint_id);
|
||||
|
||||
@@ -108,7 +108,7 @@ class EndpointManagerTest : public ::testing::Test {
|
||||
.WillRepeatedly(Return(start_time_));
|
||||
EXPECT_CALL(mock_listener_.initiated_cb, Call).Times(1);
|
||||
em_.RegisterEndpoint(&client_, endpoint_id_, info_, options_,
|
||||
std::move(channel), listener_);
|
||||
std::move(channel), listener_, connection_token);
|
||||
if (should_close) {
|
||||
EXPECT_TRUE(done.Await(absl::Milliseconds(1000)).result());
|
||||
}
|
||||
@@ -151,6 +151,7 @@ class EndpointManagerTest : public ::testing::Test {
|
||||
.bandwidth_changed_cb =
|
||||
mock_listener_.bandwidth_changed_cb.AsStdFunction(),
|
||||
};
|
||||
std::string connection_token = "conntokn";
|
||||
absl::Time start_time_{absl::Now()};
|
||||
};
|
||||
|
||||
|
||||
@@ -148,8 +148,9 @@ class ServiceControllerRouterTest : public testing::Test {
|
||||
.raw_authentication_token = ByteArray{"auth_token"},
|
||||
.is_incoming_connection = true,
|
||||
};
|
||||
std::string connection_token{"conntokn"};
|
||||
client->OnConnectionInitiated(endpoint_id, response_info, options,
|
||||
request_info.listener);
|
||||
request_info.listener, connection_token);
|
||||
EXPECT_TRUE(client->HasPendingConnectionToEndpoint(endpoint_id));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
|
||||
"//third_party/nearby_connections/cpp/analytics:__subpackages__",
|
||||
"//core:__subpackages__",
|
||||
"//platform:__subpackages__",
|
||||
"//platform/api:__subpackages__",
|
||||
|
||||
@@ -106,6 +106,7 @@ cc_library(
|
||||
"platform.cc",
|
||||
],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/analytics:__subpackages__",
|
||||
"//core:__subpackages__",
|
||||
"//platform:__subpackages__",
|
||||
],
|
||||
|
||||
@@ -50,6 +50,7 @@ cc_library(
|
||||
name = "comm",
|
||||
hdrs = [
|
||||
"ble.h",
|
||||
"bluetooth_adapter.h",
|
||||
"bluetooth_classic.h",
|
||||
"bluetooth_classic_device.h",
|
||||
"bluetooth_classic_medium.h",
|
||||
@@ -87,6 +88,7 @@ cc_library(
|
||||
cc_library(
|
||||
name = "windows",
|
||||
srcs = [
|
||||
"bluetooth_adapter.cc",
|
||||
"bluetooth_classic_device.cc",
|
||||
"bluetooth_classic_medium.cc",
|
||||
"bluetooth_classic_server_socket.cc",
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
// 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_adapter.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <winioctl.h>
|
||||
#include <bthdef.h>
|
||||
#include <bthioctl.h>
|
||||
#include <cfgmgr32.h>
|
||||
#include <devguid.h>
|
||||
#include <initguid.h>
|
||||
#include <objbase.h>
|
||||
#include <setupapi.h>
|
||||
#include <usbiodef.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Foundation.h"
|
||||
#include "platform/impl/windows/utils.h"
|
||||
#include "platform/public/logging.h"
|
||||
|
||||
typedef std::basic_string<TCHAR> tstring;
|
||||
|
||||
// IOCTL to get local radio information
|
||||
#define BTH_GET_DEVICE_INFO_IOCTL 0x411008
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothAdapter::BluetoothAdapter()
|
||||
: windows_bluetooth_adapter_(winrt::Windows::Devices::Bluetooth::
|
||||
BluetoothAdapter::GetDefaultAsync()
|
||||
.get()) {
|
||||
// Gets the radio represented by this Bluetooth adapter.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter.getradioasync?view=winrt-20348
|
||||
windows_bluetooth_radio_ = windows_bluetooth_adapter_.GetRadioAsync().get();
|
||||
}
|
||||
|
||||
// Synchronously sets the status of the BluetoothAdapter to 'status', and
|
||||
// returns true if the operation was a success.
|
||||
bool BluetoothAdapter::SetStatus(Status status) {
|
||||
if (status == Status::kDisabled) {
|
||||
// An asynchronous operation that attempts to set the state of the radio
|
||||
// represented by this object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radio.setstateasync?view=winrt-20348
|
||||
windows_bluetooth_radio_.SetStateAsync(RadioState::Off).get();
|
||||
} else {
|
||||
windows_bluetooth_radio_.SetStateAsync(RadioState::On).get();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if the BluetoothAdapter's current status is
|
||||
// Status::Value::kEnabled.
|
||||
bool BluetoothAdapter::IsEnabled() const {
|
||||
// Gets the current state of the radio represented by this object.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radio.state?view=winrt-20348
|
||||
return windows_bluetooth_radio_.State() == RadioState::On;
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode()
|
||||
//
|
||||
// Returns ScanMode::kUnknown on error.
|
||||
BluetoothAdapter::ScanMode BluetoothAdapter::GetScanMode() const {
|
||||
return scan_mode_;
|
||||
}
|
||||
|
||||
// Synchronously sets the scan mode of the adapter, and returns true if the
|
||||
// operation was a success.
|
||||
// TODO(jcarroll): Setup an event for this and hook the bluetooth medium into
|
||||
// the event to allow for updates.
|
||||
bool BluetoothAdapter::SetScanMode(ScanMode scan_mode) {
|
||||
scan_mode_ = scan_mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
|
||||
// Returns an empty string on error
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::string BluetoothAdapter::GetName() const { return "Un-implemented"; }
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
|
||||
bool BluetoothAdapter::SetName(absl::string_view name) {
|
||||
char *instanceID = GetGenericBluetoothAdapterInstanceID();
|
||||
|
||||
if (instanceID == NULL) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__ << ": Failed to get Generic Bluetooth Adapter InstanceID";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add 1 to length to get size (including null)
|
||||
char *instanceIDModified = new char[(strlen(instanceID) + 1) * sizeof(char)];
|
||||
|
||||
absl::SNPrintF(instanceIDModified,
|
||||
size_t((strlen(instanceID) + 1) * sizeof(char)), "%s",
|
||||
instanceID);
|
||||
|
||||
find_and_replace(instanceIDModified, "\\", "#");
|
||||
|
||||
HANDLE hDevice;
|
||||
char fileName[1024] = {0};
|
||||
|
||||
// defined in usbiodef.h
|
||||
const GUID guid = GUID_DEVINTERFACE_USB_DEVICE;
|
||||
|
||||
OLECHAR guidOleStr[64];
|
||||
int oleBufferLen = 64;
|
||||
|
||||
char guidStr[64];
|
||||
int bufferLen = 64;
|
||||
BOOL defaultCharUsed;
|
||||
|
||||
// Converts a globally unique identifier (GUID) into a string of printable
|
||||
// characters.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-stringfromguid2
|
||||
auto conversionResult = StringFromGUID2(guid, guidOleStr, bufferLen);
|
||||
|
||||
if (conversionResult == 0) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to convert guid to string";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Maps a UTF-16 (wide character) string to a new character string. The new
|
||||
// character string is not necessarily from a multibyte character set.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-widechartomultibyte
|
||||
conversionResult =
|
||||
WideCharToMultiByte(CP_UTF8, 0, guidOleStr, oleBufferLen, guidStr,
|
||||
bufferLen, NULL, &defaultCharUsed);
|
||||
|
||||
if (conversionResult != 0) {
|
||||
const char *errorResult = {};
|
||||
|
||||
switch (conversionResult) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
errorResult =
|
||||
"A supplied buffer size was not large enough, or it was "
|
||||
"incorrectly set to NULL.";
|
||||
break;
|
||||
case ERROR_INVALID_FLAGS:
|
||||
errorResult = "The values supplied for flags were not valid.";
|
||||
break;
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
errorResult = "Any of the parameter values was invalid.";
|
||||
break;
|
||||
case ERROR_NO_UNICODE_TRANSLATION:
|
||||
errorResult = "Invalid Unicode was found in a string.";
|
||||
break;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to convert guid to string "
|
||||
<< errorResult;
|
||||
}
|
||||
|
||||
absl::SNPrintF(fileName, sizeof(fileName), "\\\\.\\%s%s#%s", fileName,
|
||||
instanceIDModified, guidStr);
|
||||
|
||||
// Creates or opens a file or I/O device.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
|
||||
hDevice =
|
||||
CreateFileA(fileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
delete[] instanceIDModified;
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to open device. Error code: "
|
||||
<< GetLastError();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change radio module local name in registry
|
||||
HKEY hKey;
|
||||
char rmLocalNameKey[1024] = {0};
|
||||
LSTATUS ret;
|
||||
|
||||
absl::SNPrintF(rmLocalNameKey, sizeof(rmLocalNameKey),
|
||||
"SYSTEM\\ControlSet001\\Enum\\%s\\Device Parameters",
|
||||
instanceID);
|
||||
|
||||
// Opens the specified registry key. Note that key names are not case
|
||||
// sensitive.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexa
|
||||
ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, rmLocalNameKey, 0L, KEY_SET_VALUE,
|
||||
&hKey);
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to open registry key. Error code: " << ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sets the data and type of a specified value under a registry key.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexa
|
||||
ret = RegSetValueExA(hKey, "Local Name", 0, REG_BINARY,
|
||||
(LPBYTE)std::string(name).c_str(),
|
||||
strlen(std::string(name).c_str()));
|
||||
|
||||
if (ret != ERROR_SUCCESS) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to set registry key. Error code: " << ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Closes a handle to the specified registry key.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
|
||||
RegCloseKey(hKey);
|
||||
|
||||
// tells the control function to reset or reload or similar...
|
||||
int32 reload = 4;
|
||||
// merely a placeholder
|
||||
DWORD bytes = 0;
|
||||
|
||||
// Send radio module driver command to update device information
|
||||
// Sends a control code directly to a specified device driver, causing the
|
||||
// corresponding device to perform the corresponding operation.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol
|
||||
if (!DeviceIoControl(hDevice, BTH_GET_DEVICE_INFO_IOCTL, &reload, 4, NULL, 0,
|
||||
&bytes, NULL)) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to update radio module local name. Error code: "
|
||||
<< GetLastError();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BluetoothAdapter::find_and_replace(char *source, const char *strFind,
|
||||
const char *strReplace) {
|
||||
std::string s = std::string(source);
|
||||
std::string f = std::string(strFind);
|
||||
std::string r = std::string(strReplace);
|
||||
size_t j;
|
||||
|
||||
for (; (j = s.find(f)) != std::string::npos;) {
|
||||
s.replace(j, f.length(), r);
|
||||
}
|
||||
|
||||
memcpy(source, s.c_str(), s.size());
|
||||
}
|
||||
|
||||
char *BluetoothAdapter::GetGenericBluetoothAdapterInstanceID(void) {
|
||||
unsigned i;
|
||||
CONFIGRET r;
|
||||
HDEVINFO hDevInfo;
|
||||
SP_DEVINFO_DATA DeviceInfoData;
|
||||
char *deviceInstanceID = new char[MAX_DEVICE_ID_LEN];
|
||||
|
||||
// Find all bluetooth radio modules
|
||||
// The SetupDiGetClassDevs function returns a handle to a device information
|
||||
// set that contains requested device information elements for a local
|
||||
// computer.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdigetclassdevsa
|
||||
hDevInfo =
|
||||
SetupDiGetClassDevsA(&GUID_DEVCLASS_BLUETOOTH, NULL, NULL, DIGCF_PRESENT);
|
||||
|
||||
if (hDevInfo == INVALID_HANDLE_VALUE) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Could not find BluetoothDevice on this machine";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get first Generic Bluetooth Adapter InstanceID
|
||||
for (i = 0;; i++) {
|
||||
DeviceInfoData.cbSize = sizeof(DeviceInfoData);
|
||||
|
||||
// The SetupDiEnumDeviceInfo function returns a SP_DEVINFO_DATA structure
|
||||
// that specifies a device information element in a device information set.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/setupapi/nf-setupapi-setupdienumdeviceinfo
|
||||
if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData)) break;
|
||||
|
||||
// The CM_Get_Device_ID function retrieves the device instance ID for a
|
||||
// specified device instance on the local machine.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/cfgmgr32/nf-cfgmgr32-cm_get_device_ida
|
||||
r = CM_Get_Device_IDA(DeviceInfoData.DevInst, deviceInstanceID,
|
||||
MAX_DEVICE_ID_LEN, 0);
|
||||
|
||||
if (r != CR_SUCCESS) continue;
|
||||
|
||||
// With Windows, a Bluetooth radio can be packaged as an external dongle or
|
||||
// embedded inside a computer but it must be connected to one of the
|
||||
// computer's USB ports.
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/bluetooth/bluetooth-host-radio-support
|
||||
if (strncmp("USB", deviceInstanceID, 3) == 0) {
|
||||
return deviceInstanceID;
|
||||
}
|
||||
}
|
||||
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to get the generic bluetooth adapter id";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns BT MAC address assigned to this adapter.
|
||||
std::string BluetoothAdapter::GetMacAddress() const {
|
||||
return uint64_to_mac_address_string(
|
||||
windows_bluetooth_adapter_.BluetoothAddress());
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
@@ -18,47 +18,67 @@
|
||||
#include <string>
|
||||
|
||||
#include "platform/api/bluetooth_adapter.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Bluetooth.h"
|
||||
#include "platform/impl/windows/generated/winrt/Windows.Devices.Radios.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
|
||||
// Represents a Bluetooth adapter.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter?view=winrt-20348
|
||||
using winrt::Windows::Devices::Bluetooth::IBluetoothAdapter;
|
||||
|
||||
// Represents a radio device on the system.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radio?view=winrt-20348
|
||||
using winrt::Windows::Devices::Radios::IRadio;
|
||||
|
||||
// Enumeration that describes possible radio states.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.radios.radiostate?view=winrt-20348
|
||||
using winrt::Windows::Devices::Radios::RadioState;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
|
||||
class BluetoothAdapter : public api::BluetoothAdapter {
|
||||
public:
|
||||
BluetoothAdapter();
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
~BluetoothAdapter() override = default;
|
||||
|
||||
// Synchronously sets the status of the BluetoothAdapter to 'status', and
|
||||
// returns true if the operation was a success.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
bool SetStatus(Status status) override { return false; }
|
||||
bool SetStatus(Status status) override;
|
||||
// Returns true if the BluetoothAdapter's current status is
|
||||
// Status::Value::kEnabled.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
bool IsEnabled() const override { return false; }
|
||||
bool IsEnabled() const override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getScanMode()
|
||||
//
|
||||
// Returns ScanMode::kUnknown on error.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
ScanMode GetScanMode() const override { return ScanMode::kUnknown; }
|
||||
ScanMode GetScanMode() const override;
|
||||
// Synchronously sets the scan mode of the adapter, and returns true if the
|
||||
// operation was a success.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
bool SetScanMode(ScanMode scan_mode) override { return false; }
|
||||
bool SetScanMode(ScanMode scan_mode) override;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#getName()
|
||||
// Returns an empty string on error
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::string GetName() const override { return "Un-implemented"; }
|
||||
std::string GetName() const override;
|
||||
// https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#setName(java.lang.String)
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
bool SetName(absl::string_view name) override { return false; }
|
||||
bool SetName(absl::string_view name) override;
|
||||
|
||||
// Returns BT MAC address assigned to this adapter.
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
std::string GetMacAddress() const override { return "Un-implemented"; }
|
||||
std::string GetMacAddress() const override;
|
||||
|
||||
private:
|
||||
IBluetoothAdapter
|
||||
windows_bluetooth_adapter_;
|
||||
|
||||
IRadio windows_bluetooth_radio_;
|
||||
char *GetGenericBluetoothAdapterInstanceID(void);
|
||||
void find_and_replace(char *source, const char *strFind,
|
||||
const char *strReplace);
|
||||
ScanMode scan_mode_ = ScanMode::kNone;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#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"
|
||||
@@ -36,7 +37,10 @@ namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
BluetoothClassicMedium::BluetoothClassicMedium() {
|
||||
BluetoothClassicMedium::BluetoothClassicMedium(
|
||||
const api::BluetoothAdapter& bluetoothAdapter)
|
||||
: bluetooth_adapter_(
|
||||
dynamic_cast<const BluetoothAdapter&>(bluetoothAdapter)) {
|
||||
InitializeCriticalSection(&critical_section_);
|
||||
|
||||
InitializeDeviceWatcher();
|
||||
@@ -253,7 +257,12 @@ BluetoothClassicMedium::ListenForService(const std::string& service_name,
|
||||
auto bluetooth_server_socket =
|
||||
std::make_unique<location::nearby::windows::BluetoothServerSocket>();
|
||||
|
||||
bluetooth_server_socket->StartListening(service_name, service_uuid);
|
||||
bool radioDiscoverable =
|
||||
bluetooth_adapter_.GetScanMode() ==
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable;
|
||||
|
||||
bluetooth_server_socket->StartListening(service_name, service_uuid,
|
||||
radioDiscoverable);
|
||||
|
||||
return std::move(bluetooth_server_socket);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#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/bluetooth_adapter.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"
|
||||
@@ -86,7 +87,8 @@ using winrt::Windows::Storage::Streams::DataWriter;
|
||||
// medium.
|
||||
class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
public:
|
||||
explicit BluetoothClassicMedium();
|
||||
BluetoothClassicMedium() = default;
|
||||
BluetoothClassicMedium(const api::BluetoothAdapter& bluetoothAdapter);
|
||||
|
||||
~BluetoothClassicMedium() override;
|
||||
|
||||
@@ -176,6 +178,8 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
// 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_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
BluetoothServerSocket::BluetoothServerSocket() {
|
||||
BluetoothServerSocket::BluetoothServerSocket() : rfcomm_provider_(nullptr) {
|
||||
InitializeCriticalSection(&critical_section_);
|
||||
}
|
||||
|
||||
@@ -61,8 +61,9 @@ std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Exception BluetoothServerSocket::StartListening(
|
||||
const std::string& service_name, const std::string& service_uuid) {
|
||||
Exception BluetoothServerSocket::StartListening(const std::string& service_name,
|
||||
const std::string& service_uuid,
|
||||
bool radioDiscoverable) {
|
||||
EnterCriticalSection(&critical_section_);
|
||||
|
||||
winrt::guid service(service_uuid);
|
||||
@@ -121,7 +122,7 @@ Exception BluetoothServerSocket::StartListening(
|
||||
|
||||
try {
|
||||
rfcomm_provider_->StartAdvertising(
|
||||
stream_socket_listener_.as<StreamSocketListener>(), true);
|
||||
stream_socket_listener_.as<StreamSocketListener>(), radioDiscoverable);
|
||||
} catch (std::exception exception) {
|
||||
// We will log and eat the exception since the caller
|
||||
// expects nullptr if it fails
|
||||
|
||||
@@ -88,7 +88,8 @@ class BluetoothServerSocket : public api::BluetoothServerSocket {
|
||||
Exception Close() override;
|
||||
|
||||
Exception StartListening(const std::string& service_name,
|
||||
const std::string& service_uuid);
|
||||
const std::string& service_uuid,
|
||||
bool radioDiscoverable);
|
||||
|
||||
private:
|
||||
void InitializeServiceSdpAttributes(RfcommServiceProvider rfcommProvider,
|
||||
|
||||
@@ -30,6 +30,8 @@ cc_library(
|
||||
"uuid.lib",
|
||||
"winmm.lib",
|
||||
"winspool.lib",
|
||||
"comsuppwd.lib",
|
||||
"setupapi.lib",
|
||||
],
|
||||
textual_hdrs = glob(["**/*.h"]),
|
||||
visibility = [
|
||||
|
||||
@@ -122,7 +122,8 @@ ImplementationPlatform::CreateBluetoothAdapter() {
|
||||
std::unique_ptr<BluetoothClassicMedium>
|
||||
ImplementationPlatform::CreateBluetoothClassicMedium(
|
||||
BluetoothAdapter& adapter) {
|
||||
return absl::make_unique<location::nearby::windows::BluetoothClassicMedium>();
|
||||
return absl::make_unique<location::nearby::windows::BluetoothClassicMedium>(
|
||||
adapter);
|
||||
}
|
||||
|
||||
// TODO(b/184975123): replace with real implementation.
|
||||
|
||||
@@ -52,6 +52,7 @@ cc_library(
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//googlemac/iPhone/Shared/Nearby/Connections:__subpackages__",
|
||||
"//third_party/nearby_connections/cpp/analytics:__subpackages__",
|
||||
"//core:__subpackages__",
|
||||
"//platform/base:__pkg__",
|
||||
"//platform/impl/windows:__subpackages__",
|
||||
@@ -110,6 +111,7 @@ cc_library(
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections/cpp/analytics:__subpackages__",
|
||||
"//core:__subpackages__",
|
||||
"//platform:__subpackages__",
|
||||
],
|
||||
|
||||
@@ -0,0 +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.
|
||||
|
||||
load("//tools/build_defs/proto/cpp:cc_proto_library.bzl", "cc_proto_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
proto_library(
|
||||
name = "connections_log_proto",
|
||||
srcs = [
|
||||
"connections_log.proto",
|
||||
],
|
||||
cc_api_version = 2,
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
deps = [
|
||||
"//storage/datapol/annotations/proto:datapol_annotations",
|
||||
"//proto:connections_enums_proto",
|
||||
"//third_party/nearby_connections/proto/errorcode:error_code_enums_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_proto_library(
|
||||
name = "connections_log_cc_proto",
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
"//third_party/nearby_connections:__subpackages__",
|
||||
],
|
||||
deps = [":connections_log_proto"],
|
||||
)
|
||||
|
||||
java_lite_proto_library(
|
||||
name = "connections_log_java_proto_lite",
|
||||
deps = [":connections_log_proto"],
|
||||
)
|
||||
@@ -0,0 +1,357 @@
|
||||
// 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package location.nearby.analytics.proto;
|
||||
|
||||
import "storage/datapol/annotations/proto/semantic_annotations.proto";
|
||||
import "third_party/nearby_connections/proto/connections_enums.proto";
|
||||
import "third_party/nearby_connections/proto/errorcode/error_code_enums.proto";
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_package = "com.google.location.nearby.analytics.proto";
|
||||
option java_outer_classname = "ConnectionsLogProto";
|
||||
option objc_class_prefix = "GNCP";
|
||||
|
||||
// Top-level log proto for Nearby Connections.
|
||||
// LINT.IfChange(ConnectionsLog)
|
||||
message ConnectionsLog {
|
||||
// The type of this log.
|
||||
optional location.nearby.proto.connections.EventType event_type = 1;
|
||||
|
||||
// Non-null for EventType.CLIENT_SESSION.
|
||||
// Encapsulates all client activity between connecting to and disconnecting
|
||||
// from the Nearby Connections API via Client.
|
||||
optional ClientSession client_session = 2;
|
||||
|
||||
// The version of Nearby Connections. E.g. "v1.0.4".
|
||||
optional string version = 3 [(datapol.semantic_type) = ST_SOFTWARE_ID];
|
||||
|
||||
// for EventType.ERROR_CODE
|
||||
optional ErrorCode error_code = 4;
|
||||
|
||||
// Encapsulates one session of a client connected to Nearby Connections API.
|
||||
message ClientSession {
|
||||
// Elapsed time in milliseconds between Client connect and
|
||||
// disconnect.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// Zero or more StrategySessions.
|
||||
repeated StrategySession strategy_session = 2;
|
||||
}
|
||||
|
||||
// One round of a particular Strategy done by a client.
|
||||
message StrategySession {
|
||||
// Elapsed time in milliseconds between a call to startAdvertising/Discovery
|
||||
// and the end of this particular Strategy. A StrategySession may end due to
|
||||
// - the client disconnecting from Client;
|
||||
// - a call to stopAllEndpoints, which disconnects all endpoints and
|
||||
// stops any advertising/discovery;
|
||||
// - a new call to startAdvertising/Discovery.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// The Strategy used for this session.
|
||||
optional location.nearby.proto.connections.ConnectionsStrategy strategy = 2;
|
||||
|
||||
// The role(s) played by this device during this StrategySession.
|
||||
repeated location.nearby.proto.connections.SessionRole role = 3;
|
||||
|
||||
// One or more of the following *Phase is present, depending on the role(s).
|
||||
|
||||
// Encapsulates discovery information.
|
||||
repeated DiscoveryPhase discovery_phase = 4;
|
||||
// Encapsulates advertising information.
|
||||
repeated AdvertisingPhase advertising_phase = 5;
|
||||
|
||||
// Attempts at establishing a connection to another device.
|
||||
repeated ConnectionAttempt connection_attempt = 6;
|
||||
|
||||
// Successful and accepted connections to another device.
|
||||
repeated EstablishedConnection established_connection = 7;
|
||||
|
||||
// Attempts to upgrade a connection from one medium to another.
|
||||
repeated BandwidthUpgradeAttempt upgrade_attempt = 9;
|
||||
}
|
||||
|
||||
// Encapsulates activity during a period of discovery.
|
||||
message DiscoveryPhase {
|
||||
// Elapsed time in milliseconds between startDiscovery and stopDiscovery.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// The Medium(s) used for discovery.
|
||||
repeated location.nearby.proto.connections.Medium medium = 2;
|
||||
|
||||
// Discovered endpoints during this round of discovery.
|
||||
repeated DiscoveredEndpoint discovered_endpoint = 3;
|
||||
|
||||
// Attempted ConnectionRequests (requested by the client). They may or
|
||||
// may not reach the other endpoint.
|
||||
repeated ConnectionRequest sent_connection_request = 4;
|
||||
|
||||
// UWB ranging related data during discovery (May range with multiple
|
||||
// endpoints)
|
||||
repeated UwbRangingProcess uwb_ranging = 5;
|
||||
|
||||
// The SendingEvent flow id.
|
||||
optional int64 client_flow_id = 6 [(datapol.semantic_type) = ST_SESSION_ID];
|
||||
}
|
||||
|
||||
// An endpoint discovered on a particular medium during discovery.
|
||||
message DiscoveredEndpoint {
|
||||
// The medium on which this endpoint was discovered.
|
||||
optional location.nearby.proto.connections.Medium medium = 1;
|
||||
|
||||
// Elapsed time between the call to startDiscovery() and the time at which
|
||||
// this endpoint was discovered.
|
||||
optional int64 latency_millis = 2;
|
||||
}
|
||||
|
||||
// Encapsulates activity during UWB ranging.
|
||||
message UwbRangingProcess {
|
||||
// Elapsed time in milliseconds between startRanging and stopRanging.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// UWB raw ranging data received during discovery. This is optional. Only
|
||||
// certain devices (Debug/Testing etc.) will log the raw data.
|
||||
repeated RawUwbRangingEvent uwb_ranging_data = 2;
|
||||
|
||||
// Number of ranging data received
|
||||
optional int32 number_of_ranging_data = 3;
|
||||
|
||||
// The minimum distance during a UWB ranging session
|
||||
optional int32 distance_min = 4;
|
||||
|
||||
// The maximum distance during a UWB ranging session
|
||||
optional int32 distance_max = 5;
|
||||
|
||||
// The average distance during a UWB ranging session
|
||||
optional int32 distance_ave = 6;
|
||||
|
||||
// The distance variance during a UWB ranging session
|
||||
optional int32 distance_variance = 7;
|
||||
|
||||
// The minimum AoA during a UWB ranging session
|
||||
optional int32 azimuth_min = 8;
|
||||
|
||||
// The maximum AoA during a UWB ranging session
|
||||
optional int32 azimuth_max = 9;
|
||||
|
||||
// The average AoA during a UWB ranging session
|
||||
optional int32 azimuth_ave = 10;
|
||||
|
||||
// The AoA variance during a UWB ranging session
|
||||
optional int32 azimuth_variance = 11;
|
||||
}
|
||||
|
||||
// Ranging data received during discovery phase.
|
||||
message RawUwbRangingEvent {
|
||||
// Distance in cm
|
||||
optional int32 distance = 1;
|
||||
|
||||
// Azimuth angle in degree
|
||||
optional int32 azimuth_angle = 2;
|
||||
|
||||
// Polar angle in degree (0 if the device doesn't support it)
|
||||
optional int32 polar_angle = 3;
|
||||
}
|
||||
|
||||
// Encapsulates activity during a period of advertising.
|
||||
message AdvertisingPhase {
|
||||
// Elapsed time in milliseconds between startAdvertising and
|
||||
// stopAdvertising.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// The Medium(s) used for advertising.
|
||||
repeated location.nearby.proto.connections.Medium medium = 2;
|
||||
|
||||
// Received ConnectionRequests from remote endpoints.
|
||||
repeated ConnectionRequest received_connection_request = 3;
|
||||
|
||||
// The ReceivingEvent flow id.
|
||||
optional int64 client_flow_id = 4 [(datapol.semantic_type) = ST_SESSION_ID];
|
||||
}
|
||||
|
||||
// A request to connect, corresponding to the API's concept of
|
||||
// request/accept/rejectConnection().
|
||||
message ConnectionRequest {
|
||||
// Elapsed time in milliseconds between the connection request being
|
||||
// initiated and the responses being received.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// Elapsed time in milliseconds between the start of the containing
|
||||
// Advertising/DiscoveryPhase and the start of this ConnectionRequest, i.e.
|
||||
// the time at which the request is sent (on the discoverer, at the request
|
||||
// of the client) or received (on the advertiser, over the wire from the
|
||||
// remote endpoint).
|
||||
optional int64 request_delay_millis = 2;
|
||||
|
||||
// The local endpoint's response to this connection request.
|
||||
optional location.nearby.proto.connections.ConnectionRequestResponse
|
||||
local_response = 3;
|
||||
|
||||
// The remote endpoint's response to this connection request.
|
||||
optional location.nearby.proto.connections.ConnectionRequestResponse
|
||||
remote_response = 4;
|
||||
|
||||
// The SendingEvent flow id.
|
||||
optional int64 client_flow_id = 5 [(datapol.semantic_type) = ST_SESSION_ID];
|
||||
}
|
||||
|
||||
// An attempt to connect to an endpoint over a particular medium.
|
||||
message ConnectionAttempt {
|
||||
// Elapsed time in milliseconds between starting the connection attempt
|
||||
// and succeeding/failing.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// The type of connection attempt.
|
||||
optional location.nearby.proto.connections.ConnectionAttemptType type = 2;
|
||||
|
||||
// The direction (incoming vs outgoing) of this attempt.
|
||||
optional location.nearby.proto.connections.ConnectionAttemptDirection
|
||||
direction = 3;
|
||||
|
||||
// The Medium of this connection attempt.
|
||||
optional location.nearby.proto.connections.Medium medium = 4;
|
||||
|
||||
// The result of the connection attempt.
|
||||
optional location.nearby.proto.connections.ConnectionAttemptResult
|
||||
attempt_result = 5;
|
||||
|
||||
// The ReceivingEvent flow id.
|
||||
optional int64 client_flow_id = 6 [(datapol.semantic_type) = ST_SESSION_ID];
|
||||
|
||||
// The token used to identify this connection pair.
|
||||
optional string connection_token = 7
|
||||
[(datapol.semantic_type) = ST_SESSION_ID];
|
||||
}
|
||||
|
||||
// A successfully-established connection over a particular medium.
|
||||
message EstablishedConnection {
|
||||
// Elapsed time in milliseconds that the connection is active.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// The Medium of this connection.
|
||||
optional location.nearby.proto.connections.Medium medium = 2;
|
||||
|
||||
// Payloads sent over this connection.
|
||||
repeated Payload sent_payload = 3;
|
||||
|
||||
// Payloads received over this connection.
|
||||
repeated Payload received_payload = 4;
|
||||
|
||||
// The reason this connection was disconnected.
|
||||
optional location.nearby.proto.connections.DisconnectionReason
|
||||
disconnection_reason = 5;
|
||||
|
||||
// The SendingEvent flow id.
|
||||
optional int64 client_flow_id = 6 [(datapol.semantic_type) = ST_SESSION_ID];
|
||||
|
||||
// The token use to identify this established connection.
|
||||
optional string connection_token = 7
|
||||
[(datapol.semantic_type) = ST_SESSION_ID];
|
||||
}
|
||||
|
||||
// A Payload transferred (or attempted to be transferred) between devices.
|
||||
message Payload {
|
||||
// Elapsed time in milliseconds that num_bytes_transferred took to transfer.
|
||||
optional int64 duration_millis = 1;
|
||||
|
||||
// The type of this payload.
|
||||
optional location.nearby.proto.connections.PayloadType type = 2;
|
||||
|
||||
// Total size of the payload in bytes.
|
||||
optional int64 total_size_bytes = 3;
|
||||
|
||||
// Total number of bytes transferred successfully.
|
||||
optional int64 num_bytes_transferred = 4;
|
||||
|
||||
// The number of chunks used to transfer num_bytes_transferred.
|
||||
optional int32 num_chunks = 5;
|
||||
|
||||
// The end status of the payload transfer.
|
||||
optional location.nearby.proto.connections.PayloadStatus status = 6;
|
||||
}
|
||||
|
||||
// An attempt to upgrade an existing connection from one medium to another.
|
||||
message BandwidthUpgradeAttempt {
|
||||
// The direction (incoming vs outgoing) of the upgrade attempt.
|
||||
optional location.nearby.proto.connections.ConnectionAttemptDirection
|
||||
direction = 1;
|
||||
|
||||
// Elapsed time in milliseconds of the upgrade attempt.
|
||||
optional int64 duration_millis = 2;
|
||||
|
||||
// The original medium (e.g. bluetooth).
|
||||
optional location.nearby.proto.connections.Medium from_medium = 3;
|
||||
|
||||
// The new medium that we're hoping to upgrade to (e.g. wifi).
|
||||
optional location.nearby.proto.connections.Medium to_medium = 4;
|
||||
|
||||
// The result of the upgrade attempt.
|
||||
optional location.nearby.proto.connections.BandwidthUpgradeResult
|
||||
upgrade_result = 5;
|
||||
|
||||
// If upgrade_result is not success, the stage at which the error occurred.
|
||||
optional location.nearby.proto.connections.BandwidthUpgradeErrorStage
|
||||
error_stage = 6;
|
||||
|
||||
// The SendingEvent flow id.
|
||||
optional int64 client_flow_id = 7 [(datapol.semantic_type) = ST_SESSION_ID];
|
||||
|
||||
// The token used to identify this upgrade pair.
|
||||
optional string connection_token = 8
|
||||
[(datapol.semantic_type) = ST_SESSION_ID];
|
||||
}
|
||||
|
||||
// Next Id: 17
|
||||
message ErrorCode {
|
||||
// The direction (incoming vs outgoing) of this error.
|
||||
optional location.nearby.proto.connections.ConnectionAttemptDirection
|
||||
direction = 1;
|
||||
optional string service_id = 2;
|
||||
// The error medium (e.g. bluetooth).
|
||||
optional location.nearby.proto.connections.Medium medium = 3;
|
||||
// The event which the error occurs on.
|
||||
optional location.nearby.errorcode.proto.Event event = 4;
|
||||
// The error description.
|
||||
optional location.nearby.errorcode.proto.Description description = 5;
|
||||
// The flow id which the error occurs on.
|
||||
optional int64 flow_id = 6 [(datapol.semantic_type) = ST_SESSION_ID];
|
||||
|
||||
// Error code value
|
||||
oneof ErrorCodeDetail {
|
||||
location.nearby.errorcode.proto.CommonError common_error = 7;
|
||||
location.nearby.errorcode.proto.StartAdvertisingError
|
||||
start_advertising_error = 8;
|
||||
location.nearby.errorcode.proto.StartDiscoveringError
|
||||
start_discovering_error = 9;
|
||||
location.nearby.errorcode.proto.StopAdvertisingError
|
||||
stop_advertising_error = 10;
|
||||
location.nearby.errorcode.proto.StopDiscoveringError
|
||||
stop_discovering_error = 11;
|
||||
location.nearby.errorcode.proto.StartListeningIncomingConnectionError
|
||||
start_listening_incoming_connection_error = 12;
|
||||
location.nearby.errorcode.proto.StopListeningIncomingConnectionError
|
||||
stop_listening_incoming_connection_error = 13;
|
||||
location.nearby.errorcode.proto.ConnectError connect_error = 14;
|
||||
location.nearby.errorcode.proto.DisconnectError disconnect_error = 15;
|
||||
}
|
||||
|
||||
// The token use to identify this established connection.
|
||||
optional string connection_token = 16
|
||||
[(datapol.semantic_type) = ST_SESSION_ID];
|
||||
}
|
||||
}
|
||||
// LINT.ThenChange()
|
||||
@@ -303,6 +303,12 @@ message MediumMetadata {
|
||||
optional AvailableChannels available_channels = 7;
|
||||
// Usable WiFi Direct client channels on the local device.
|
||||
optional WifiDirectCliUsableChannels wifi_direct_cli_usable_channels = 8;
|
||||
// Usable WiFi LAN channels on the local device.
|
||||
optional WifiLanUsableChannels wifi_lan_usable_channels = 9;
|
||||
// Usable WiFi Aware channels on the local device.
|
||||
optional WifiAwareUsableChannels wifi_aware_usable_channels = 10;
|
||||
// Usable WiFi Hotspot STA channels on the local device.
|
||||
optional WifiHotspotStaUsableChannels wifi_hotspot_sta_usable_channels = 11;
|
||||
}
|
||||
|
||||
// Available channels on the local device.
|
||||
@@ -315,6 +321,21 @@ message WifiDirectCliUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Usable WiFi LAN channels on the local device.
|
||||
message WifiLanUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Usable WiFi Aware channels on the local device.
|
||||
message WifiAwareUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Usable WiFi Hotspot STA channels on the local device.
|
||||
message WifiHotspotStaUsableChannels {
|
||||
repeated int32 channels = 1 [packed = true];
|
||||
}
|
||||
|
||||
// LocationHint is used to specify a location as well as format.
|
||||
message LocationHint {
|
||||
// Location is the location, provided in the format specified by format.
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# 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.
|
||||
|
||||
# Proto for Nearby products
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
proto_library(
|
||||
name = "error_code_enums_proto",
|
||||
srcs = ["error_code_enums.proto"],
|
||||
cc_api_version = 2,
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
deps = [
|
||||
"//logs/proto/logs_annotations",
|
||||
],
|
||||
)
|
||||
|
||||
java_lite_proto_library(
|
||||
name = "error_code_enums_java_proto_lite",
|
||||
deps = [":error_code_enums_proto"],
|
||||
)
|
||||
@@ -0,0 +1,500 @@
|
||||
// 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.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package location.nearby.errorcode.proto;
|
||||
|
||||
|
||||
|
||||
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
option java_package = "com.google.location.nearby.errorcode.proto";
|
||||
option java_outer_classname = "ErrorCodeEnums";
|
||||
option objc_class_prefix = "GNCP";
|
||||
|
||||
// The type of the error.
|
||||
// It help to sort error codes to different types to analyze and also impact the
|
||||
// logcat print it as Warning or Severe.
|
||||
enum ErrorType {
|
||||
UNKNOWN_TYPE = 0;
|
||||
|
||||
// The error should not happen on production, it's like the input is null or
|
||||
// not invalid or it's a unexpected API call. For example, start advertising
|
||||
// with empty service ID or start advertising with the same service ID twice.
|
||||
DEVELOPING = 1;
|
||||
|
||||
// It’s about the device's capabilities, some devices may not support the
|
||||
// feature Nearby used. E.g. The device not support BLE advertising
|
||||
DEVICE = 2;
|
||||
|
||||
// The failure return from the system or library API we used to communicate
|
||||
// with the medium. E.g. get null OS objects or call the API but get a
|
||||
// negative return value which indicates that the system does not allow to do
|
||||
// that now.
|
||||
SYSTEM = 3;
|
||||
|
||||
// The network related failure. E.g. get an EOF exception while reading pipe
|
||||
// or fail to create connection.
|
||||
NETWORK = 4;
|
||||
|
||||
// This may not be a failure, it can be the things we are interested in, like
|
||||
// to count how many BLE advertisements the device received in a specified
|
||||
// period and how many different advertisements in it, it can help us to know
|
||||
// the user under a clean or dirty environment.
|
||||
OTHERS = 5;
|
||||
}
|
||||
|
||||
// The event which the error occurs on.
|
||||
enum Event {
|
||||
UNKNOWN_EVENT = 0;
|
||||
START_ADVERTISING = 1;
|
||||
STOP_ADVERTISING = 2;
|
||||
START_LISTENING_INCOMING_CONNECTION = 3;
|
||||
STOP_LISTENING_INCOMING_CONNECTION = 4;
|
||||
START_DISCOVERING = 5;
|
||||
STOP_DISCOVERING = 6;
|
||||
CONNECT = 7;
|
||||
DISCONNECT = 8;
|
||||
ACCEPT_CONNECTION = 9;
|
||||
REJECT_CONNECTION = 10;
|
||||
SEND_PAYLOAD = 11;
|
||||
CANCEL_PAYLOAD = 12;
|
||||
RECEIVE_PAYLOAD = 13;
|
||||
}
|
||||
|
||||
// The error to identify the common failure for all mediums. The range between 0
|
||||
// and 30.
|
||||
enum CommonError {
|
||||
UNKNOWN_ERROR = 0;
|
||||
|
||||
// The common error for all mediums, the range between 0 and 30.
|
||||
|
||||
// Developing error, the input with invalid format or empty.
|
||||
INVALID_PARAMETER = 1;
|
||||
// Device error, the medium not available on this device.
|
||||
MEDIUM_NOT_AVAILABLE = 2;
|
||||
// System error, the medium in the unexpected state, e.g. we have check the
|
||||
// medium is on, after then it suddently off and cause Nearby
|
||||
// Connection failed.
|
||||
UNEXPECTED_MEDIUM_STATE = 3;
|
||||
// System error, the medim not available because the resource ran out. e.g.
|
||||
// the Wi-Fi Direct initialized cause Wi-Fi Aware not available, or BLE
|
||||
// connections hit the maximan number, or Wi-Fi Hotstop already created.
|
||||
OUT_OF_RESOURCE = 4;
|
||||
// Others error, the error happens when user cancel the flow, it's not a
|
||||
// real failure.
|
||||
FLOW_CANCELED = 5;
|
||||
// Developing error, an unexpect call that the medium not ready, need to do
|
||||
// something before this call. e.g. call WifiAwareImpli#connectToSocket but
|
||||
// never join network before this call.
|
||||
UNEXPECTED_CALL = 6;
|
||||
|
||||
// Reserved 7 to 30
|
||||
}
|
||||
|
||||
// The error for event START_ADVERTISING. The range between 31 and 99.
|
||||
enum StartAdvertisingError {
|
||||
reserved 37, 39;
|
||||
|
||||
// Developing error, not allow to advertising fast pair model id and sharing
|
||||
// fast advertisement at the same time, they are both use fast
|
||||
// advertisement, and only allow 1 fast advertisement at the same time.
|
||||
MULTIPLE_FAST_ADVERTISEMENT_NOT_ALLOWED = 31;
|
||||
// System error, there's already someone advertising fast advertisement, not
|
||||
// allow to start another one.
|
||||
FAST_ADVERTISEMENT_ALREADY_ADVERTISED = 32;
|
||||
// Developing error, this service ID already requested, should not request
|
||||
// it again without stop advertising.
|
||||
DUPLICATE_ADVERTISING_REQUESTED = 33;
|
||||
// System error, failed to start GATT server
|
||||
START_GATT_SERVER_FAILED = 34;
|
||||
// System error, all advertising slot ran out, can't available for new
|
||||
// regular advertisement.
|
||||
BLE_MAX_GATT_ADVERTISEMENT_SLOT_REACHED = 35;
|
||||
// System error, failed to start advertising for legacy advertisements on BLE
|
||||
START_LEGACY_ADVERTISING_FAILED = 36;
|
||||
// System error, failed to start advertising for extended advertisements on
|
||||
// BLE
|
||||
START_EXTENDED_ADVERTISING_FAILED = 38;
|
||||
// System error, there's already someone advertising on Bluetooth, not allow
|
||||
// to start another one.
|
||||
BLUETOOTH_ALREADY_ADVERTISED = 40;
|
||||
// System error, failed to modify the Bluetooth name.
|
||||
MODIFY_BLUETOOTH_NAME_FAILED = 41;
|
||||
// System error, failed to persist the original Bluetooth name into shared
|
||||
// preference.
|
||||
PERSIST_ORIGINAL_BLUETOOTH_NAME_FAILED = 42;
|
||||
// System error, failed to start advertising.
|
||||
START_ADVERTISING_FAILED = 43;
|
||||
|
||||
// Developing error, not allow to advertising on Wi-Fi Lan(TDLS) without
|
||||
// accetpting connections. The connection may comes in very quickly, so need
|
||||
// to accetpt connections before advertising.
|
||||
SHOULD_ACCEPT_CONNECTIONS_BEFORE_ADVERTISING_ON_WIFI_LAN = 44;
|
||||
// System error, failed to acquire WifiAwareSession
|
||||
ACQUIRE_WIFI_AWARE_SESSION_FAILED = 45;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_START_ADVERTISING_ERROR = 46;
|
||||
|
||||
// System error, failed to update Aware PublishConfig
|
||||
AWARE_UPDATE_PUBLISHING_FAILED = 47;
|
||||
|
||||
// Next ID :48
|
||||
}
|
||||
|
||||
// The error for event STOP_ADVERTISING. The range between 31 and 99.
|
||||
enum StopAdvertisingError {
|
||||
// System error, failed to stop advertising.
|
||||
STOP_ADVERTISING_FAILED = 31;
|
||||
// System error, failed to modify the Bluetooth name.
|
||||
RESTORE_BLUETOOTH_NAME_FAILED = 32;
|
||||
// System error, failed to stop advertising for BLE legacy advertisements.
|
||||
STOP_LEGACY_ADVERTISING_FAILED = 33;
|
||||
// System error, failed to stop advertising for BLE extended advertisements.
|
||||
STOP_EXTENDED_ADVERTISING_FAILED = 34;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_STOP_ADVERTISING_ERROR = 35;
|
||||
|
||||
// Next ID :36
|
||||
}
|
||||
|
||||
// The error for event START_DISCOVERING. The range between 31 and 99.
|
||||
enum StartDiscoveringError {
|
||||
// Developing error, this service ID already requested, should not request it
|
||||
// again without stop discovering.
|
||||
DUPLICATE_DISCOVERING_REQUESTED = 31;
|
||||
// System error, failed to start discovering for legacy advertisements on BLE
|
||||
START_LEGACY_DISCOVERING_FAILED = 32;
|
||||
// System error, failed to start discovering for extended advertisements on
|
||||
// BLE
|
||||
START_EXTENDED_DISCOVERING_FAILED = 33;
|
||||
// System error, failed to start discovering.
|
||||
START_DISCOVERING_FAILED = 34;
|
||||
// Network error, invalid remote target info, discover the nearby devices but
|
||||
// the information not valid.
|
||||
INVALID_TARGET_INFO = 35;
|
||||
// Network error, failed to fetch the advertisement from the remote devices.
|
||||
FETCH_ADVERTISEMENT_FAILED = 36;
|
||||
// Network error, failed to fetch the advertisement via GATT from the remote
|
||||
// devices.
|
||||
GATT_FETCH_ADVERTISEMENT_FAILED = 37;
|
||||
// Network error, failed to fetch the advertisement via L2CAP from the remote
|
||||
// devices.
|
||||
L2CAP_FETCH_ADVERTISEMENT_FAILED = 38;
|
||||
// System error, the medium not available when trying to fetch advertisements.
|
||||
// e.g. fetch advertisements but BT disabled unexpectedly.
|
||||
NOT_AVAILABLE_TO_FETCH_ADVERTISEMENT = 39;
|
||||
// System error, failed to acquire WifiAwareSession
|
||||
ACQUIRE_WIFI_AWARE_SESSION_FOR_DISCOVERING_FAILED = 40;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_START_DISCOVERING_ERROR = 41;
|
||||
|
||||
// Next ID :42
|
||||
}
|
||||
|
||||
// The error for event STOP_DISCOVERING. The range between 31 and 99.
|
||||
enum StopDiscoveringError {
|
||||
// System error, failed to stop discovering.
|
||||
STOP_DISCOVERING_FAILED = 31;
|
||||
// System error, failed to stop discovering for BLE legacy scanning.
|
||||
STOP_LEGACY_DISCOVERING_FAILED = 32;
|
||||
// System error, failed to stop discovering for BLE extended scanning.
|
||||
STOP_EXTENDED_DISCOVERING_FAILED = 33;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_STOP_DISCOVERING_ERROR = 34;
|
||||
|
||||
// Next ID :35
|
||||
}
|
||||
|
||||
// The error for event START_LISTENING_INCOMING_CONNECTION. The range between 31
|
||||
// and 99.
|
||||
enum StartListeningIncomingConnectionError {
|
||||
// Developing error, this service ID already requested, should not request it
|
||||
// again without stop accepting.
|
||||
DUPLICATE_ACCEPTING_CONNECTION_REQUESTED = 31;
|
||||
// System error, failed to open a GATT server for listening incoming GATT
|
||||
// connection.
|
||||
OPEN_GATT_SERVER_FAILED = 32;
|
||||
// System error, failed to accept the incoming GATT connection
|
||||
ACCEPT_GATT_CONNECTION_FAILED = 33;
|
||||
// System error, failed to accept the incoming L2CAP connection
|
||||
ACCEPT_L2CAP_CONNECTION_FAILED = 34;
|
||||
// Network error, wait the GATT connection ready after the connection
|
||||
// established but never.
|
||||
CREATE_GATT_SERVER_SOCKET_NOT_READY = 35;
|
||||
// System error, failed to accept the incoming connection
|
||||
ACCEPT_CONNECTION_FAILED = 36;
|
||||
// System error, failed to create a server socket for listening incoming
|
||||
// connection.
|
||||
CREATE_SERVER_SOCKET_FAILED = 37;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_START_LISTENING_INCOMING_CONNECTION_ERROR = 38;
|
||||
|
||||
// Network error, failed to send L2 Message to the remote peer
|
||||
ACCEPT_SEND_AWARE_L2_MESSAGE_FAILED = 39;
|
||||
// Network error, failed to receive L2 Message from the remote peer
|
||||
ACCEPT_RECEIVE_AWARE_L2_MESSAGE_FAILED = 40;
|
||||
|
||||
// Next ID :41
|
||||
}
|
||||
|
||||
// The error for event STOP_LISTENING_INCOMING_CONNECTION. The range between 31
|
||||
// and 99.
|
||||
enum StopListeningIncomingConnectionError {
|
||||
// System error, failed to stop accepting the incoming connection
|
||||
STOP_ACCEPTING_CONNECTION_FAILED = 31;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_STOP_LISTENING_INCOMING_CONNECTION_ERROR = 32;
|
||||
|
||||
// Next ID :33
|
||||
}
|
||||
|
||||
// The error for event CONNECT. The range between 31 and 99.
|
||||
enum ConnectError {
|
||||
// Network error, failed to connect to remote device because we lost the
|
||||
// target without MAC address to connect to. e.g. BLE cache MAC address in
|
||||
// medium, it may lost when just try to connect.
|
||||
UNEXPECT_TARGET_LOST = 31;
|
||||
// System error, failed to establish connection on GATT
|
||||
ESTABLISH_GATT_CONNECTION_FAILED = 32;
|
||||
// System error, failed to establish connection on L2CAP
|
||||
ESTABLISH_L2CAP_CONNECTION_FAILED = 33;
|
||||
// Developing error, the MAC address not valid for connecting
|
||||
INVALID_MAC_ADDRESS = 34;
|
||||
// Others error, unexpected interrupt when sleep before connect GATT for
|
||||
// waiting GATT server ready. Should not hapepen, it may be the process be
|
||||
// killed.
|
||||
SLEEP_BEFORE_CONNECT_GATT_INTERRUPTED = 35;
|
||||
// Others error, unexpected interrupt when sleep after GATT connect to wait
|
||||
// GATT connection ready to transfer data. Should not hapepen, it may be
|
||||
// the process be killed.
|
||||
SLEEP_AFTER_GATT_CONNECTED_INTERRUPTED = 36;
|
||||
// Network error, failed to configure the GATT connection priority, it may
|
||||
// failed when the connection still wait for the status update from network or
|
||||
// just a RemoteException.
|
||||
REQUEST_GATT_CONNECTION_PRIORITY_FAILED = 37;
|
||||
// Network error, failed to change connection for data transferring on L2CAP
|
||||
// connection.
|
||||
L2CAP_SWITCH_TO_DATA_TRANSFERRING_FAILED = 38;
|
||||
// Network error, failed to change connection for data transferring on GATT
|
||||
// connection.
|
||||
GATT_SWITCH_TO_DATA_TRANSFERRING_FAILED = 39;
|
||||
// System error, failed to establish connection
|
||||
ESTABLISH_CONNECTION_FAILED = 40;
|
||||
// Developing error, this connection already established, should not request
|
||||
// it again.
|
||||
DUPLICATE_CONNECTION_REQUESTED = 41;
|
||||
// Network error, the connection lost.
|
||||
CONNECTION_LOST = 42;
|
||||
// Network error, failed to connect to the network. e.g. an aware network,
|
||||
// hotspot or a direct network.
|
||||
CONNECT_TO_NETWORK_FAILED = 43;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_CONNECT_ERROR = 44;
|
||||
|
||||
// Network error, failed to send L2 Message to the remote peer
|
||||
CONNECT_SEND_AWARE_L2_MESSAGE_FAILED = 45;
|
||||
// Network error, failed to send L2 Message to the remote peer
|
||||
CONNECT_READ_AWARE_L2_MESSAGE_FAILED = 46;
|
||||
|
||||
// Next ID :47
|
||||
}
|
||||
|
||||
// The error for event DISCONNECT. The range between 31 and 99.
|
||||
enum DisconnectError {
|
||||
// System error, failed to disconnect the network.
|
||||
DISCONNECT_NETWORK_FAILED = 31;
|
||||
|
||||
// The default value for clearcut
|
||||
UNKNOWN_DISCONNECT_ERROR = 32;
|
||||
|
||||
// Next ID :33
|
||||
}
|
||||
|
||||
enum Description {
|
||||
reserved 28, 29;
|
||||
|
||||
UNKNOWN = 0;
|
||||
NULL_SERVICE_ID = 1;
|
||||
NULL_ADVERTISEMENT_BYTES = 2;
|
||||
CONNECTIONS_FEATURE_DISABLED = 3;
|
||||
STALE_SDK_VERSION = 4;
|
||||
FEATURE_BLUETOOTH_NOT_SUPPORTED = 5;
|
||||
FEATURE_BLUETOOTH_LE_NOT_SUPPORTED = 6;
|
||||
NULL_BLUETOOTH_MANAGER = 7;
|
||||
NULL_BLUETOOTH_ADAPTER = 8;
|
||||
INVALID_FAST_PAIR_MODEL_ID = 9;
|
||||
INVALID_FAST_ADVERTISEMENT_DATA = 10;
|
||||
INVALID_ADVERTISEMENT_HEADER_DATA = 11;
|
||||
INVALID_REGULAR_ADVERTISEMENT_DATA = 12;
|
||||
NULL_BLUETOOTH_LE_ADVERTISER_COMPAT = 13;
|
||||
ADVERTISE_FAILED_ALREADY_STARTED = 14;
|
||||
ADVERTISE_FAILED_DATA_TOO_LARGE = 15;
|
||||
ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 16;
|
||||
ADVERTISE_FAILED_INTERNAL_ERROR = 17;
|
||||
ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 18;
|
||||
INTERRUPTED_EXCEPTION = 19;
|
||||
EXECUTION_EXCEPTION = 20;
|
||||
NULL_BLUETOOTH_DEVICE_NAME = 21;
|
||||
SET_SCAN_MODE_FAILED = 22;
|
||||
INVOKE_API_FAILED = 23;
|
||||
TIMEOUT = 24;
|
||||
NULL_NFC_TAG = 25;
|
||||
FEATURE_NFC_NOT_SUPPORTED = 26;
|
||||
FEATURE_NFC_HOST_CARD_EMULATION_NOT_SUPPORTED = 27;
|
||||
MULTICAST_NOT_SUPPORTED = 30;
|
||||
NSD_NOT_ENABLED = 31;
|
||||
INVALID_PORT_NUMBER = 32;
|
||||
NULL_SERVICE_NAME = 33;
|
||||
NULL_SERVICE_TYPE = 34;
|
||||
WITHOUT_CONNECTED_WIFI_NETWORK = 35;
|
||||
FEATURE_WIFI_AWARE_NOT_SUPPORTED = 36;
|
||||
NULL_CONNECTIVITY_MANAGER = 37;
|
||||
NULL_WIFI_AWARE_MANAGER = 38;
|
||||
STALE_ANDROID_VERSION = 39;
|
||||
NULL_SERVICE_INFO = 40;
|
||||
NULL_WORK_SOURCE = 41;
|
||||
NULL_CALLBACK = 42;
|
||||
NULL_BLUETOOTH_LE_SCANNER_COMPAT = 43;
|
||||
EMPTY_WORK_SOURCE_CACHE = 44;
|
||||
SCAN_FAILED_ALREADY_STARTED = 45;
|
||||
SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 46;
|
||||
SCAN_FAILED_INTERNAL_ERROR = 47;
|
||||
SCAN_FAILED_FEATURE_UNSUPPORTED = 48;
|
||||
SCAN_FAILED_BLUETOOTH_DISABLED = 49;
|
||||
SCAN_FILTERS_NOT_ALLOWED_FOR_LOCATION = 50;
|
||||
BLUETOOTH_SCAN_REJUVENATE_FAILED = 51;
|
||||
NULL_BLE_PERIPHERAL = 52;
|
||||
NULL_BLUETOOTH_GATT = 53;
|
||||
UNEXPECTED_BLUETOOTH_STATE = 54;
|
||||
REMOTE_EXCEPTION = 55;
|
||||
INVALID_BLUETOOTH_SOCKET_STATE_BEFORE_CONNECT = 56;
|
||||
BLUETOOTH_SOCKET_CLOSED_AFTER_CONNECTED = 57;
|
||||
INVALID_BLUETOOTH_CHANNEL = 58;
|
||||
NULL_BLUETOOTH_DEVICE = 59;
|
||||
NULL_BLUETOOTH_PROXY = 60;
|
||||
INVALID_PACKET_LENGTH = 61;
|
||||
INVALID_PACKET_BYTES = 62;
|
||||
UNEXPECTED_EOF_EXCEPTION = 63;
|
||||
SOCKET_CLOSED_OR_TIMEOUT = 64;
|
||||
INVALID_IPV4_ADDRESS = 65;
|
||||
INVALID_IPV6_ADDRESS = 66;
|
||||
NULL_ADDRESS = 67;
|
||||
INVALID_VERSION = 68;
|
||||
SET_CONNECTION_PRIORITY_FAILED = 69;
|
||||
SET_CONNECTION_PRIORITY_INTERRUPTED = 70;
|
||||
UNKNOWN_IO_EXCEPTION = 71;
|
||||
READ_CHARACTERISTIC_FAILED = 72;
|
||||
WIFI_HOTSPOT_ENABLED = 73;
|
||||
AWARE_UNAVAILABLE = 74;
|
||||
IN_BLACK_LIST = 75;
|
||||
FEATURE_WIFI_NOT_SUPPORTED = 76;
|
||||
NULL_WIFI_MANAGER = 77;
|
||||
SOCKET_CLOSED = 78;
|
||||
SOCKET_ALREADY_CONNECTED = 79;
|
||||
NFC_TECH_NOT_SUPPORTED = 80;
|
||||
NFC_SERVICE_DIED = 81;
|
||||
BIND_NFC_SERVICE_FAILED = 82;
|
||||
NFC_CREATE_SOCKET_FAILED = 83;
|
||||
NULL_WIFI_AWARE_PEER = 84;
|
||||
NETWORK_ALREADY_JOINED = 85;
|
||||
JOIN_AWARE_NETWORK_CANCELLED = 86;
|
||||
NETWORK_UNAVAILABLE = 87;
|
||||
WITHOUT_ACTIVE_AWARE_NETWORK = 88;
|
||||
WITHOUT_JOINED_AWARE_NETWORK = 89;
|
||||
CONNET_TO_SOCKET_CANCELLED = 90;
|
||||
NULL_SSID = 91;
|
||||
NULL_PASSWORD = 92;
|
||||
FEATURE_WIFI_DIRECT_NOT_SUPPORTED = 93;
|
||||
NULL_WIFI_P2P_MANAGER = 94;
|
||||
P2P_GROUP_FORMED = 95;
|
||||
ACQUIRE_P2P_CHANNEL_FAILED = 96;
|
||||
P2P_UNSUPPORTED = 97;
|
||||
INTERNAL_ERROR = 98;
|
||||
BUSY = 99;
|
||||
REFLECTION_ERROR = 100;
|
||||
NETWORK_ERROR_EHOSTUNREACH = 101;
|
||||
NETWORK_ERROR_ENETUNREACH = 102;
|
||||
ADD_NETWORK_FAILED = 103;
|
||||
UPDATE_NETWORK_FAILED = 104;
|
||||
ALREADY_IN_PROGRESS = 105;
|
||||
INVALID_ARGS = 106;
|
||||
NOT_AUTHORIZED = 107;
|
||||
INVALID_NETWORK_ID = 108;
|
||||
WIFI_MANAGER_ENABLE_NETWORK_FAILED = 109;
|
||||
WIFI_MANAGER_RECONNECT_FAILED = 110;
|
||||
WITHOUT_ACTIVE_NETWORK = 111;
|
||||
WEBRTC_CONNECTION_FLOW_EXIST = 112;
|
||||
NULL_DROID_GUARD_RESULT = 113;
|
||||
TACHYON_SIGNALING_MESSENGER_EXIST = 114;
|
||||
TACHYON_ALREADY_START_RECEIVE_MESSAGE = 115;
|
||||
TACHYON_RECEIVE_MESSAGE_FAILED = 116;
|
||||
TACHYON_RECEIVE_MESSAGE_INTERRUPTED = 117;
|
||||
TACHYON_RECEIVE_MESSAGE_EXECUTION_EXCEPTION = 118;
|
||||
TACHYON_RECEIVE_MESSAGE_TIMEOUT = 119;
|
||||
TACHYON_RECEIVE_MESSAGE_AUTH_EXCEPTION = 120;
|
||||
TACHYON_RECEIVE_MESSAGE_STATUS_EXCEPTION = 121;
|
||||
TACHYON_SEND_MESSAGE_AUTH_EXCEPTION = 122;
|
||||
TACHYON_SEND_MESSAGE_STATUS_EXCEPTION = 123;
|
||||
TACHYON_GET_ICE_SERVER_AUTH_EXCEPTION = 124;
|
||||
TACHYON_GET_ICE_SERVER_STATUS_EXCEPTION = 125;
|
||||
EMPTY_TACHYON_ICE_SERVER = 126;
|
||||
POTENTIAL_WEBRTC_LIB_LOADING_FAILURE = 127;
|
||||
UNEXPECTED_GATT_DESCRIPTOR = 128;
|
||||
FAIL_TO_RECEIVE_L2CAP_PACKET = 129;
|
||||
WITHOUT_PSM_VALUE = 130;
|
||||
SOCKET_BIND_LISTEN_FAILED = 131;
|
||||
UNEXPECTED_PACKET_CONTENT = 132;
|
||||
UNREGISTER_NSD_MANAGER_FAILED = 133;
|
||||
PUBLISH_EMPTY_ADVERTISEMENT_FAILED = 134;
|
||||
BLUETOOTH_SOCKET_NOT_IN_LISTENING_STATE = 135;
|
||||
INVALID_BLUETOOTH_SOCKET_SIGNAL_SIZE = 136;
|
||||
INVALID_BLUETOOTH_SOCKET_SIGNAL_STATUS = 137;
|
||||
GET_ADDRESS_FAILED = 138;
|
||||
NULL_LOCAL_ADDRESS = 139;
|
||||
IS_LOOPBACK_ADDRESS = 140;
|
||||
SOCKET_NOT_BOUND = 141;
|
||||
INVALID_REMOTE_ADDRESS = 142;
|
||||
SOCKET_ALREADY_BOUND = 143;
|
||||
HOTSPOT_NOT_STARTED = 144;
|
||||
WEBRTC_ALREADY_INITIALIZED = 145;
|
||||
INVALID_WEBRTC_STATE = 146;
|
||||
NULL_DATA_CHANNEL = 147;
|
||||
CREATE_OFFER_FAILED = 148;
|
||||
CLOSE_SERVER_SOCKET_FAILED = 149;
|
||||
WIFI_AWARE_STARTED = 150;
|
||||
AWARE_PUBLISH_SESSION_RAN_OUT = 151;
|
||||
AWARE_SUBSCRIBE_SESSION_RAN_OUT = 152;
|
||||
AWARE_DATA_PATH_RAN_OUT = 153;
|
||||
WIFI_SIGNAL_STRENGTH_POOR = 154;
|
||||
POTENTIAL_SRD_ISSUE = 155;
|
||||
AWARE_L2_MESSAGE_HOST_NETWORK_ERROR = 156;
|
||||
AWARE_L2_MESSAGE_NETWORK_AVAILABLE_ERROR = 157;
|
||||
AWARE_L2_MESSAGE_IP_AVAILABLE_ERROR = 158;
|
||||
AWARE_L2_MESSAGE_CANCELLATION_RECEIVED = 159;
|
||||
TIE_BREAK_LOSER = 160;
|
||||
SERVER_SOCKET_UNAVAILABLE = 161;
|
||||
HOSTED_NETWORK_UNAVAILABLE = 162;
|
||||
AWARE_UPDATE_PUBLISHING_CONFIG_FAILED = 163;
|
||||
L2CAP_UNAVAILABLE = 164;
|
||||
ALREADY_HAS_GATT_CONNECTION = 165;
|
||||
}
|
||||
Reference in New Issue
Block a user