#include "PixelStats.h" #define LOG_TAG "pixelstats-system" #include <log/log.h> #include <metricslogger/metrics_logger.h> namespace hardware { namespace google { namespace pixelstats { namespace V1_0 { namespace implementation { using namespace android::metricslogger; PixelStats::PixelStats() :limiter_(kDailyRatelimit) {} void loggerAddFields(ComplexEventLogger* logger) { logger->Record(); } template<typename... Args> void loggerAddFields(ComplexEventLogger* logger, int32_t field, int32_t value, Args... args) { logger->AddTaggedData(LOGBUILDER_TYPE, TYPE_ACTION); logger->AddTaggedData(field, value); loggerAddFields(logger, args...); } template<typename... Args> void logIntAction(int32_t category, Args... args) { ComplexEventLogger logger(category); logger.AddTaggedData(LOGBUILDER_TYPE, TYPE_ACTION); loggerAddFields(&logger, args...); } // Methods from ::hardware::google::pixelstats::V1_0::IPixelStats follow. Return<void> PixelStats::reportUsbConnectorConnected() { // Ratelimit to max 20 / 24hrs (expected 0/24hrs) if (rateLimit(android::metricslogger::ACTION_USB_CONNECTOR_CONNECTED, 20)) return Void(); logIntAction(android::metricslogger::ACTION_USB_CONNECTOR_CONNECTED); return Void(); } Return<void> PixelStats::reportUsbConnectorDisconnected(int32_t durationMillis) { // Ratelimit to max 20 / 24hrs (expected 0/24hrs) if (rateLimit(android::metricslogger::ACTION_USB_CONNECTOR_DISCONNECTED, 20)) return Void(); logIntAction(android::metricslogger::ACTION_USB_CONNECTOR_DISCONNECTED, android::metricslogger::FIELD_DURATION_MILLIS, durationMillis); return Void(); } Return<void> PixelStats::reportUsbAudioConnected(int32_t vid, int32_t pid) { // Ratelimit to max 20 / 24hrs (expected 0/24hrs) if (rateLimit(android::metricslogger::ACTION_USB_AUDIO_CONNECTED, 20)) return Void(); logIntAction(android::metricslogger::ACTION_USB_AUDIO_CONNECTED, android::metricslogger::FIELD_USB_AUDIO_VIDPID, (vid << 16) | pid); return Void(); } Return<void> PixelStats::reportUsbAudioDisconnected(int32_t vid, int32_t pid, int32_t durationMillis) { // Ratelimit to max 20 / 24hrs (expected 0/24hrs) if (rateLimit(android::metricslogger::ACTION_USB_AUDIO_DISCONNECTED, 20)) return Void(); logIntAction(android::metricslogger::ACTION_USB_AUDIO_DISCONNECTED, FIELD_USB_AUDIO_VIDPID, (vid << 16) | pid, android::metricslogger::FIELD_DURATION_MILLIS, durationMillis); return Void(); } Return<void> PixelStats::reportSpeakerImpedance(int32_t speakerLocation, int32_t milliOhms) { // Ratelimit to max 2 / 24hrs (expected 1/24hrs) if (rateLimit(android::metricslogger::ACTION_SPEAKER_IMPEDANCE, 2)) return Void(); logIntAction(android::metricslogger::ACTION_SPEAKER_IMPEDANCE, FIELD_SPEAKER_LOCATION, speakerLocation, FIELD_SPEAKER_IMPEDANCE_MILLIOHMS, milliOhms); return Void(); } static android::metricslogger::HardwareType toMetricsLoggerHardwareType( IPixelStats::HardwareType pixelstatsType) { switch (pixelstatsType) { case IPixelStats::HardwareType::MICROPHONE: return android::metricslogger::HardwareType::HARDWARE_MICROPHONE; case IPixelStats::HardwareType::CODEC: return android::metricslogger::HardwareType::HARDWARE_CODEC; case IPixelStats::HardwareType::SPEAKER: return android::metricslogger::HardwareType::HARDWARE_SPEAKER; case IPixelStats::HardwareType::FINGERPRINT: return android::metricslogger::HardwareType::HARDWARE_FINGERPRINT; case IPixelStats::HardwareType::UNKNOWN: default: return android::metricslogger::HardwareType::HARDWARE_UNKNOWN; } } static android::metricslogger::HardwareFailureCode toMetricsLoggerHardwareFailure( IPixelStats::HardwareErrorCode pixelstatsError) { switch (pixelstatsError) { case IPixelStats::HardwareErrorCode::COMPLETE: return HARDWARE_FAILURE_COMPLETE; case IPixelStats::HardwareErrorCode::SPEAKER_HIGH_Z: return HARDWARE_FAILURE_SPEAKER_HIGH_Z; case IPixelStats::HardwareErrorCode::SPEAKER_SHORT: return HARDWARE_FAILURE_SPEAKER_SHORT; case IPixelStats::HardwareErrorCode::FINGERPRINT_SENSOR_BROKEN: return HARDWARE_FAILURE_FINGERPRINT_SENSOR_BROKEN; case IPixelStats::HardwareErrorCode::FINGERPRINT_TOO_MANY_DEAD_PIXELS: return HARDWARE_FAILURE_FINGERPRINT_TOO_MANY_DEAD_PIXELS; case IPixelStats::HardwareErrorCode::UNKNOWN: default: return HARDWARE_FAILURE_UNKNOWN; } } Return<void> PixelStats::reportHardwareFailed(HardwareType hardwareType, int32_t hardwareLocation, HardwareErrorCode errorCode) { // Ratelimit to max 15 / 24hrs (expected 0/24hrs) if (rateLimit(android::metricslogger::ACTION_HARDWARE_FAILED, 15)) return Void(); logIntAction(ACTION_HARDWARE_FAILED, FIELD_HARDWARE_TYPE, toMetricsLoggerHardwareType(hardwareType), FIELD_HARDWARE_LOCATION, hardwareLocation, FIELD_HARDWARE_FAILURE_CODE, toMetricsLoggerHardwareFailure(errorCode)); return Void(); } Return<void> PixelStats::reportPhysicalDropDetected(int32_t confidencePctg, int32_t accelPeak, int32_t freefallDurationMs) { // Ratelimit to max 10 / 24hrs (expected 0/24hrs) if (rateLimit(android::metricslogger::ACTION_PHYSICAL_DROP, 10)) return Void(); logIntAction(ACTION_PHYSICAL_DROP, FIELD_CONFIDENCE_PERCENT, confidencePctg, FIELD_ACCEL_MILLI_G, accelPeak, FIELD_DURATION_MILLIS, freefallDurationMs); return Void(); } Return<void> PixelStats::reportChargeCycles(const hidl_string& buckets) { // Ratelimit to max 2 / 24hrs (expected 1/24hrs) if (rateLimit(android::metricslogger::ACTION_BATTERY_CHARGE_CYCLES, 2)) return Void(); LogMultiAction(ACTION_BATTERY_CHARGE_CYCLES, FIELD_BATTERY_CHARGE_CYCLES, buckets); return Void(); } static android::metricslogger::IoOperation toMetricsLoggerIoOperation(IPixelStats::IoOperation op) { switch (op) { default: case IPixelStats::IoOperation::UNKNOWN: return android::metricslogger::IoOperation::IOOP_UNKNOWN; case IPixelStats::IoOperation::READ: return android::metricslogger::IoOperation::IOOP_READ; case IPixelStats::IoOperation::WRITE: return android::metricslogger::IoOperation::IOOP_WRITE; case IPixelStats::IoOperation::UNMAP: return android::metricslogger::IoOperation::IOOP_UNMAP; case IPixelStats::IoOperation::SYNC: return android::metricslogger::IoOperation::IOOP_SYNC; } } Return<void> PixelStats::reportSlowIo(IoOperation operation, int32_t count) { // Ratelimit to max 2 per 24hrs if (rateLimit(android::metricslogger::ACTION_SLOW_IO, 2)) return Void(); logIntAction(ACTION_SLOW_IO, FIELD_IO_OPERATION_TYPE, toMetricsLoggerIoOperation(operation), FIELD_IO_OPERATION_COUNT, count); return Void(); } Return<void> PixelStats::reportBatteryHealthSnapshot(const BatteryHealthSnapshotArgs& args) { // Ratelimit to max 2 per 24hrs if (rateLimit(android::metricslogger::ACTION_BATTERY_HEALTH, 2)) return Void(); logIntAction(ACTION_BATTERY_HEALTH, FIELD_BATTERY_HEALTH_SNAPSHOT_TYPE, (int32_t)args.type, FIELD_BATTERY_TEMPERATURE_DECI_C, args.temperatureDeciC, FIELD_BATTERY_VOLTAGE_UV, args.voltageMicroV, FIELD_BATTERY_CURRENT_UA, args.currentMicroA, FIELD_BATTERY_OPEN_CIRCUIT_VOLTAGE_UV, args.openCircuitVoltageMicroV, FIELD_BATTERY_RESISTANCE_UOHMS, args.resistanceMicroOhm, FIELD_END_BATTERY_PERCENT, args.levelPercent); return Void(); } Return<void> PixelStats::reportBatteryCausedShutdown(int32_t voltageMicroV) { // Ratelimit to max 5 per 24hrs if (rateLimit(android::metricslogger::ACTION_BATTERY_CAUSED_SHUTDOWN, 5)) return Void(); logIntAction(ACTION_BATTERY_CAUSED_SHUTDOWN, FIELD_BATTERY_VOLTAGE_UV, voltageMicroV); return Void(); } bool PixelStats::rateLimit(int action, int limit) { if (limiter_.RateLimit(action, limit)) { ALOGE("Rate limited action %d\n", action); return true; } return false; } } // namespace implementation } // namespace V1_0 } // namespace pixelstats } // namespace google } // namespace hardware