0

arc: Implement ANR metrics.

This reports ANR events. The main purpose of use it is the context of
ANR reduce project to utilize UMA functionality to track improvements
and conduct Finch experiments.
Android part: ag/14415327

BUG=b:187112142
TEST=Locally, modified framework timeouts to easy cause ANRs and confirm
     they appear in chrome://histograms

Change-Id: Ide6ae234923b4bd1bbed942a3a4065d71a0e8792
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2869972
Commit-Queue: Yury Khmel <khmel@chromium.org>
Reviewed-by: Jesse Doherty <jwd@chromium.org>
Reviewed-by: Yusuke Sato <yusukes@chromium.org>
Reviewed-by: Alan Ding <alanding@chromium.org>
Reviewed-by: Elijah Taylor <elijahtaylor@chromium.org>
Reviewed-by: Greg Levin <glevin@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#881313}
This commit is contained in:
Yury Khmel
2021-05-10 23:45:49 +00:00
committed by Chromium LUCI CQ
parent fe90f985ad
commit 35a0bf80de
6 changed files with 220 additions and 2 deletions

@ -44,6 +44,40 @@ constexpr char kGmsProcessNamePrefix[] = "com.google.android.gms";
constexpr char kBootProgressEnableScreen[] = "boot_progress_enable_screen";
constexpr char kBootProgressArcUpgraded[] = "boot_progress_arc_upgraded";
// App types to report.
constexpr char kAppTypeArcAppLauncher[] = "ArcAppLauncher";
constexpr char kAppTypeArcOther[] = "ArcOther";
constexpr char kAppTypeFirstParty[] = "FirstParty";
constexpr char kAppTypeGmsCore[] = "GmsCore";
constexpr char kAppTypePlayStore[] = "PlayStore";
constexpr char kAppTypeSystemServer[] = "SystemServer";
constexpr char kAppTypeSystem[] = "SystemApp";
constexpr char kAppTypeOther[] = "Other";
std::string AnrSourceToTableName(mojom::AnrSource value) {
switch (value) {
case mojom::AnrSource::OTHER:
return kAppTypeOther;
case mojom::AnrSource::SYSTEM_SERVER:
return kAppTypeSystemServer;
case mojom::AnrSource::SYSTEM_APP:
return kAppTypeSystem;
case mojom::AnrSource::GMS_CORE:
return kAppTypeGmsCore;
case mojom::AnrSource::PLAY_STORE:
return kAppTypePlayStore;
case mojom::AnrSource::FIRST_PARTY:
return kAppTypeFirstParty;
case mojom::AnrSource::ARC_OTHER:
return kAppTypeArcOther;
case mojom::AnrSource::ARC_APP_LAUNCHER:
return kAppTypeArcAppLauncher;
default:
LOG(ERROR) << "Unrecognized source ANR " << value;
return kAppTypeOther;
}
}
std::string BootTypeToString(mojom::BootType boot_type) {
switch (boot_type) {
case mojom::BootType::UNKNOWN:
@ -369,6 +403,14 @@ void ArcMetricsService::ReportClipboardDragDropEvent(
base::UmaHistogramEnumeration("Arc.ClipboardDragDrop", event_type);
}
void ArcMetricsService::ReportAnr(mojom::AnrPtr anr) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::UmaHistogramEnumeration("Arc.Anr.Overall", anr->type);
base::UmaHistogramEnumeration("Arc.Anr." + AnrSourceToTableName(anr->source),
anr->type);
}
void ArcMetricsService::OnWindowActivated(
wm::ActivationChangeObserver::ActivationReason reason,
aura::Window* gained_active,

@ -109,6 +109,7 @@ class ArcMetricsService : public KeyedService,
void ReportArcCorePriAbiMigBootTime(base::TimeDelta duration) override;
void ReportClipboardDragDropEvent(
mojom::ArcClipboardDragDropEvent event_type) override;
void ReportAnr(mojom::AnrPtr anr) override;
// wm::ActivationChangeObserver overrides.
// Records to UMA when a user has interacted with an ARC app window.

@ -6,12 +6,15 @@
#include <algorithm>
#include <array>
#include <map>
#include <utility>
#include <vector>
#include "ash/public/cpp/app_types.h"
#include "base/metrics/histogram_samples.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "chromeos/dbus/session_manager/fake_session_manager_client.h"
#include "components/arc/arc_prefs.h"
@ -46,6 +49,46 @@ constexpr std::array<const char*, 11> kBootEvents{
constexpr const char kBootProgressArcUpgraded[] = "boot_progress_arc_upgraded";
constexpr char kAppTypeArcAppLauncher[] = "ArcAppLauncher";
constexpr char kAppTypeArcOther[] = "ArcOther";
constexpr char kAppTypeFirstParty[] = "FirstParty";
constexpr char kAppTypeGmsCore[] = "GmsCore";
constexpr char kAppTypePlayStore[] = "PlayStore";
constexpr char kAppTypeSystemServer[] = "SystemServer";
constexpr char kAppTypeSystem[] = "SystemApp";
constexpr char kAppTypeOther[] = "Other";
constexpr char kAppOverall[] = "Overall";
constexpr std::array<const char*, 9> kAppTypes{
kAppTypeArcAppLauncher, kAppTypeArcOther, kAppTypeFirstParty,
kAppTypeGmsCore, kAppTypePlayStore, kAppTypeSystemServer,
kAppTypeSystem, kAppTypeOther, kAppOverall,
};
std::string CreateAnrKey(const std::string& app_type, mojom::AnrType type) {
std::stringstream output;
output << app_type << "/" << type;
return output.str();
}
mojom::AnrPtr GetAnr(mojom::AnrSource source, mojom::AnrType type) {
return mojom::Anr::New(type, source);
}
void VerifyAnr(const base::HistogramTester& tester,
const std::map<std::string, int>& expectation) {
std::map<std::string, int> current;
for (const char* app_type : kAppTypes) {
const std::vector<base::Bucket> buckets =
tester.GetAllSamples("Arc.Anr." + std::string(app_type));
for (const auto& bucket : buckets) {
current[CreateAnrKey(app_type, static_cast<mojom::AnrType>(bucket.min))] =
bucket.count;
}
}
EXPECT_EQ(expectation, current);
}
class ArcMetricsServiceTest : public testing::Test {
protected:
ArcMetricsServiceTest() {
@ -344,5 +387,61 @@ TEST_F(ArcMetricsServiceTest, UserInteractionObserver) {
service()->RemoveUserInteractionObserver(&observer);
}
TEST_F(ArcMetricsServiceTest, ArcAnr) {
base::HistogramTester tester;
std::map<std::string, int> expectation;
service()->ReportAnr(
GetAnr(mojom::AnrSource::OTHER, mojom::AnrType::UNKNOWN));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::UNKNOWN)] = 1;
expectation[CreateAnrKey(kAppTypeOther, mojom::AnrType::UNKNOWN)] = 1;
VerifyAnr(tester, expectation);
service()->ReportAnr(
GetAnr(mojom::AnrSource::SYSTEM_SERVER, mojom::AnrType::INPUT));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::INPUT)] = 1;
expectation[CreateAnrKey(kAppTypeSystemServer, mojom::AnrType::INPUT)] = 1;
VerifyAnr(tester, expectation);
service()->ReportAnr(
GetAnr(mojom::AnrSource::SYSTEM_SERVER, mojom::AnrType::SERVICE));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::SERVICE)] = 1;
expectation[CreateAnrKey(kAppTypeSystemServer, mojom::AnrType::SERVICE)] = 1;
VerifyAnr(tester, expectation);
service()->ReportAnr(
GetAnr(mojom::AnrSource::GMS_CORE, mojom::AnrType::BROADCAST));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::BROADCAST)] = 1;
expectation[CreateAnrKey(kAppTypeGmsCore, mojom::AnrType::BROADCAST)] = 1;
VerifyAnr(tester, expectation);
service()->ReportAnr(
GetAnr(mojom::AnrSource::PLAY_STORE, mojom::AnrType::CONTENT_PROVIDER));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::CONTENT_PROVIDER)] = 1;
expectation[CreateAnrKey(kAppTypePlayStore,
mojom::AnrType::CONTENT_PROVIDER)] = 1;
VerifyAnr(tester, expectation);
service()->ReportAnr(
GetAnr(mojom::AnrSource::FIRST_PARTY, mojom::AnrType::APP_REQUESTED));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::APP_REQUESTED)] = 1;
expectation[CreateAnrKey(kAppTypeFirstParty, mojom::AnrType::APP_REQUESTED)] =
1;
VerifyAnr(tester, expectation);
service()->ReportAnr(
GetAnr(mojom::AnrSource::ARC_OTHER, mojom::AnrType::INPUT));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::INPUT)] = 2;
expectation[CreateAnrKey(kAppTypeArcOther, mojom::AnrType::INPUT)] = 1;
VerifyAnr(tester, expectation);
service()->ReportAnr(
GetAnr(mojom::AnrSource::ARC_APP_LAUNCHER, mojom::AnrType::SERVICE));
expectation[CreateAnrKey(kAppOverall, mojom::AnrType::SERVICE)] = 2;
expectation[CreateAnrKey(kAppTypeArcAppLauncher, mojom::AnrType::SERVICE)] =
1;
VerifyAnr(tester, expectation);
}
} // namespace
} // namespace arc

