123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- // Copyright 2021 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/metrics/stylus_metrics_recorder.h"
- #include <memory>
- #include <set>
- #include <string>
- #include "ash/system/power/peripheral_battery_listener.h"
- #include "ash/system/power/peripheral_battery_tests.h"
- #include "ash/test/ash_test_base.h"
- #include "base/containers/contains.h"
- #include "base/strings/string_piece.h"
- #include "base/strings/string_util.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "testing/gmock/include/gmock/gmock.h"
- using BatteryInfo = ash::PeripheralBatteryListener::BatteryInfo;
- namespace ash {
- namespace {
- const char kHistogramGarageSessionMetric[] =
- "ChromeOS.FeatureUsage.StylusDetachedFromGarageSession";
- const char kHistogramGarageSessionUsetimeMetric[] =
- "ChromeOS.FeatureUsage.StylusDetachedFromGarageSession.Usetime";
- const char kHistogramDockSessionMetric[] =
- "ChromeOS.FeatureUsage.StylusDetachedFromDockSession";
- const char kHistogramDockSessionUsetimeMetric[] =
- "ChromeOS.FeatureUsage.StylusDetachedFromDockSession.Usetime";
- const char kHistogramGarageOrDockSessionMetric[] =
- "ChromeOS.FeatureUsage.StylusDetachedFromGarageOrDockSession";
- const char kHistogramGarageOrDockSessionUsetimeMetric[] =
- "ChromeOS.FeatureUsage.StylusDetachedFromGarageOrDockSession.Usetime";
- enum class StylusChargingStyle { kDock, kGarage };
- std::string BatteryKey(StylusChargingStyle style) {
- return (style == StylusChargingStyle::kGarage) ? "garaged-stylus-charger"
- : "docked-stylus-charger";
- }
- // Test fixture for the StylusMetricsRecorder class.
- class StylusMetricsRecorderTest : public AshTestBase {
- public:
- StylusMetricsRecorderTest()
- : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
- StylusMetricsRecorderTest(const StylusMetricsRecorderTest&) = delete;
- StylusMetricsRecorderTest& operator=(const StylusMetricsRecorderTest&) =
- delete;
- ~StylusMetricsRecorderTest() override = default;
- // AshTestBase:
- void SetUp() override {
- AshTestBase::SetUp();
- stylus_metrics_recorder_ = std::make_unique<ash::StylusMetricsRecorder>();
- histogram_tester_ = std::make_unique<base::HistogramTester>();
- }
- void TearDown() override {
- stylus_metrics_recorder_.reset();
- AshTestBase::TearDown();
- }
- base::TimeTicks NowTicks() { return task_environment()->NowTicks(); }
- void AdvanceClock(base::TimeDelta delta) {
- task_environment()->AdvanceClock(delta);
- }
- BatteryInfo ConstructBatteryInfo(
- StylusChargingStyle style,
- BatteryInfo::ChargeStatus charge_status,
- bool battery_report_eligible = true,
- BatteryInfo::PeripheralType type =
- BatteryInfo::PeripheralType::kStylusViaCharger) {
- const std::string key = BatteryKey(style);
- const int level = 50;
- const std::u16string name = base::ASCIIToUTF16("name:" + key);
- const std::string btaddr = "";
- return BatteryInfo(key, name, level, battery_report_eligible, NowTicks(),
- type, charge_status, btaddr);
- }
- void SetChargerState(StylusChargingStyle style,
- BatteryInfo::ChargeStatus charge_status,
- bool battery_report_eligible = true,
- BatteryInfo::PeripheralType type =
- BatteryInfo::PeripheralType::kStylusViaCharger) {
- const BatteryInfo info = ConstructBatteryInfo(
- style, charge_status, battery_report_eligible, type);
- if (!base::Contains(known_batteries_, info.key)) {
- stylus_metrics_recorder_->OnAddingBattery(info);
- known_batteries_.insert(info.key);
- }
- stylus_metrics_recorder_->OnUpdatedBatteryLevel(info);
- }
- void RemoveCharger(StylusChargingStyle style,
- BatteryInfo::ChargeStatus charge_status,
- bool battery_report_eligible = true,
- BatteryInfo::PeripheralType type =
- BatteryInfo::PeripheralType::kStylusViaCharger) {
- const BatteryInfo info = ConstructBatteryInfo(
- style, charge_status, battery_report_eligible, type);
- if (base::Contains(known_batteries_, info.key)) {
- stylus_metrics_recorder_->OnRemovingBattery(info);
- known_batteries_.erase(info.key);
- }
- }
- protected:
- // The test target.
- std::unique_ptr<StylusMetricsRecorder> stylus_metrics_recorder_;
- // Used to verify recorded data.
- std::unique_ptr<base::HistogramTester> histogram_tester_;
- // Track whether batteries are known or need to be added.
- std::set<std::string> known_batteries_;
- };
- } // namespace
- // Verifies that histogram is not recorded when no events are received.
- TEST_F(StylusMetricsRecorderTest, Baseline) {
- histogram_tester_->ExpectTotalCount(kHistogramGarageSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramDockSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(
- kHistogramGarageOrDockSessionUsetimeMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramGarageSessionUsetimeMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramDockSessionUsetimeMetric, 0);
- histogram_tester_->ExpectTotalCount(
- kHistogramGarageOrDockSessionUsetimeMetric, 0);
- }
- TEST_F(StylusMetricsRecorderTest, BaselineStayInGarage) {
- const base::TimeDelta kTimeSpentCharging = base::Minutes(5);
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- AdvanceClock(kTimeSpentCharging);
- // By removing the battery, we force the stylus_metrics_recorder to close out
- // the session.
- RemoveCharger(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- histogram_tester_->ExpectTotalCount(kHistogramGarageSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramDockSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramGarageOrDockSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramGarageSessionUsetimeMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramDockSessionUsetimeMetric, 0);
- histogram_tester_->ExpectTotalCount(
- kHistogramGarageOrDockSessionUsetimeMetric, 0);
- }
- TEST_F(StylusMetricsRecorderTest, BaselineStayInDock) {
- const base::TimeDelta kTimeSpentCharging = base::Minutes(5);
- SetChargerState(StylusChargingStyle::kDock,
- BatteryInfo::ChargeStatus::kCharging);
- AdvanceClock(kTimeSpentCharging);
- // By removing the battery, we force the stylus_metrics_recorder to close out
- // the session.
- RemoveCharger(StylusChargingStyle::kDock,
- BatteryInfo::ChargeStatus::kCharging);
- histogram_tester_->ExpectTotalCount(kHistogramGarageSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramDockSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramGarageOrDockSessionMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramGarageSessionUsetimeMetric, 0);
- histogram_tester_->ExpectTotalCount(kHistogramDockSessionUsetimeMetric, 0);
- histogram_tester_->ExpectTotalCount(
- kHistogramGarageOrDockSessionUsetimeMetric, 0);
- }
- TEST_F(StylusMetricsRecorderTest, RemovedFromGarage) {
- const base::TimeDelta kTimeSpentInUse = base::Minutes(5);
- const base::TimeDelta kTimeSpentCharging = base::Minutes(1);
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kDischarging);
- AdvanceClock(kTimeSpentInUse);
- // By removing the battery, we force the stylus_metrics_recorder to close out
- // the session.
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- // Step time further when we're back on charge, to make sure this time is not
- // counted
- AdvanceClock(kTimeSpentCharging);
- RemoveCharger(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- histogram_tester_->ExpectTotalCount(kHistogramDockSessionMetric, 0);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageSessionMetric,
- static_cast<int>(
- feature_usage::FeatureUsageMetrics::Event::kUsedWithSuccess),
- 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEnabled), 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEligible),
- 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageOrDockSessionMetric,
- static_cast<int>(
- feature_usage::FeatureUsageMetrics::Event::kUsedWithSuccess),
- 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageOrDockSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEnabled), 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageOrDockSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEligible),
- 1);
- histogram_tester_->ExpectTimeBucketCount(kHistogramGarageSessionUsetimeMetric,
- kTimeSpentInUse, 1);
- histogram_tester_->ExpectTimeBucketCount(
- kHistogramGarageOrDockSessionUsetimeMetric, kTimeSpentInUse, 1);
- }
- TEST_F(StylusMetricsRecorderTest, RemovedFromDock) {
- const base::TimeDelta kTimeSpentInUse = base::Minutes(5);
- const base::TimeDelta kTimeSpentCharging = base::Minutes(1);
- SetChargerState(StylusChargingStyle::kDock,
- BatteryInfo::ChargeStatus::kDischarging);
- AdvanceClock(kTimeSpentInUse);
- // By removing the battery, we force the stylus_metrics_recorder to close out
- // the session.
- SetChargerState(StylusChargingStyle::kDock,
- BatteryInfo::ChargeStatus::kCharging);
- // Step time further when we're back on charge, to make sure this time is not
- // counted
- AdvanceClock(kTimeSpentCharging);
- RemoveCharger(StylusChargingStyle::kDock,
- BatteryInfo::ChargeStatus::kCharging);
- histogram_tester_->ExpectTotalCount(kHistogramGarageSessionMetric, 0);
- histogram_tester_->ExpectBucketCount(
- kHistogramDockSessionMetric,
- static_cast<int>(
- feature_usage::FeatureUsageMetrics::Event::kUsedWithSuccess),
- 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramDockSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEnabled), 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramDockSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEligible),
- 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageOrDockSessionMetric,
- static_cast<int>(
- feature_usage::FeatureUsageMetrics::Event::kUsedWithSuccess),
- 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageOrDockSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEnabled), 1);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageOrDockSessionMetric,
- static_cast<int>(feature_usage::FeatureUsageMetrics::Event::kEligible),
- 1);
- histogram_tester_->ExpectTimeBucketCount(kHistogramDockSessionUsetimeMetric,
- kTimeSpentInUse, 1);
- histogram_tester_->ExpectTimeBucketCount(
- kHistogramGarageOrDockSessionUsetimeMetric, kTimeSpentInUse, 1);
- }
- TEST_F(StylusMetricsRecorderTest, ShutdownWhileStylusRemoved) {
- const base::TimeDelta kTimeSpentInUse = base::Minutes(5);
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kDischarging);
- AdvanceClock(kTimeSpentInUse);
- // By removing the battery, we force the stylus_metrics_recorder to close out
- // the session.
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- // Just destroy the recorder, without replacing the stylus; we should still
- // see the time recorded
- stylus_metrics_recorder_.reset();
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageSessionMetric,
- static_cast<int>(
- feature_usage::FeatureUsageMetrics::Event::kUsedWithSuccess),
- 1);
- histogram_tester_->ExpectTimeBucketCount(kHistogramGarageSessionUsetimeMetric,
- kTimeSpentInUse, 1);
- }
- TEST_F(StylusMetricsRecorderTest, StylusUsageOverMultipleDays) {
- const base::TimeDelta kTimeSpentInUse = base::Hours(48);
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kDischarging);
- AdvanceClock(kTimeSpentInUse);
- RemoveCharger(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageSessionMetric,
- static_cast<int>(
- feature_usage::FeatureUsageMetrics::Event::kUsedWithSuccess),
- 1);
- histogram_tester_->ExpectTimeBucketCount(kHistogramGarageSessionUsetimeMetric,
- kTimeSpentInUse, 1);
- }
- TEST_F(StylusMetricsRecorderTest, StylusChargeSequencing) {
- const base::TimeDelta kTimeSpentTrickleCharging = base::Minutes(1);
- const base::TimeDelta kTimeSpentCharging = base::Minutes(60);
- const base::TimeDelta kTimeSpentFull = base::Minutes(5);
- const base::TimeDelta kTimeSpentDischarging = base::Minutes(60);
- const int kCycles = 2;
- // Initial state, stylus is garage, charging, not in use
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- for (int cycle = 0; cycle < kCycles; cycle++) {
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- AdvanceClock(kTimeSpentTrickleCharging);
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- AdvanceClock(kTimeSpentCharging);
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kFull);
- AdvanceClock(kTimeSpentFull);
- // Stylus is removed from garage when it starts discharging
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kDischarging);
- AdvanceClock(kTimeSpentDischarging);
- }
- // Final state, same as initial
- SetChargerState(StylusChargingStyle::kGarage,
- BatteryInfo::ChargeStatus::kCharging);
- histogram_tester_->ExpectBucketCount(
- kHistogramGarageSessionMetric,
- static_cast<int>(
- feature_usage::FeatureUsageMetrics::Event::kUsedWithSuccess),
- kCycles);
- histogram_tester_->ExpectTimeBucketCount(kHistogramGarageSessionUsetimeMetric,
- kTimeSpentDischarging, kCycles);
- }
- } // namespace ash
|