1/* 2 * Copyright (C) 2017 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 17//#define LOG_NDEBUG 0 18#define LOG_TAG "PluginMetricsReporting" 19#include <utils/Log.h> 20 21#include <media/PluginMetricsReporting.h> 22 23#include <media/MediaAnalyticsItem.h> 24 25#include "protos/plugin_metrics.pb.h" 26 27namespace android { 28 29namespace { 30 31using android::drm_metrics::MetricsGroup; 32using android::drm_metrics::MetricsGroup_Metric; 33using android::drm_metrics::MetricsGroup_Metric_MetricValue; 34 35const char* const kParentAttribute = "/parent/external"; 36 37status_t reportMetricsGroup(const MetricsGroup& metricsGroup, 38 const String8& batchName, 39 const int64_t* parentId) { 40 MediaAnalyticsItem analyticsItem(batchName.c_str()); 41 analyticsItem.generateSessionID(); 42 int64_t sessionId = analyticsItem.getSessionID(); 43 if (parentId != NULL) { 44 analyticsItem.setInt64(kParentAttribute, *parentId); 45 } 46 47 // Report the package name. 48 if (metricsGroup.has_app_package_name()) { 49 AString app_package_name(metricsGroup.app_package_name().c_str(), 50 metricsGroup.app_package_name().size()); 51 analyticsItem.setPkgName(app_package_name); 52 } 53 54 for (int i = 0; i < metricsGroup.metric_size(); ++i) { 55 const MetricsGroup_Metric& metric = metricsGroup.metric(i); 56 if (!metric.has_name()) { 57 ALOGE("Metric with no name."); 58 return BAD_VALUE; 59 } 60 61 if (!metric.has_value()) { 62 ALOGE("Metric with no value."); 63 return BAD_VALUE; 64 } 65 66 const MetricsGroup_Metric_MetricValue& value = metric.value(); 67 if (value.has_int_value()) { 68 analyticsItem.setInt64(metric.name().c_str(), 69 value.int_value()); 70 } else if (value.has_double_value()) { 71 analyticsItem.setDouble(metric.name().c_str(), 72 value.double_value()); 73 } else if (value.has_string_value()) { 74 analyticsItem.setCString(metric.name().c_str(), 75 value.string_value().c_str()); 76 } else { 77 ALOGE("Metric Value with no actual value."); 78 return BAD_VALUE; 79 } 80 } 81 82 analyticsItem.setFinalized(true); 83 if (!analyticsItem.selfrecord()) { 84 // Note the cast to int is because we build on 32 and 64 bit. 85 // The cast prevents a peculiar printf problem where one format cannot 86 // satisfy both. 87 ALOGE("selfrecord() returned false. sessioId %d", (int) sessionId); 88 } 89 90 for (int i = 0; i < metricsGroup.metric_sub_group_size(); ++i) { 91 const MetricsGroup& subGroup = metricsGroup.metric_sub_group(i); 92 status_t res = reportMetricsGroup(subGroup, batchName, &sessionId); 93 if (res != OK) { 94 return res; 95 } 96 } 97 98 return OK; 99} 100 101String8 sanitize(const String8& input) { 102 // Filters the input string down to just alphanumeric characters. 103 String8 output; 104 for (size_t i = 0; i < input.size(); ++i) { 105 char candidate = input[i]; 106 if ((candidate >= 'a' && candidate <= 'z') || 107 (candidate >= 'A' && candidate <= 'Z') || 108 (candidate >= '0' && candidate <= '9')) { 109 output.append(&candidate, 1); 110 } 111 } 112 return output; 113} 114 115} // namespace 116 117status_t reportDrmPluginMetrics(const Vector<uint8_t>& serializedMetrics, 118 const String8& vendor, 119 const String8& description) { 120 MetricsGroup root_metrics_group; 121 if (!root_metrics_group.ParseFromArray(serializedMetrics.array(), 122 serializedMetrics.size())) { 123 ALOGE("Failure to parse."); 124 return BAD_VALUE; 125 } 126 127 String8 name = String8::format("drm.vendor.%s.%s", 128 sanitize(vendor).c_str(), 129 sanitize(description).c_str()); 130 131 return reportMetricsGroup(root_metrics_group, name, NULL); 132} 133 134} // namespace android 135