@ -1,12 +1,56 @@
// Copyright 2016 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.
// Next MinVersion: 9
// Next MinVersion: 10
module arc.mojom;
import "mojo/public/mojom/base/time.mojom";
[Extensible]
enum AnrType {
// Other types of ANR which are not explicitly defined.
UNKNOWN = 0,
// ANR while handling input events.
INPUT = 1,
// ANR in services.
SERVICE = 2,
// ANR in broadcasts.
BROADCAST = 3,
// ANR in content provider.
CONTENT_PROVIDER = 4,
// App custom ANR.
APP_REQUESTED = 5,
};
[Extensible]
enum AnrSource {
// ANR coming from anything else than explicitly defined.
OTHER = 0,
// ANR coming from system server.
SYSTEM_SERVER = 1,
// ANR coming from system apps.
SYSTEM_APP = 2,
// ANR coming from GMS core.
GMS_CORE = 3,
// ANR coming from Play Store.
PLAY_STORE = 4,
// ANR coming from first party Google apps
FIRST_PARTY = 5,
// ANR coming from ARC apps other than explicitly defined.
ARC_OTHER = 6,
// ANR coming from ARC App launcher.
ARC_APP_LAUNCHER = 7,
};
// Describes an ANR event.
struct Anr {
// Type of ANR event.
AnrType type;
// ANR source.
AnrSource source;
};
[Extensible]
enum BootType {
// This is used only for backward compatibility reasons and the value has to
@ -152,7 +196,7 @@ enum ArcClipboardDragDropEvent {
kImageDragDropFromArc = 7,
};
// Next method ID: 9
// Next method ID: 10
interface MetricsHost {
// Reports boot progress events from ARC instance.
ReportBootProgress@0(array<BootProgressEvent> events,
@ -182,6 +226,9 @@ interface MetricsHost {
// Reports a clipboard / drag-and-drop event.
[MinVersion=8] ReportClipboardDragDropEvent@8(
ArcClipboardDragDropEvent event_type);
// Reports ANR event.
[MinVersion=9] ReportAnr@10(Anr anr);
};
// Next method ID: 3

@ -3469,6 +3469,16 @@ Unknown properties are collapsed to zero. -->
<int value="2" label="In Splitview"/>
</enum>
<enum name="ArcAnr">
<summary>Defines ARC ANR types.</summary>
<int value="0" label="Unknown">ANR type cannot be determined.</int>
<int value="1" label="Input">ANR while handling input event dispatching.</int>
<int value="2" label="Service">ANR in service.</int>
<int value="3" label="Broadcast">ANR handling broadcast.</int>
<int value="4" label="ContentProvider">ANR from ContentProvider.</int>
<int value="5" label="AppRequested">ANR requested explicitly by app.</int>
</enum>
<enum name="ArcAuthAccountCheckStatus">
<int value="0" label="Account is up to date"/>
<int value="1" label="New account"/>

@ -116,6 +116,25 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
<summary>The time elapsed for booting up the ARC instance.</summary>
</histogram>
<histogram name="Arc.Anr.{AnrSource}" enum="ArcAnr" expires_after="2022-05-01">
<owner>khmel@google.com</owner>
<owner>alanding@google.com</owner>
<summary>
Counts ANR events in the system separated by ANR type and {AnrSource}.
</summary>
<token key="AnrSource">
<variant name="ArcAppLauncher" summary="ARC App launcher."/>
<variant name="ArcOther" summary="Other ARC components."/>
<variant name="FirstParty" summary="First party Google apps."/>
<variant name="GmsCore" summary="GMS Core."/>
<variant name="Other" summary="Other apps."/>
<variant name="Overall" summary="Total statistics."/>
<variant name="PlayStore" summary="Play Store."/>
<variant name="Server" summary="System Server."/>
<variant name="System" summary="System components."/>
</token>
</histogram>
<histogram name="Arc.AppCount" units="units" expires_after="2021-10-17">
<owner>elijahtaylor@google.com</owner>
<owner>shihuis@google.com</owner>