From c940c63c3d776c35a7f488d95878d55dfcb44f0b Mon Sep 17 00:00:00 2001 From: hai007 Date: Tue, 11 Apr 2023 15:10:21 -0700 Subject: [PATCH] Create fast_pair analytics recorder. PiperOrigin-RevId: 523515641 --- fastpair/analytics/BUILD | 48 ++++++ fastpair/analytics/analytics_recorder.cc | 130 ++++++++++++++++ fastpair/analytics/analytics_recorder.h | 69 +++++++++ fastpair/analytics/analytics_recorder_test.cc | 140 ++++++++++++++++++ internal/analytics/BUILD | 1 + 5 files changed, 388 insertions(+) create mode 100644 fastpair/analytics/BUILD create mode 100644 fastpair/analytics/analytics_recorder.cc create mode 100644 fastpair/analytics/analytics_recorder.h create mode 100644 fastpair/analytics/analytics_recorder_test.cc diff --git a/fastpair/analytics/BUILD b/fastpair/analytics/BUILD new file mode 100644 index 00000000..d1f7f1cf --- /dev/null +++ b/fastpair/analytics/BUILD @@ -0,0 +1,48 @@ +licenses(["notice"]) + +# Copyright 2023 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", + ], + copts = [ + "-Ithird_party", + ], + visibility = ["//fastpair:__subpackages__"], + deps = [ + "//internal/analytics:event_logger", + "//internal/proto/analytics:fast_pair_log_cc_proto", + "//proto:fast_pair_enums_cc_proto", + "//third_party/protobuf:protobuf_lite", + ], +) + +cc_test( + name = "analytics_recorder_test", + srcs = ["analytics_recorder_test.cc"], + deps = [ + ":analytics", + "//internal/analytics:event_logger", + "//internal/proto/analytics:fast_pair_log_cc_proto", + "//proto:fast_pair_enums_cc_proto", + "//third_party/protobuf:protobuf_lite", + "@com_github_protobuf_matchers//protobuf-matchers", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/fastpair/analytics/analytics_recorder.cc b/fastpair/analytics/analytics_recorder.cc new file mode 100644 index 00000000..dfdeabb9 --- /dev/null +++ b/fastpair/analytics/analytics_recorder.cc @@ -0,0 +1,130 @@ +// Copyright 2023 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 "fastpair/analytics/analytics_recorder.h" + +#include + +#include "internal/analytics/event_logger.h" +#include "internal/proto/analytics/fast_pair_log.proto.h" +#include "proto/fast_pair_enums.proto.h" +#include "third_party/protobuf/message_lite.h" + +namespace nearby { +namespace fastpair { +namespace analytics { + +using ::nearby::fastpair::analytics::AnalyticsRecorder; +using ::nearby::proto::fastpair::FastPairLog; + +void AnalyticsRecorder::NewGattEvent(int error_from_os) { + auto fast_pair_log = std::make_unique(); + + auto gatt_event = FastPairLog::GattEvent::default_instance().New(); + gatt_event->set_error_from_os(error_from_os); + + fast_pair_log->set_allocated_gatt_event(gatt_event); + LogEvent(*fast_pair_log); +} + +void AnalyticsRecorder::NewBrEdrHandoverEvent( + ::nearby::proto::fastpair::FastPairEvent::BrEdrHandoverErrorCode + error_code) { + auto fast_pair_log = std::make_unique(); + + auto br_edr_event = FastPairLog::BrEdrHandoverEvent::default_instance().New(); + br_edr_event->set_error_code(error_code); + + fast_pair_log->set_allocated_br_edr_handover_event(br_edr_event); + LogEvent(*fast_pair_log); +} + +void AnalyticsRecorder::NewCreateBondEvent( + ::nearby::proto::fastpair::FastPairEvent::CreateBondErrorCode error_code, + int unbond_reason) { + auto fast_pair_log = std::make_unique(); + + auto create_bond_event = + FastPairLog::CreateBondEvent::default_instance().New(); + create_bond_event->set_error_code(error_code); + create_bond_event->set_unbond_reason(unbond_reason); + + fast_pair_log->set_allocated_bond_event(create_bond_event); + LogEvent(*fast_pair_log); +} + +void AnalyticsRecorder::NewConnectEvent( + ::nearby::proto::fastpair::FastPairEvent::ConnectErrorCode error_code, + int profile_uuid) { + auto fast_pair_log = std::make_unique(); + + auto connect_event = FastPairLog::ConnectEvent::default_instance().New(); + connect_event->set_error_code(error_code); + connect_event->set_profile_uuid(profile_uuid); + + fast_pair_log->set_allocated_connect_event(connect_event); + LogEvent(*fast_pair_log); +} + +void AnalyticsRecorder::NewProviderInfo(int number_account_keys_on_provider) { + auto fast_pair_log = std::make_unique(); + + auto provider_info = FastPairLog::ProviderInfo::default_instance().New(); + provider_info->set_number_account_keys_on_provider( + number_account_keys_on_provider); + + fast_pair_log->set_allocated_provider_info(provider_info); + LogEvent(*fast_pair_log); +} + +void AnalyticsRecorder::NewFootprintsInfo(int number_devices_on_footprints) { + auto fast_pair_log = std::make_unique(); + + auto footprints_info = FastPairLog::FootprintsInfo::default_instance().New(); + footprints_info->set_number_devices_on_footprints( + number_devices_on_footprints); + + fast_pair_log->set_allocated_footprints_info(footprints_info); + LogEvent(*fast_pair_log); +} + +void AnalyticsRecorder::NewKeyBasedPairingInfo(int request_flag, + int response_type, + int response_flag, + int response_device_count) { + auto fast_pair_log = std::make_unique(); + + auto key_based_pairing_info = + FastPairLog::KeyBasedPairingInfo::default_instance().New(); + key_based_pairing_info->set_request_flag(request_flag); + key_based_pairing_info->set_response_flag(response_flag); + key_based_pairing_info->set_response_device_count(response_device_count); + key_based_pairing_info->set_response_type(response_type); + + fast_pair_log->set_allocated_key_based_pairing_info(key_based_pairing_info); + LogEvent(*fast_pair_log); +} + +// start private methods + +void AnalyticsRecorder::LogEvent(const ::google::protobuf::MessageLite& message) { + if (event_logger_ == nullptr) { + return; + } + event_logger_->Log(message); +} + +} // namespace analytics +} // namespace fastpair +} // namespace nearby diff --git a/fastpair/analytics/analytics_recorder.h b/fastpair/analytics/analytics_recorder.h new file mode 100644 index 00000000..dc8d7b92 --- /dev/null +++ b/fastpair/analytics/analytics_recorder.h @@ -0,0 +1,69 @@ +// Copyright 2023 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 THIRD_PARTY_NEARBY_FASTPAIR_ANALYTICS_ANALYTICS_RECORDER_H_ +#define THIRD_PARTY_NEARBY_FASTPAIR_ANALYTICS_ANALYTICS_RECORDER_H_ + +#include + +#include "internal/analytics/event_logger.h" +#include "internal/proto/analytics/fast_pair_log.proto.h" +#include "proto/fast_pair_enums.proto.h" +#include "third_party/protobuf/message_lite.h" + +namespace nearby { +namespace fastpair { +namespace analytics { + +class AnalyticsRecorder { + public: + explicit AnalyticsRecorder(::nearby::analytics::EventLogger* event_logger) + : event_logger_(event_logger) {} + ~AnalyticsRecorder() = default; + + void NewGattEvent(int error_from_os); + + void NewBrEdrHandoverEvent( + ::nearby::proto::fastpair::FastPairEvent::BrEdrHandoverErrorCode + error_code + + ); + + void NewCreateBondEvent( + ::nearby::proto::fastpair::FastPairEvent::CreateBondErrorCode error_code, + int unbond_reason); + + void NewConnectEvent( + ::nearby::proto::fastpair::FastPairEvent::ConnectErrorCode error_code, + int profile_uuid); + + void NewProviderInfo(int number_account_keys_on_provider); + + void NewFootprintsInfo(int number_devices_on_footprints); + + void NewKeyBasedPairingInfo(int request_flag, int response_type, + int response_flag, int response_device_count); + + private: + std::unique_ptr<::nearby::proto::fastpair::FastPairLog> createFastPairLog(); + void LogEvent(const ::google::protobuf::MessageLite& message); + + ::nearby::analytics::EventLogger* event_logger_ = nullptr; +}; + +} // namespace analytics +} // namespace fastpair +} // namespace nearby + +#endif // THIRD_PARTY_NEARBY_FASTPAIR_ANALYTICS_ANALYTICS_RECORDER_H_ diff --git a/fastpair/analytics/analytics_recorder_test.cc b/fastpair/analytics/analytics_recorder_test.cc new file mode 100644 index 00000000..4eb68d40 --- /dev/null +++ b/fastpair/analytics/analytics_recorder_test.cc @@ -0,0 +1,140 @@ +// Copyright 2023 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 "fastpair/analytics/analytics_recorder.h" + +#include + +#include "gmock/gmock.h" +#include "protobuf-matchers/protocol-buffer-matchers.h" +#include "gtest/gtest.h" +#include "internal/analytics/event_logger.h" +#include "internal/proto/analytics/fast_pair_log.proto.h" +#include "proto/fast_pair_enums.proto.h" +#include "third_party/protobuf/message_lite.h" + +namespace nearby { +namespace fastpair { +namespace analytics { +namespace { + +using ::nearby::proto::fastpair::FastPairEvent; +using ::nearby::proto::fastpair::FastPairLog; + +class MockEventLogger : public ::nearby::analytics::EventLogger { + public: + MockEventLogger() = default; + ~MockEventLogger() override = default; + + MOCK_METHOD(void, Log, (const ::google::protobuf::MessageLite& message), (override)); +}; + +class AnalyticsRecorderTest : public ::testing::Test { + public: + AnalyticsRecorderTest() = default; + ~AnalyticsRecorderTest() override = default; + + const MockEventLogger& event_logger() { return event_logger_; } + + AnalyticsRecorder analytics_recoder() { return analytics_recorder_; } + + private: + MockEventLogger event_logger_; + AnalyticsRecorder analytics_recorder_{&event_logger_}; +}; + +TEST_F(AnalyticsRecorderTest, NewGattEvent) { + EXPECT_CALL(event_logger(), Log) + .WillOnce([=](const ::google::protobuf::MessageLite& message) { + auto log = dynamic_cast(&message); + ASSERT_NE(log, nullptr); + EXPECT_EQ(log->gatt_event().error_from_os(), 1); + }); + + analytics_recoder().NewGattEvent(1); +} + +TEST_F(AnalyticsRecorderTest, NewBrEdrHandoverEvent) { + EXPECT_CALL(event_logger(), Log) + .WillOnce([=](const ::google::protobuf::MessageLite& message) { + auto log = dynamic_cast(&message); + ASSERT_NE(log, nullptr); + ASSERT_EQ(log->br_edr_handover_event().error_code(), + FastPairEvent::BLUETOOTH_MAC_INVALID); + }); + analytics_recoder().NewBrEdrHandoverEvent( + FastPairEvent::BLUETOOTH_MAC_INVALID); +} + +TEST_F(AnalyticsRecorderTest, NewCreateBondEvent) { + EXPECT_CALL(event_logger(), Log) + .WillOnce([=](const ::google::protobuf::MessageLite& message) { + auto log = dynamic_cast(&message); + ASSERT_NE(log, nullptr); + ASSERT_EQ(log->bond_event().error_code(), FastPairEvent::NO_PERMISSION); + ASSERT_EQ(log->bond_event().unbond_reason(), 12); + }); + analytics_recoder().NewCreateBondEvent(FastPairEvent::NO_PERMISSION, 12); +} + +TEST_F(AnalyticsRecorderTest, NewConnectEvent) { + EXPECT_CALL(event_logger(), Log) + .WillOnce([=](const ::google::protobuf::MessageLite& message) { + auto log = dynamic_cast(&message); + ASSERT_NE(log, nullptr); + ASSERT_EQ(log->connect_event().error_code(), + FastPairEvent::GET_PROFILE_PROXY_FAILED); + ASSERT_EQ(log->connect_event().profile_uuid(), 13); + }); + analytics_recoder().NewConnectEvent(FastPairEvent::GET_PROFILE_PROXY_FAILED, + 13); +} + +TEST_F(AnalyticsRecorderTest, NewProviderInfo) { + EXPECT_CALL(event_logger(), Log) + .WillOnce([=](const ::google::protobuf::MessageLite& message) { + auto log = dynamic_cast(&message); + ASSERT_NE(log, nullptr); + ASSERT_EQ(log->provider_info().number_account_keys_on_provider(), 14); + }); + analytics_recoder().NewProviderInfo(14); +} + +TEST_F(AnalyticsRecorderTest, NewFootprintsInfo) { + EXPECT_CALL(event_logger(), Log) + .WillOnce([=](const ::google::protobuf::MessageLite& message) { + auto log = dynamic_cast(&message); + ASSERT_NE(log, nullptr); + ASSERT_EQ(log->footprints_info().number_devices_on_footprints(), 15); + }); + analytics_recoder().NewFootprintsInfo(15); +} + +TEST_F(AnalyticsRecorderTest, NewKeyBasedPairingInfo) { + EXPECT_CALL(event_logger(), Log) + .WillOnce([=](const ::google::protobuf::MessageLite& message) { + auto log = dynamic_cast(&message); + ASSERT_NE(log, nullptr); + ASSERT_EQ(log->key_based_pairing_info().request_flag(), 16); + ASSERT_EQ(log->key_based_pairing_info().response_type(), 17); + ASSERT_EQ(log->key_based_pairing_info().response_flag(), 18); + ASSERT_EQ(log->key_based_pairing_info().response_device_count(), 19); + }); + analytics_recoder().NewKeyBasedPairingInfo(16, 17, 18, 19); +} + +} // namespace +} // namespace analytics +} // namespace fastpair +} // namespace nearby diff --git a/internal/analytics/BUILD b/internal/analytics/BUILD index 72b6179e..e641167a 100644 --- a/internal/analytics/BUILD +++ b/internal/analytics/BUILD @@ -20,6 +20,7 @@ cc_library( ], visibility = [ "//connections:__subpackages__", + "//fastpair:__subpackages__", "//location/nearby/analytics/cpp:__subpackages__", "//location/nearby/cpp/sharing:__subpackages__", ],