Implement the android metrics reporter

Implement the metrics_reporter_android class which reports with
libmetricslogger. We reports the error_code only for now, and more
android metrics will be reported in the following up cls.

Test: mma
Change-Id: Id5760aaa4853fa9ee0248344fa12900b923dfb7f
diff --git a/Android.mk b/Android.mk
index d34898a..8807666 100644
--- a/Android.mk
+++ b/Android.mk
@@ -356,6 +356,7 @@
     libbrillo-binder \
     libcutils \
     libcurl \
+    libmetricslogger \
     libssl \
     libutils
 
@@ -389,6 +390,8 @@
     daemon_state_android.cc \
     hardware_android.cc \
     libcurl_http_fetcher.cc \
+    metrics_reporter_android.cc \
+    metrics_utils.cc \
     network_selector_android.cc \
     proxy_resolver.cc \
     update_attempter_android.cc \
@@ -463,6 +466,8 @@
 LOCAL_SRC_FILES := \
     boot_control_recovery.cc \
     hardware_android.cc \
+    metrics_reporter_android.cc \
+    metrics_utils.cc \
     network_selector_stub.cc \
     proxy_resolver.cc \
     sideload_main.cc \
diff --git a/metrics_reporter_android.cc b/metrics_reporter_android.cc
new file mode 100644
index 0000000..ebfad0d
--- /dev/null
+++ b/metrics_reporter_android.cc
@@ -0,0 +1,53 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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
+//
+//      http://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 "update_engine/metrics_reporter_android.h"
+
+#ifndef _UE_SIDELOAD
+#include <metricslogger/metrics_logger.h>
+#endif  // _UE_SIDELOAD
+
+namespace chromeos_update_engine {
+
+namespace metrics {
+
+#ifndef _UE_SIDELOAD
+const char kMetricsUpdateEngineErrorCode[] = "ota_update_engine_error_code";
+#endif
+}  // namespace metrics
+
+void MetricsReporterAndroid::ReportUpdateAttemptMetrics(
+    SystemState* /* system_state */,
+    int /* attempt_number */,
+    PayloadType /* payload_type */,
+    base::TimeDelta /* duration */,
+    base::TimeDelta /* duration_uptime */,
+    int64_t /* payload_size */,
+    int64_t /* payload_bytes_downloaded */,
+    int64_t /* payload_download_speed_bps */,
+    DownloadSource /* download_source */,
+    metrics::AttemptResult /* attempt_result */,
+    ErrorCode error_code,
+    metrics::DownloadErrorCode /* payload_download_error_code */,
+    metrics::ConnectionType /* connection_type */) {
+// No need to log histogram under sideload mode.
+#ifndef _UE_SIDELOAD
+  android::metricslogger::LogHistogram(metrics::kMetricsUpdateEngineErrorCode,
+                                       static_cast<int>(error_code));
+#endif
+}
+
+};  // namespace chromeos_update_engine
diff --git a/metrics_reporter_android.h b/metrics_reporter_android.h
new file mode 100644
index 0000000..9ee8bf5
--- /dev/null
+++ b/metrics_reporter_android.h
@@ -0,0 +1,87 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// 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
+//
+//      http://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 UPDATE_ENGINE_METRICS_REPORTER_ANDROID_H_
+#define UPDATE_ENGINE_METRICS_REPORTER_ANDROID_H_
+
+#include "update_engine/common/error_code.h"
+#include "update_engine/metrics_constants.h"
+#include "update_engine/metrics_reporter_interface.h"
+
+namespace chromeos_update_engine {
+
+class MetricsReporterAndroid : public MetricsReporterInterface {
+ public:
+  MetricsReporterAndroid() = default;
+
+  ~MetricsReporterAndroid() override = default;
+
+  void Initialize() override {}
+
+  void ReportRollbackMetrics(metrics::RollbackResult result) override {}
+
+  void ReportDailyMetrics(base::TimeDelta os_age) override {}
+
+  void ReportUpdateCheckMetrics(
+      SystemState* system_state,
+      metrics::CheckResult result,
+      metrics::CheckReaction reaction,
+      metrics::DownloadErrorCode download_error_code) override {}
+
+  void ReportUpdateAttemptMetrics(
+      SystemState* system_state,
+      int attempt_number,
+      PayloadType payload_type,
+      base::TimeDelta duration,
+      base::TimeDelta duration_uptime,
+      int64_t payload_size,
+      int64_t payload_bytes_downloaded,
+      int64_t payload_download_speed_bps,
+      DownloadSource download_source,
+      metrics::AttemptResult attempt_result,
+      ErrorCode internal_error_code,
+      metrics::DownloadErrorCode payload_download_error_code,
+      metrics::ConnectionType connection_type) override;
+
+  void ReportAbnormallyTerminatedUpdateAttemptMetrics() override {}
+
+  void ReportSuccessfulUpdateMetrics(
+      int attempt_count,
+      int updates_abandoned_count,
+      PayloadType payload_type,
+      int64_t payload_size,
+      int64_t num_bytes_downloaded[kNumDownloadSources],
+      int download_overhead_percentage,
+      base::TimeDelta total_duration,
+      int reboot_count,
+      int url_switch_count) override {}
+
+  void ReportCertificateCheckMetrics(ServerToCheck server_to_check,
+                                     CertificateCheckResult result) override {}
+
+  void ReportFailedUpdateCount(int target_attempt) override {}
+
+  void ReportTimeToReboot(int time_to_reboot_minutes) override {}
+
+  void ReportInstallDateProvisioningSource(int source, int max) override {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MetricsReporterAndroid);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_METRICS_REPORTER_ANDROID_H_
diff --git a/metrics_reporter_interface.h b/metrics_reporter_interface.h
index 458d98e..0c8a025 100644
--- a/metrics_reporter_interface.h
+++ b/metrics_reporter_interface.h
@@ -19,7 +19,6 @@
 
 #include <base/time/time.h>
 
-#include "update_engine/certificate_checker.h"
 #include "update_engine/common/constants.h"
 #include "update_engine/common/error_code.h"
 #include "update_engine/metrics_constants.h"
@@ -27,6 +26,9 @@
 
 namespace chromeos_update_engine {
 
+enum class ServerToCheck;
+enum class CertificateCheckResult;
+
 class MetricsReporterInterface {
  public:
   virtual ~MetricsReporterInterface() = default;
@@ -80,8 +82,8 @@
   //  |kMetricAttemptNumber|
   //  |kMetricAttemptPayloadType|
   //  |kMetricAttemptPayloadSizeMiB|
-  //  |kMetricAttemptDurationSeconds|
-  //  |kMetricAttemptDurationUptimeSeconds|
+  //  |kMetricAttemptDurationMinutes|
+  //  |kMetricAttemptDurationUptimeMinutes|
   //  |kMetricAttemptTimeSinceLastAttemptMinutes|
   //  |kMetricAttemptTimeSinceLastAttemptUptimeMinutes|
   //  |kMetricAttemptPayloadBytesDownloadedMiB|
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index e9502fe..0a1c20f 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -32,6 +32,8 @@
 #include "update_engine/common/file_fetcher.h"
 #include "update_engine/common/utils.h"
 #include "update_engine/daemon_state_interface.h"
+#include "update_engine/metrics_reporter_android.h"
+#include "update_engine/metrics_utils.h"
 #include "update_engine/network_selector.h"
 #include "update_engine/payload_consumer/download_action.h"
 #include "update_engine/payload_consumer/filesystem_verifier_action.h"
@@ -86,7 +88,8 @@
       prefs_(prefs),
       boot_control_(boot_control),
       hardware_(hardware),
-      processor_(new ActionProcessor()) {
+      processor_(new ActionProcessor()),
+      metrics_reporter_(new MetricsReporterAndroid()) {
   network_selector_ = network::CreateNetworkSelector();
 }
 
@@ -427,6 +430,30 @@
 
   for (auto observer : daemon_state_->service_observers())
     observer->SendPayloadApplicationComplete(error_code);
+
+  // TODO(xunchang): assign proper values to the metrics.
+  PayloadType payload_type = kNumPayloadTypes;
+  DownloadSource download_source = kNumDownloadSources;
+  metrics::AttemptResult attempt_result =
+      metrics_utils::GetAttemptResult(error_code);
+  TimeDelta duration;
+  TimeDelta duration_uptime;
+  // Report the android metrics when we terminate the update. Currently we are
+  // reporting error_code only.
+  metrics_reporter_->ReportUpdateAttemptMetrics(
+      nullptr,  // system_state
+      0,        // attempt_number
+      payload_type,
+      duration,
+      duration_uptime,
+      0,  // payload_size
+      0,  // payload_bytes_downloaded
+      0,  // payload_download_speed_bps
+      download_source,
+      attempt_result,
+      error_code,
+      metrics::DownloadErrorCode::kUnset,
+      metrics::ConnectionType::kUnset);
 }
 
 void UpdateAttempterAndroid::SetStatusAndNotify(UpdateStatus status) {
diff --git a/update_attempter_android.h b/update_attempter_android.h
index 167191e..a347e52 100644
--- a/update_attempter_android.h
+++ b/update_attempter_android.h
@@ -31,6 +31,7 @@
 #include "update_engine/common/hardware_interface.h"
 #include "update_engine/common/prefs_interface.h"
 #include "update_engine/daemon_state_interface.h"
+#include "update_engine/metrics_reporter_interface.h"
 #include "update_engine/network_selector_interface.h"
 #include "update_engine/payload_consumer/download_action.h"
 #include "update_engine/payload_consumer/postinstall_runner_action.h"
@@ -162,6 +163,8 @@
   // before applying an update to the other slot.
   bool updated_boot_flags_ = false;
 
+  std::unique_ptr<MetricsReporterInterface> metrics_reporter_;
+
   DISALLOW_COPY_AND_ASSIGN(UpdateAttempterAndroid);
 };