• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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