1767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant#include "PixelStats.h"
2767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
3752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant#define LOG_TAG "pixelstats-system"
4752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant#include <log/log.h>
5752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant#include <metricslogger/metrics_logger.h>
6767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
7767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chantnamespace hardware {
8767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chantnamespace google {
9767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chantnamespace pixelstats {
10767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chantnamespace V1_0 {
11767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chantnamespace implementation {
12767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
13752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chantusing namespace android::metricslogger;
14752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
1598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew ChantPixelStats::PixelStats()
1698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    :limiter_(kDailyRatelimit) {}
1798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
18752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chantvoid loggerAddFields(ComplexEventLogger* logger) {
19752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logger->Record();
20752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
21752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
22752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chanttemplate<typename... Args>
23752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chantvoid loggerAddFields(ComplexEventLogger* logger, int32_t field, int32_t value, Args... args) {
24752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logger->AddTaggedData(LOGBUILDER_TYPE, TYPE_ACTION);
25752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logger->AddTaggedData(field, value);
26752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    loggerAddFields(logger, args...);
27752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
28752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
29752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chanttemplate<typename... Args>
30752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chantvoid logIntAction(int32_t category, Args... args) {
31752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    ComplexEventLogger logger(category);
32752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logger.AddTaggedData(LOGBUILDER_TYPE, TYPE_ACTION);
33752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    loggerAddFields(&logger, args...);
34752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
35752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
36767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant// Methods from ::hardware::google::pixelstats::V1_0::IPixelStats follow.
37752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportUsbConnectorConnected() {
3898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 20 / 24hrs (expected 0/24hrs)
3998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_USB_CONNECTOR_CONNECTED, 20))
4098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
41752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logIntAction(android::metricslogger::ACTION_USB_CONNECTOR_CONNECTED);
42752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    return Void();
43752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
44752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
4598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew ChantReturn<void> PixelStats::reportUsbConnectorDisconnected(int32_t durationMillis) {
4698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 20 / 24hrs (expected 0/24hrs)
4798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_USB_CONNECTOR_DISCONNECTED, 20))
4898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
49752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logIntAction(android::metricslogger::ACTION_USB_CONNECTOR_DISCONNECTED,
5098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant                 android::metricslogger::FIELD_DURATION_MILLIS, durationMillis);
51752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    return Void();
52752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
53752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
54752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportUsbAudioConnected(int32_t vid, int32_t pid) {
5598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 20 / 24hrs (expected 0/24hrs)
5698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_USB_AUDIO_CONNECTED, 20))
5798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
58752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logIntAction(android::metricslogger::ACTION_USB_AUDIO_CONNECTED,
59752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant                 android::metricslogger::FIELD_USB_AUDIO_VIDPID, (vid << 16) | pid);
60767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant    return Void();
61767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}
62767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
63752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportUsbAudioDisconnected(int32_t vid, int32_t pid,
6498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant                                                    int32_t durationMillis) {
6598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 20 / 24hrs (expected 0/24hrs)
6698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_USB_AUDIO_DISCONNECTED, 20))
6798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
68752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logIntAction(android::metricslogger::ACTION_USB_AUDIO_DISCONNECTED, FIELD_USB_AUDIO_VIDPID,
69752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant                    (vid << 16) | pid, android::metricslogger::FIELD_DURATION_MILLIS,
7098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant                    durationMillis);
71767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant    return Void();
72767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}
73767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
74752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportSpeakerImpedance(int32_t speakerLocation, int32_t milliOhms) {
7598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 2 / 24hrs (expected 1/24hrs)
7698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_SPEAKER_IMPEDANCE, 2))
7798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
7898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
79752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logIntAction(android::metricslogger::ACTION_SPEAKER_IMPEDANCE, FIELD_SPEAKER_LOCATION,
80752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant                    speakerLocation, FIELD_SPEAKER_IMPEDANCE_MILLIOHMS, milliOhms);
81767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant    return Void();
82767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}
83767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
84752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chantstatic android::metricslogger::HardwareType toMetricsLoggerHardwareType(
85752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    IPixelStats::HardwareType pixelstatsType) {
86752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    switch (pixelstatsType) {
87752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareType::MICROPHONE:
88752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::HardwareType::HARDWARE_MICROPHONE;
89752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareType::CODEC:
90752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::HardwareType::HARDWARE_CODEC;
91752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareType::SPEAKER:
92752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::HardwareType::HARDWARE_SPEAKER;
93752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareType::FINGERPRINT:
94752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::HardwareType::HARDWARE_FINGERPRINT;
95752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareType::UNKNOWN:
96752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        default:
97752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::HardwareType::HARDWARE_UNKNOWN;
98752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
99752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    }
100752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
101752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
102752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chantstatic android::metricslogger::HardwareFailureCode toMetricsLoggerHardwareFailure(
103752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    IPixelStats::HardwareErrorCode pixelstatsError) {
104752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    switch (pixelstatsError) {
105752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareErrorCode::COMPLETE:
106752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return HARDWARE_FAILURE_COMPLETE;
107752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareErrorCode::SPEAKER_HIGH_Z:
108752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return HARDWARE_FAILURE_SPEAKER_HIGH_Z;
109752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareErrorCode::SPEAKER_SHORT:
110752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return HARDWARE_FAILURE_SPEAKER_SHORT;
111752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareErrorCode::FINGERPRINT_SENSOR_BROKEN:
112752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return HARDWARE_FAILURE_FINGERPRINT_SENSOR_BROKEN;
113752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareErrorCode::FINGERPRINT_TOO_MANY_DEAD_PIXELS:
114752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return HARDWARE_FAILURE_FINGERPRINT_TOO_MANY_DEAD_PIXELS;
115752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::HardwareErrorCode::UNKNOWN:
116752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        default:
117752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return HARDWARE_FAILURE_UNKNOWN;
118752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    }
119752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
120752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
121752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportHardwareFailed(HardwareType hardwareType, int32_t hardwareLocation,
122752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant                                              HardwareErrorCode errorCode) {
12398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 15 / 24hrs (expected 0/24hrs)
12498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_HARDWARE_FAILED, 15))
12598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
126752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
127dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant    logIntAction(ACTION_HARDWARE_FAILED,
128dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_HARDWARE_TYPE, toMetricsLoggerHardwareType(hardwareType),
129dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_HARDWARE_LOCATION, hardwareLocation,
130dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_HARDWARE_FAILURE_CODE, toMetricsLoggerHardwareFailure(errorCode));
131767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant    return Void();
132767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}
133767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
134752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportPhysicalDropDetected(int32_t confidencePctg, int32_t accelPeak,
135752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant                                                    int32_t freefallDurationMs) {
13698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 10 / 24hrs (expected 0/24hrs)
13798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_PHYSICAL_DROP, 10))
13898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
13998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
140752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    logIntAction(ACTION_PHYSICAL_DROP, FIELD_CONFIDENCE_PERCENT, confidencePctg,
141752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant                 FIELD_ACCEL_MILLI_G, accelPeak,
142752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant                 FIELD_DURATION_MILLIS, freefallDurationMs);
143767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant    return Void();
144767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}
145767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
146752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportChargeCycles(const hidl_string& buckets) {
14798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 2 / 24hrs (expected 1/24hrs)
14898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_BATTERY_CHARGE_CYCLES, 2))
14998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
150752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    LogMultiAction(ACTION_BATTERY_CHARGE_CYCLES, FIELD_BATTERY_CHARGE_CYCLES, buckets);
151767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant    return Void();
152767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}
153767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
154752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chantstatic android::metricslogger::IoOperation toMetricsLoggerIoOperation(IPixelStats::IoOperation op) {
155752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    switch (op) {
156752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        default:
157752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::IoOperation::UNKNOWN:
158752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::IoOperation::IOOP_UNKNOWN;
159752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::IoOperation::READ:
160752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::IoOperation::IOOP_READ;
161752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::IoOperation::WRITE:
162752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::IoOperation::IOOP_WRITE;
163752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::IoOperation::UNMAP:
164752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::IoOperation::IOOP_UNMAP;
165752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant        case IPixelStats::IoOperation::SYNC:
166752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant            return android::metricslogger::IoOperation::IOOP_SYNC;
167752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    }
168752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
169752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant
170752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportSlowIo(IoOperation operation, int32_t count) {
17198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 2 per 24hrs
17298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_SLOW_IO, 2))
17398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
17498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    logIntAction(ACTION_SLOW_IO, FIELD_IO_OPERATION_TYPE, toMetricsLoggerIoOperation(operation),
17598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant                    FIELD_IO_OPERATION_COUNT, count);
176752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    return Void();
177752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
178767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
179752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew ChantReturn<void> PixelStats::reportBatteryHealthSnapshot(const BatteryHealthSnapshotArgs& args) {
18098a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    // Ratelimit to max 2 per 24hrs
18198a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (rateLimit(android::metricslogger::ACTION_BATTERY_HEALTH, 2))
18298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return Void();
183dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant    logIntAction(ACTION_BATTERY_HEALTH,
184dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_BATTERY_HEALTH_SNAPSHOT_TYPE, (int32_t)args.type,
185dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_BATTERY_TEMPERATURE_DECI_C, args.temperatureDeciC,
186dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_BATTERY_VOLTAGE_UV, args.voltageMicroV,
187dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_BATTERY_CURRENT_UA, args.currentMicroA,
188dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_BATTERY_OPEN_CIRCUIT_VOLTAGE_UV, args.openCircuitVoltageMicroV,
189dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_BATTERY_RESISTANCE_UOHMS, args.resistanceMicroOhm,
190dd5e0e81c78b8223f095fae4cd50f3dced38d6b3Andrew Chant                 FIELD_END_BATTERY_PERCENT, args.levelPercent);
191752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant    return Void();
192752e6c7ae93ae026569ee4cab0a8f717fc9e1f5eAndrew Chant}
193767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant
1947841d1d38400420da5a13a3d6da028153318e100Andrew ChantReturn<void> PixelStats::reportBatteryCausedShutdown(int32_t voltageMicroV) {
1957841d1d38400420da5a13a3d6da028153318e100Andrew Chant    // Ratelimit to max 5 per 24hrs
1967841d1d38400420da5a13a3d6da028153318e100Andrew Chant    if (rateLimit(android::metricslogger::ACTION_BATTERY_CAUSED_SHUTDOWN, 5))
1977841d1d38400420da5a13a3d6da028153318e100Andrew Chant        return Void();
1987841d1d38400420da5a13a3d6da028153318e100Andrew Chant    logIntAction(ACTION_BATTERY_CAUSED_SHUTDOWN, FIELD_BATTERY_VOLTAGE_UV, voltageMicroV);
1997841d1d38400420da5a13a3d6da028153318e100Andrew Chant    return Void();
2007841d1d38400420da5a13a3d6da028153318e100Andrew Chant}
2017841d1d38400420da5a13a3d6da028153318e100Andrew Chant
20298a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chantbool PixelStats::rateLimit(int action, int limit) {
20398a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    if (limiter_.RateLimit(action, limit)) {
20498a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        ALOGE("Rate limited action %d\n", action);
20598a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant        return true;
20698a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    }
20798a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant    return false;
20898a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant}
20998a7fc1fa2eea02eaa0ff6071803756e363bb1caAndrew Chant
210767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}  // namespace implementation
211767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}  // namespace V1_0
212767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}  // namespace pixelstats
213767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}  // namespace google
214767e1a5b5017588902ac9eb58bca1bc84939c906Andrew Chant}  // namespace hardware
215