0

[CrOS Cellular] Emit DBus results for eSIM installation attempts

This CL makes changes to log DBus results as a new metric for all eSIM
installation attempts. DBus results are only logged when we receive an
unknown response code from Hermes.

Bug: b/293524299
Change-Id: Id946c0a061dd31f1498a8d09eed937ed16c99711
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4714407
Reviewed-by: Chad Duffin <chadduffin@chromium.org>
Reviewed-by: Steven Bennetts <stevenjb@chromium.org>
Commit-Queue: Nikhil Nayunigari <nikhilcn@google.com>
Cr-Commit-Position: refs/heads/main@{#1176393}
This commit is contained in:
Nikhil Nayunigari
2023-07-28 01:41:56 +00:00
committed by Chromium LUCI CQ
parent ff1737b7d8
commit 1ede90c26d
16 changed files with 437 additions and 72 deletions

@ -32,6 +32,7 @@ namespace {
const char* kDefaultMccMnc = "310999";
const char* kFakeActivationCodePrefix = "1$SMDP.GSMA.COM$00000-00000-00000-000";
const char* kActivationCodeToTriggerDBusError = "no_memory";
const char* kFakeProfilePathPrefix = "/org/chromium/Hermes/Profile/";
const char* kFakeIccidPrefix = "10000000000000000";
const char* kFakeProfileNamePrefix = "FakeCellularNetwork_";
@ -363,6 +364,10 @@ std::string FakeHermesEuiccClient::GenerateFakeActivationCode() {
fake_profile_counter_++);
}
std::string FakeHermesEuiccClient::GetDBusErrorActivationCode() {
return kActivationCodeToTriggerDBusError;
}
bool FakeHermesEuiccClient::GetLastRefreshProfilesRestoreSlotArg() {
return last_restore_slot_arg_;
}
@ -374,6 +379,7 @@ void FakeHermesEuiccClient::InstallProfileFromActivationCode(
InstallCarrierProfileCallback callback) {
if (next_install_profile_result_.has_value()) {
std::move(callback).Run(next_install_profile_result_.value(),
dbus::DBusResult::kSuccess,
/*carrier_profile_path=*/nullptr);
next_install_profile_result_ = absl::nullopt;
return;
@ -492,15 +498,22 @@ void FakeHermesEuiccClient::DoInstallProfileFromActivationCode(
DVLOG(1) << "Installing profile from activation code: code="
<< activation_code << ", confirmation_code=" << confirmation_code;
if (!error_status_queue_.empty()) {
std::move(callback).Run(error_status_queue_.front(), nullptr);
std::move(callback).Run(error_status_queue_.front(),
dbus::DBusResult::kSuccess, nullptr);
error_status_queue_.pop();
return;
}
if (activation_code == kActivationCodeToTriggerDBusError) {
std::move(callback).Run(HermesResponseStatus::kErrorUnknownResponse,
dbus::DBusResult::kErrorNoMemory, nullptr);
return;
}
if (!base::StartsWith(activation_code, kFakeActivationCodePrefix,
base::CompareCase::SENSITIVE)) {
std::move(callback).Run(HermesResponseStatus::kErrorInvalidActivationCode,
nullptr);
dbus::DBusResult::kSuccess, nullptr);
return;
}
@ -526,7 +539,8 @@ void FakeHermesEuiccClient::DoInstallProfileFromActivationCode(
}
CreateCellularService(euicc_path, profile_path);
std::move(callback).Run(HermesResponseStatus::kSuccess, &profile_path);
std::move(callback).Run(HermesResponseStatus::kSuccess,
dbus::DBusResult::kSuccess, &profile_path);
}
void FakeHermesEuiccClient::DoInstallPendingProfile(

@ -70,6 +70,7 @@ class COMPONENT_EXPORT(HERMES_CLIENT) FakeHermesEuiccClient
std::vector<dbus::ObjectPath> profiles) override;
void SetInteractiveDelay(base::TimeDelta delay) override;
std::string GenerateFakeActivationCode() override;
std::string GetDBusErrorActivationCode() override;
bool GetLastRefreshProfilesRestoreSlotArg() override;
// HermesEuiccClient:

@ -13,6 +13,7 @@
#include "chromeos/ash/components/dbus/hermes/hermes_response_status.h"
#include "components/device_event_log/device_event_log.h"
#include "dbus/bus.h"
#include "dbus/dbus_result.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
@ -205,7 +206,7 @@ class HermesEuiccClientImpl : public HermesEuiccClient {
<< error_response->GetErrorName();
std::move(callback).Run(
HermesResponseStatusFromErrorName(error_response->GetErrorName()),
nullptr);
GetResult(error_response), nullptr);
return;
}
@ -213,14 +214,16 @@ class HermesEuiccClientImpl : public HermesEuiccClient {
// No Error or Response received.
NET_LOG(ERROR) << "Carrier profile installation Error: No error or "
"response received.";
std::move(callback).Run(HermesResponseStatus::kErrorNoResponse, nullptr);
std::move(callback).Run(HermesResponseStatus::kErrorNoResponse,
dbus::DBusResult::kErrorNoReply, nullptr);
return;
}
dbus::MessageReader reader(response);
dbus::ObjectPath profile_path;
reader.PopObjectPath(&profile_path);
std::move(callback).Run(HermesResponseStatus::kSuccess, &profile_path);
std::move(callback).Run(HermesResponseStatus::kSuccess,
dbus::DBusResult::kSuccess, &profile_path);
}
void OnRefreshSmdxProfilesResponse(RefreshSmdxProfilesCallback callback,

@ -14,6 +14,7 @@
#include "base/observer_list.h"
#include "chromeos/ash/components/dbus/hermes/hermes_response_status.h"
#include "chromeos/dbus/common/dbus_method_call_status.h"
#include "dbus/dbus_result.h"
#include "dbus/property.h"
#include "third_party/cros_system_api/dbus/hermes/dbus-constants.h"
@ -26,6 +27,7 @@ class COMPONENT_EXPORT(HERMES_CLIENT) HermesEuiccClient {
// and the object path for the profile that was just successfully installed.
using InstallCarrierProfileCallback =
base::OnceCallback<void(HermesResponseStatus status,
dbus::DBusResult result,
const dbus::ObjectPath* carrier_profile_path)>;
// Callback for the RefreshSmdxProfiles(). Callback returns the status code
@ -130,6 +132,10 @@ class COMPONENT_EXPORT(HERMES_CLIENT) HermesEuiccClient {
// a new fake carrier profile.
virtual std::string GenerateFakeActivationCode() = 0;
// Returns an activation code that will trigger no memory error from DBUS
// upon attempts to activate it.
virtual std::string GetDBusErrorActivationCode() = 0;
// Returns true when the last call to RefreshInstalledProfiles was requested
// with |restore_slot| set to true.
virtual bool GetLastRefreshProfilesRestoreSlotArg() = 0;

@ -161,10 +161,13 @@ void CopyRefreshSmdxProfilesResult(
}
void CopyInstallResult(HermesResponseStatus* dest_status,
dbus::DBusResult* dest_dbus_result,
dbus::ObjectPath* dest_path,
HermesResponseStatus status,
dbus::DBusResult dbus_result,
const dbus::ObjectPath* carrier_profile_path) {
*dest_status = status;
*dest_dbus_result = dbus_result;
if (carrier_profile_path) {
*dest_path = *carrier_profile_path;
}
@ -237,10 +240,11 @@ TEST_F(HermesEuiccClientTest, TestInstallProfileFromActivationCode) {
MatchInstallFromActivationCodeCall(kTestActivationCode,
kTestConfirmationCode),
_, _))
.Times(2)
.Times(3)
.WillRepeatedly(Invoke(this, &HermesEuiccClientTest::OnMethodCalled));
HermesResponseStatus install_status;
dbus::DBusResult dbus_result;
dbus::ObjectPath installed_profile_path(kInvalidPath);
// Verify that client makes corresponding dbus method call with
@ -251,10 +255,11 @@ TEST_F(HermesEuiccClientTest, TestInstallProfileFromActivationCode) {
AddPendingMethodCallResult(std::move(response), nullptr);
client_->InstallProfileFromActivationCode(
test_euicc_path, kTestActivationCode, kTestConfirmationCode,
base::BindOnce(&CopyInstallResult, &install_status,
base::BindOnce(&CopyInstallResult, &install_status, &dbus_result,
&installed_profile_path));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(install_status, HermesResponseStatus::kSuccess);
EXPECT_EQ(dbus_result, dbus::DBusResult::kSuccess);
EXPECT_EQ(installed_profile_path, test_carrier_path);
// Verify that error responses are returned properly.
@ -265,11 +270,25 @@ TEST_F(HermesEuiccClientTest, TestInstallProfileFromActivationCode) {
AddPendingMethodCallResult(nullptr, std::move(error_response));
client_->InstallProfileFromActivationCode(
test_euicc_path, kTestActivationCode, kTestConfirmationCode,
base::BindOnce(&CopyInstallResult, &install_status,
base::BindOnce(&CopyInstallResult, &install_status, &dbus_result,
&installed_profile_path));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(install_status, HermesResponseStatus::kErrorInvalidActivationCode);
EXPECT_EQ(dbus_result, dbus::DBusResult::kErrorUnknown);
EXPECT_EQ(installed_profile_path.value(), kInvalidPath);
// Verify that dbus errors are captured properly.
installed_profile_path = dbus::ObjectPath(kInvalidPath);
error_response = dbus::ErrorResponse::FromMethodCall(
&method_call, DBUS_ERROR_LIMITS_EXCEEDED, "");
AddPendingMethodCallResult(nullptr, std::move(error_response));
client_->InstallProfileFromActivationCode(
test_euicc_path, kTestActivationCode, kTestConfirmationCode,
base::BindOnce(&CopyInstallResult, &install_status, &dbus_result,
&installed_profile_path));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(install_status, HermesResponseStatus::kErrorUnknownResponse);
EXPECT_EQ(dbus_result, dbus::DBusResult::kErrorLimitsExceeded);
}
TEST_F(HermesEuiccClientTest, TestInstallPendingProfile) {

@ -213,8 +213,9 @@ void CellularESimInstaller::OnProfileInstallResult(
bool is_initial_install,
bool is_install_via_qr_code,
HermesResponseStatus status,
dbus::DBusResult dbusResult,
const dbus::ObjectPath* profile_path) {
hermes_metrics::LogInstallViaQrCodeResult(status);
hermes_metrics::LogInstallViaQrCodeResult(status, dbusResult);
bool is_managed = IsManagedNetwork(new_shill_properties);
if (status != HermesResponseStatus::kSuccess) {

@ -14,6 +14,7 @@
#include "chromeos/ash/components/dbus/hermes/hermes_response_status.h"
#include "chromeos/ash/components/network/cellular_esim_profile_handler.h"
#include "chromeos/ash/components/network/cellular_inhibitor.h"
#include "dbus/dbus_result.h"
namespace dbus {
class ObjectPath;
@ -154,6 +155,7 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) CellularESimInstaller {
bool is_initial_install,
bool is_install_via_qr_code,
HermesResponseStatus status,
dbus::DBusResult dbus_result,
const dbus::ObjectPath* object_path);
void OnShillConfigurationCreationSuccess(
ConfigureESimServiceCallback callback,

@ -47,6 +47,8 @@ const char kTestEid[] = "12345678901234567890123456789012";
const char kTestCellularServicePath[] = "/service/cellular101";
const char kInstallViaQrCodeHistogram[] =
"Network.Cellular.ESim.InstallViaQrCode.Result";
const char kInstallViaQrCodeDBusResultHistogram[] =
"Network.Cellular.ESim.InstallViaQrCode.DBusResult";
const char kESimInstallNonUserErrorSuccessRate[] =
"Network.Cellular.ESim.Installation.NonUserErrorSuccessRate";
@ -249,6 +251,10 @@ class CellularESimInstallerTest : public testing::Test {
HistogramTesterPtr()->ExpectBucketCount(
kESimInstallNonUserErrorSuccessRate, expected_hermes_status, 0);
}
if (expected_hermes_status != HermesResponseStatus::kErrorUnknownResponse) {
HistogramTesterPtr()->ExpectTotalCount(
kInstallViaQrCodeDBusResultHistogram, 0);
}
}
void CheckDetailedESimInstallHistograms(
@ -354,6 +360,25 @@ TEST_F(CellularESimInstallerTest, InstallProfileInvalidActivationCode) {
kInstallViaPolicyRetryOperationHistogram, 0);
}
TEST_F(CellularESimInstallerTest, InstallProfileDBusError) {
InstallResultTuple result_tuple = InstallProfileFromActivationCode(
HermesEuiccClient::Get()
->GetTestInterface()
->GetDBusErrorActivationCode(),
/*confirmation_code=*/std::string(),
/*euicc_path=*/dbus::ObjectPath(kTestEuiccPath),
/*new_shill_properties=*/base::Value::Dict(),
/*wait_for_connect=*/false, /*fail_connect=*/false);
HistogramTesterPtr()->ExpectTotalCount(kInstallViaQrCodeDBusResultHistogram,
1);
HistogramTesterPtr()->ExpectBucketCount(kInstallViaQrCodeDBusResultHistogram,
dbus::DBusResult::kErrorNoMemory, 1);
HistogramTesterPtr()->ExpectBucketCount(
kInstallViaQrCodeHistogram, HermesResponseStatus::kErrorUnknownResponse,
1);
}
TEST_F(CellularESimInstallerTest, InstallProfileConnectFailure) {
// Verify that connect failures are handled properly.
InstallResultTuple result_tuple = InstallProfileFromActivationCode(

@ -11,10 +11,16 @@
namespace ash::hermes_metrics {
void LogInstallViaQrCodeResult(HermesResponseStatus status) {
void LogInstallViaQrCodeResult(HermesResponseStatus status,
dbus::DBusResult dbusResult) {
base::UmaHistogramEnumeration("Network.Cellular.ESim.InstallViaQrCode.Result",
status);
if (status == HermesResponseStatus::kErrorUnknownResponse) {
base::UmaHistogramEnumeration(
"Network.Cellular.ESim.InstallViaQrCode.DBusResult", dbusResult);
}
if (status == HermesResponseStatus::kSuccess ||
!base::Contains(kHermesUserErrorCodes, status)) {
base::UmaHistogramEnumeration(

@ -8,11 +8,13 @@
#include "base/component_export.h"
#include "base/time/tick_clock.h"
#include "chromeos/ash/components/dbus/hermes/hermes_response_status.h"
#include "dbus/dbus_result.h"
namespace ash::hermes_metrics {
void COMPONENT_EXPORT(CHROMEOS_NETWORK)
LogInstallViaQrCodeResult(HermesResponseStatus status);
LogInstallViaQrCodeResult(HermesResponseStatus status,
dbus::DBusResult dbus_result);
void COMPONENT_EXPORT(CHROMEOS_NETWORK)
LogInstallPendingProfileResult(HermesResponseStatus status);

@ -14,6 +14,8 @@ component("dbus") {
"bus.cc",
"bus.h",
"dbus_export.h",
"dbus_result.cc",
"dbus_result.h",
"dbus_statistics.cc",
"dbus_statistics.h",
"error.cc",

211
dbus/dbus_result.cc Normal file

@ -0,0 +1,211 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "dbus/dbus_result.h"
#include "dbus/message.h"
namespace dbus {
DBusResult GetResult(dbus::ErrorResponse* response) {
if (!response) {
return DBusResult::kErrorResponseMissing;
}
const std::string& error_name = response->GetErrorName();
if (error_name == DBUS_ERROR_NO_REPLY) {
return DBusResult::kErrorNoReply;
}
if (error_name == DBUS_ERROR_TIMEOUT) {
return DBusResult::kErrorTimeout;
}
if (error_name == DBUS_ERROR_TIMED_OUT) {
return DBusResult::kErrorTimedOut;
}
if (error_name == DBUS_ERROR_NOT_SUPPORTED) {
return DBusResult::kErrorNotSupported;
}
if (error_name == DBUS_ERROR_ACCESS_DENIED) {
return DBusResult::kErrorAccessDenied;
}
if (error_name == DBUS_ERROR_DISCONNECTED) {
return DBusResult::kErrorDisconnected;
}
if (error_name == DBUS_ERROR_FAILED) {
return DBusResult::kErrorFailed;
}
if (error_name == DBUS_ERROR_NO_MEMORY) {
return DBusResult::kErrorNoMemory;
}
if (error_name == DBUS_ERROR_SERVICE_UNKNOWN) {
return DBusResult::kErrorServiceUnknown;
}
if (error_name == DBUS_ERROR_NAME_HAS_NO_OWNER) {
return DBusResult::kErrorNameHasNoOwner;
}
if (error_name == DBUS_ERROR_IO_ERROR) {
return DBusResult::kErrorIOError;
}
if (error_name == DBUS_ERROR_BAD_ADDRESS) {
return DBusResult::kErrorBadAddress;
}
if (error_name == DBUS_ERROR_LIMITS_EXCEEDED) {
return DBusResult::kErrorLimitsExceeded;
}
if (error_name == DBUS_ERROR_AUTH_FAILED) {
return DBusResult::kErrorAuthFailed;
}
if (error_name == DBUS_ERROR_NO_SERVER) {
return DBusResult::kErrorNoServer;
}
if (error_name == DBUS_ERROR_NO_NETWORK) {
return DBusResult::kErrorNoNetwork;
}
if (error_name == DBUS_ERROR_ADDRESS_IN_USE) {
return DBusResult::kErrorAddressInUse;
}
if (error_name == DBUS_ERROR_DISCONNECTED) {
return DBusResult::kErrorDisconnected;
}
if (error_name == DBUS_ERROR_INVALID_ARGS) {
return DBusResult::kErrorInvalidArgs;
}
if (error_name == DBUS_ERROR_FILE_NOT_FOUND) {
return DBusResult::kErrorFileNotFound;
}
if (error_name == DBUS_ERROR_FILE_EXISTS) {
return DBusResult::kErrorFileExists;
}
if (error_name == DBUS_ERROR_UNKNOWN_METHOD) {
return DBusResult::kErrorUnknownMethod;
}
if (error_name == DBUS_ERROR_UNKNOWN_OBJECT) {
return DBusResult::kErrorUnknownObject;
}
if (error_name == DBUS_ERROR_UNKNOWN_INTERFACE) {
return DBusResult::kErrorUnknownInterface;
}
if (error_name == DBUS_ERROR_UNKNOWN_PROPERTY) {
return DBusResult::kErrorUnknownProperty;
}
if (error_name == DBUS_ERROR_PROPERTY_READ_ONLY) {
return DBusResult::kErrorPropertyReadOnly;
}
if (error_name == DBUS_ERROR_MATCH_RULE_NOT_FOUND) {
return DBusResult::kErrorMatchRuleNotFound;
}
if (error_name == DBUS_ERROR_MATCH_RULE_INVALID) {
return DBusResult::kErrorMatchRuleInvalid;
}
if (error_name == DBUS_ERROR_SPAWN_EXEC_FAILED) {
return DBusResult::kErrorSpawnExecFailed;
}
if (error_name == DBUS_ERROR_SPAWN_FORK_FAILED) {
return DBusResult::kErrorSpawnForkFailed;
}
if (error_name == DBUS_ERROR_SPAWN_CHILD_EXITED) {
return DBusResult::kErrorSpawnChildExited;
}
if (error_name == DBUS_ERROR_SPAWN_CHILD_SIGNALED) {
return DBusResult::kErrorSpawnChildSignaled;
}
if (error_name == DBUS_ERROR_SPAWN_FAILED) {
return DBusResult::kErrorSpawnFailed;
}
if (error_name == DBUS_ERROR_SPAWN_SETUP_FAILED) {
return DBusResult::kErrorSpawnSetupFailed;
}
if (error_name == DBUS_ERROR_SPAWN_CONFIG_INVALID) {
return DBusResult::kErrorSpawnConfigInvalid;
}
if (error_name == DBUS_ERROR_SPAWN_SERVICE_INVALID) {
return DBusResult::kErrorSpawnServiceInvalid;
}
if (error_name == DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND) {
return DBusResult::kErrorSpawnServiceNotFound;
}
if (error_name == DBUS_ERROR_SPAWN_PERMISSIONS_INVALID) {
return DBusResult::kErrorSpawnPermissionsInvalid;
}
if (error_name == DBUS_ERROR_SPAWN_FILE_INVALID) {
return DBusResult::kErrorSpawnFileInvalid;
}
if (error_name == DBUS_ERROR_SPAWN_NO_MEMORY) {
return DBusResult::kErrorSpawnNoMemory;
}
if (error_name == DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN) {
return DBusResult::kErrorUnixProcessIDUnknown;
}
if (error_name == DBUS_ERROR_INVALID_SIGNATURE) {
return DBusResult::kErrorInvalidSignature;
}
if (error_name == DBUS_ERROR_INVALID_FILE_CONTENT) {
return DBusResult::kErrorInvalidFileContent;
}
if (error_name == DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN) {
return DBusResult::kErrorSELinuxSecurityContextUnknown;
}
if (error_name == DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN) {
return DBusResult::kErrorAdtAuditDataUnknown;
}
if (error_name == DBUS_ERROR_OBJECT_PATH_IN_USE) {
return DBusResult::kErrorObjectPathInUse;
}
if (error_name == DBUS_ERROR_INCONSISTENT_MESSAGE) {
return DBusResult::kErrorInconsistentMessage;
}
if (error_name == DBUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED) {
return DBusResult::kErrorInteractiveAuthorizationRequired;
}
return DBusResult::kErrorUnknown;
}
} // namespace dbus

75
dbus/dbus_result.h Normal file

@ -0,0 +1,75 @@
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DBUS_DBUS_RESULT_H_
#define DBUS_DBUS_RESULT_H_
#include "base/functional/callback.h"
#include "dbus/dbus_export.h"
#include "dbus/message.h"
namespace dbus {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class DBusResult {
kSuccess = 0,
kErrorNoReply = 1,
kErrorTimeout = 2,
kErrorTimedOut = 3,
kErrorNotSupported = 4,
kErrorAccessDenied = 5,
kErrorDisconnected = 6,
kErrorResponseMissing = 7,
kErrorUnknown = 8,
kErrorFailed = 9,
kErrorNoMemory = 10,
kErrorServiceUnknown = 11,
kErrorNameHasNoOwner = 12,
kErrorIOError = 13,
kErrorBadAddress = 14,
kErrorLimitsExceeded = 15,
kErrorAuthFailed = 16,
kErrorNoServer = 17,
kErrorNoNetwork = 18,
kErrorAddressInUse = 19,
kErrorInvalidArgs = 20,
kErrorFileNotFound = 21,
kErrorFileExists = 22,
kErrorUnknownMethod = 23,
kErrorUnknownObject = 24,
kErrorUnknownInterface = 25,
kErrorUnknownProperty = 26,
kErrorPropertyReadOnly = 27,
kErrorMatchRuleNotFound = 28,
kErrorMatchRuleInvalid = 29,
kErrorSpawnExecFailed = 30,
kErrorSpawnForkFailed = 31,
kErrorSpawnChildExited = 32,
kErrorSpawnChildSignaled = 33,
kErrorSpawnFailed = 34,
kErrorSpawnSetupFailed = 35,
kErrorSpawnConfigInvalid = 36,
kErrorSpawnServiceInvalid = 37,
kErrorSpawnServiceNotFound = 38,
kErrorSpawnPermissionsInvalid = 39,
kErrorSpawnFileInvalid = 40,
kErrorSpawnNoMemory = 41,
kErrorUnixProcessIDUnknown = 42,
kErrorInvalidSignature = 43,
kErrorInvalidFileContent = 44,
kErrorSELinuxSecurityContextUnknown = 45,
kErrorAdtAuditDataUnknown = 46,
kErrorObjectPathInUse = 47,
kErrorInconsistentMessage = 48,
kErrorInteractiveAuthorizationRequired = 49,
kErrorNotContainer = 50,
kMaxValue = kErrorNotContainer
};
CHROME_DBUS_EXPORT DBusResult GetResult(dbus::ErrorResponse* response);
} // namespace dbus
#endif // DBUS_DBUS_RESULT_H_

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "device/bluetooth/dbus/bluetooth_metrics_helper.h"
#include "dbus/dbus_result.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
@ -10,64 +11,6 @@
namespace bluez {
namespace {
// This enum is tied directly to a UMA enum defined in
// tools/metrics/histograms/enums.xml, existing entries should not be modified.
enum class DBusResult {
kSuccess = 0,
// The following three are all different types of timeouts reported by the
// DBus service:
// "No reply to a message expecting one, usually means a timeout occurred."
kErrorNoReply = 1,
// "Certain timeout errors, possibly ETIMEDOUT on a socket."
kErrorTimeout = 2,
// "Certain timeout errors, e.g. while starting a service"
kErrorTimedOut = 3,
kErrorNotSupported = 4,
kErrorAccessDenied = 5,
kErrorDisconnected = 6,
kErrorResponseMissing = 7,
kErrorUnknown = 8,
kMaxValue = kErrorUnknown
};
DBusResult GetResult(dbus::ErrorResponse* response) {
if (!response) {
return DBusResult::kErrorResponseMissing;
}
const std::string& error_name = response->GetErrorName();
if (error_name == DBUS_ERROR_NO_REPLY) {
return DBusResult::kErrorNoReply;
}
if (error_name == DBUS_ERROR_TIMEOUT) {
return DBusResult::kErrorTimeout;
}
if (error_name == DBUS_ERROR_TIMED_OUT) {
return DBusResult::kErrorTimedOut;
}
if (error_name == DBUS_ERROR_NOT_SUPPORTED) {
return DBusResult::kErrorNotSupported;
}
if (error_name == DBUS_ERROR_ACCESS_DENIED) {
return DBusResult::kErrorAccessDenied;
}
if (error_name == DBUS_ERROR_DISCONNECTED) {
return DBusResult::kErrorDisconnected;
}
return DBusResult::kErrorUnknown;
}
} // namespace
void RecordSuccess(const std::string& method_name, base::Time start_time) {
base::TimeDelta latency = base::Time::Now() - start_time;
std::string result_metric =
@ -76,14 +19,14 @@ void RecordSuccess(const std::string& method_name, base::Time start_time) {
base::StringPrintf(kLatencyMetric, method_name.c_str());
base::UmaHistogramMediumTimes(latency_metric, latency);
base::UmaHistogramEnumeration(result_metric, DBusResult::kSuccess);
base::UmaHistogramEnumeration(result_metric, dbus::DBusResult::kSuccess);
}
void RecordFailure(const std::string& method_name,
dbus::ErrorResponse* response) {
std::string result_metric =
base::StringPrintf(kResultMetric, method_name.c_str());
DBusResult result = GetResult(response);
dbus::DBusResult result = dbus::GetResult(response);
base::UmaHistogramEnumeration(result_metric, result);
}

@ -26176,6 +26176,48 @@ metrics consent we also won't be able to send UMA metrics. -->
<int value="6" label="Error - Disconnected"/>
<int value="7" label="Error - Response Missing"/>
<int value="8" label="Error - Unknown"/>
<int value="9" label="Error - Failed"/>
<int value="10" label="Error - No Memory"/>
<int value="11" label="Error - Service Unknown"/>
<int value="12" label="Error - Name Has No Owner"/>
<int value="13" label="Error - IO Error"/>
<int value="14" label="Error - Bad Address"/>
<int value="15" label="Error - Limits Exceeded"/>
<int value="16" label="Error - Auth Failed"/>
<int value="17" label="Error - No Server"/>
<int value="18" label="Error - No Network"/>
<int value="19" label="Error - Address In Use"/>
<int value="20" label="Error - Invalid Args"/>
<int value="21" label="Error - File Not Found"/>
<int value="22" label="Error - File Exists"/>
<int value="23" label="Error - Unknown Method"/>
<int value="24" label="Error - Unknown Object"/>
<int value="25" label="Error - Unknown Interface"/>
<int value="26" label="Error - Unknown Property"/>
<int value="27" label="Error - Property Read Only"/>
<int value="28" label="Error - Match Rule Not Found"/>
<int value="29" label="Error - Match Rule Invalid"/>
<int value="30" label="Error - Spawn Exec Failed"/>
<int value="31" label="Error - Spawn Fork Failed"/>
<int value="32" label="Error - Spawn Child Exited"/>
<int value="33" label="Error - Spawn Child Signaled"/>
<int value="34" label="Error - Spawn Failed"/>
<int value="35" label="Error - Spawn Setup Failed"/>
<int value="36" label="Error - Spawn Config Invalid"/>
<int value="37" label="Error - Spawn Service Invalid"/>
<int value="38" label="Error - Spawn Service Not Found"/>
<int value="39" label="Error - Spawn Permissions Invalid"/>
<int value="40" label="Error - Spawn File Invalid"/>
<int value="41" label="Error - Spawn No Memory"/>
<int value="42" label="Error - Unix Process Id Unknown"/>
<int value="43" label="Error - Invalid Signature"/>
<int value="44" label="Error - Invalid File Content"/>
<int value="45" label="Error - SE Linux Security Context Unknown"/>
<int value="46" label="Error - Adt Audit Data Unknown"/>
<int value="47" label="Error - Object Path InUse"/>
<int value="48" label="Error - Inconsistent Message"/>
<int value="49" label="Error - Interactive Authorization Required"/>
<int value="50" label="Error - Not Container"/>
</enum>
<enum name="DCLayerResult">

@ -805,6 +805,19 @@ chromium-metrics-reviews@google.com.
</summary>
</histogram>
<histogram name="Network.Cellular.ESim.InstallViaQrCode.DBusResult"
enum="DBusResult" expires_after="2023-12-31">
<owner>nikhilcn@chromium.org</owner>
<owner>khorimoto@chromium.org</owner>
<owner>cros-connectivity@google.com</owner>
<summary>
Tracks the dbus result for all eSIM installation attempts. This gets logged
only if we receive an unknown hermes response code.
Emitted once the operation completes.
</summary>
</histogram>
<histogram name="Network.Cellular.ESim.InstallViaQrCode.OperationResult"
enum="NetworkCellularESimInstallResult" expires_after="2023-12-31">
<obsolete>