1 //
2 // Copyright (C) 2022 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include <android-base/logging.h>
17 #include <android-base/strings.h>
18 #include <fruit/fruit.h>
19 #include <gflags/gflags.h>
20 #include <string>
21
22 #include "common/libs/utils/flag_parser.h"
23 #include "common/libs/utils/tee_logging.h"
24 #include "host/commands/metrics/events.h"
25 #include "host/commands/metrics/metrics_defs.h"
26 #include "host/commands/metrics/proto/cf_metrics_proto.h"
27 #include "host/commands/metrics/utils.h"
28 #include "host/libs/config/config_flag.h"
29 #include "host/libs/config/cuttlefish_config.h"
30 #include "host/libs/config/feature.h"
31 #include "shared/api_level.h"
32
33 using cuttlefish::MetricsExitCodes;
34
35 const std::string kLogSourceStr = "CUTTLEFISH_METRICS";
36 const int kLogSourceId = 1753;
37 const int kCppClientType =
38 19; // C++ native client type (clientanalytics.proto)
39
40 namespace cuttlefish {
41
Clearcut()42 Clearcut::Clearcut() {}
43
~Clearcut()44 Clearcut::~Clearcut() {}
45
buildCFLogEvent(uint64_t now_ms,cuttlefish::CuttlefishLogEvent::DeviceType device_type)46 std::unique_ptr<cuttlefish::CuttlefishLogEvent> buildCFLogEvent(
47 uint64_t now_ms, cuttlefish::CuttlefishLogEvent::DeviceType device_type) {
48 uint64_t now_s = now_ms / 1000;
49 uint64_t now_ns = (now_ms % 1000) * 1000000;
50
51 // "cfEvent" is the top level CuttlefishLogEvent
52 auto cfEvent = std::make_unique<cuttlefish::CuttlefishLogEvent>();
53 cfEvent->set_device_type(device_type);
54 cfEvent->set_session_id(metrics::sessionId(now_ms));
55 if (metrics::cfVersion() != "") {
56 cfEvent->set_cuttlefish_version(metrics::cfVersion());
57 }
58 Timestamp* timestamp = cfEvent->mutable_timestamp_ms();
59 timestamp->set_seconds(now_s);
60 timestamp->set_nanos(now_ns);
61 return cfEvent;
62 }
63
buildCFMetricsEvent(uint64_t now_ms,cuttlefish::CuttlefishLogEvent * cfEvent,cuttlefish::MetricsEvent::EventType event_type)64 void buildCFMetricsEvent(uint64_t now_ms,
65 cuttlefish::CuttlefishLogEvent* cfEvent,
66 cuttlefish::MetricsEvent::EventType event_type) {
67 uint64_t now_s = now_ms / 1000;
68 uint64_t now_ns = (now_ms % 1000) * 1000000;
69
70 // "metrics_event" is the 2nd level MetricsEvent
71 cuttlefish::MetricsEvent* metrics_event = cfEvent->mutable_metrics_event();
72 metrics_event->set_event_type(event_type);
73 metrics_event->set_os_type(metrics::osType());
74 metrics_event->set_os_version(metrics::osVersion());
75 metrics_event->set_vmm_type(metrics::vmmManager());
76 if (metrics::vmmVersion() != "") {
77 metrics_event->set_vmm_version(metrics::vmmVersion());
78 }
79 metrics_event->set_company(metrics::company());
80 metrics_event->set_api_level(PRODUCT_SHIPPING_API_LEVEL);
81 Timestamp* metrics_timestamp = metrics_event->mutable_event_time_ms();
82 metrics_timestamp->set_seconds(now_s);
83 metrics_timestamp->set_nanos(now_ns);
84 }
85
buildLogRequest(uint64_t now_ms,cuttlefish::CuttlefishLogEvent * cfEvent)86 std::unique_ptr<LogRequest> buildLogRequest(
87 uint64_t now_ms, cuttlefish::CuttlefishLogEvent* cfEvent) {
88 // "log_request" is the top level LogRequest
89 auto log_request = std::make_unique<LogRequest>();
90 log_request->set_request_time_ms(now_ms);
91 log_request->set_log_source(kLogSourceId);
92 log_request->set_log_source_name(kLogSourceStr);
93 ClientInfo* client_info = log_request->mutable_client_info();
94 client_info->set_client_type(kCppClientType);
95
96 // "cfLogStr" is CuttlefishLogEvent serialized
97 std::string cfLogStr;
98 if (!cfEvent->SerializeToString(&cfLogStr)) {
99 LOG(ERROR) << "SerializeToString failed for event";
100 return nullptr;
101 }
102 LogEvent* logEvent = log_request->add_log_event();
103 logEvent->set_event_time_ms(now_ms);
104 logEvent->set_source_extension(cfLogStr);
105 return log_request;
106 }
107
SendEvent(cuttlefish::CuttlefishLogEvent::DeviceType device_type,cuttlefish::MetricsEvent::EventType event_type)108 int Clearcut::SendEvent(cuttlefish::CuttlefishLogEvent::DeviceType device_type,
109 cuttlefish::MetricsEvent::EventType event_type) {
110 uint64_t now_ms = metrics::epochTimeMs();
111
112 auto cfEvent = buildCFLogEvent(now_ms, device_type);
113 buildCFMetricsEvent(now_ms, cfEvent.get(), event_type);
114 auto logRequest = buildLogRequest(now_ms, cfEvent.get());
115 if (!logRequest) {
116 LOG(ERROR) << "failed to build LogRequest";
117 return kMetricsError;
118 }
119
120 std::string logRequestStr;
121 if (!logRequest->SerializeToString(&logRequestStr)) {
122 LOG(ERROR) << "SerializeToString failed for log_request";
123 return kMetricsError;
124 }
125 return metrics::postReq(logRequestStr, metrics::kProd);
126 }
127
SendVMStart(cuttlefish::CuttlefishLogEvent::DeviceType device)128 int Clearcut::SendVMStart(cuttlefish::CuttlefishLogEvent::DeviceType device) {
129 return SendEvent(
130 device, cuttlefish::MetricsEvent::CUTTLEFISH_EVENT_TYPE_VM_INSTANTIATION);
131 }
132
SendVMStop(cuttlefish::CuttlefishLogEvent::DeviceType device)133 int Clearcut::SendVMStop(cuttlefish::CuttlefishLogEvent::DeviceType device) {
134 return SendEvent(device,
135 cuttlefish::MetricsEvent::CUTTLEFISH_EVENT_TYPE_VM_STOP);
136 }
137
SendDeviceBoot(cuttlefish::CuttlefishLogEvent::DeviceType device)138 int Clearcut::SendDeviceBoot(
139 cuttlefish::CuttlefishLogEvent::DeviceType device) {
140 return SendEvent(device,
141 cuttlefish::MetricsEvent::CUTTLEFISH_EVENT_TYPE_DEVICE_BOOT);
142 }
143
SendLockScreen(cuttlefish::CuttlefishLogEvent::DeviceType device)144 int Clearcut::SendLockScreen(
145 cuttlefish::CuttlefishLogEvent::DeviceType device) {
146 return SendEvent(
147 device,
148 cuttlefish::MetricsEvent::CUTTLEFISH_EVENT_TYPE_LOCK_SCREEN_AVAILABLE);
149 }
150
151 } // namespace cuttlefish
152