0

Adds Bluetooth Unavailable state in QS Pod

This CL makes the bluetooth pod visible with an error state when
Bluetooth is unavailable and updates unit tests to reflect this.

Bug: 357945367
Change-Id: I8cbbb9472aa83ca68bc125400eb99b07e92a6a66
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5770654
Commit-Queue: Bhuvana Betini <bbetini@google.com>
Reviewed-by: Andre Le <leandre@chromium.org>
Reviewed-by: Ahmed Mehfooz <amehfooz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1341975}
This commit is contained in:
Bhuvana Betini
2024-08-14 22:00:10 +00:00
committed by Chromium LUCI CQ
parent e204f7c7af
commit 68196581fa
6 changed files with 80 additions and 19 deletions

@ -663,6 +663,9 @@ Style notes:
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED_TOOLTIP" desc="The tooltip text to notify that bluetooth is disabled.">
Bluetooth is off
</message>
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_UNAVAILABLE_TOOLTIP" desc="The tooltip text to notify that bluetooth is unavailable.">
Bluetooth is unavailable
</message>
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_MULTIPLE_DEVICES_CONNECTED_TOOLTIP_LEGACY" desc="The tooltip text to notify that multiple bluetooth devices are connected. [ICU Syntax]">
{NUM_DEVICES, plural,
=1 {Connected to a device}
@ -692,6 +695,9 @@ Style notes:
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED_SHORT" desc="Bluetooth button label in the status tray popup." meaning="Bluetooth is disabled. [CHAR_LIMIT=14]">
Off
</message>
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_UNAVAILABLE_SHORT" desc="Bluetooth button label in the status tray popup." meaning="Bluetooth is unavailable. [CHAR_LIMIT=14]">
Unavailable
</message>
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISCOVERING" desc="The label used in the tray popup to show bluetooth is discovering devices.">
Scanning for devices...
</message>

@ -0,0 +1 @@
da1d83b20ab3e9d7960a14214964c61bcefe6a0e

@ -0,0 +1 @@
3c522469b5f2d6570f8328a24db622fc23ffc11c

@ -23,6 +23,7 @@
#include "base/i18n/number_formatting.h"
#include "base/strings/string_number_conversions.h"
#include "chromeos/ash/services/bluetooth_config/public/cpp/cros_bluetooth_config_util.h"
#include "chromeos/constants/chromeos_features.h"
#include "mojo/public/cpp/bindings/clone_traits.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/image_view.h"
@ -87,6 +88,10 @@ QsFeatureCatalogName BluetoothFeaturePodController::GetCatalogName() {
return QsFeatureCatalogName::kBluetooth;
}
bool BluetoothFeaturePodController::IsBluetoothAvailable() const {
return system_state_ != BluetoothSystemState::kUnavailable;
}
void BluetoothFeaturePodController::OnIconPressed() {
if (!IsButtonEnabled()) {
return;
@ -184,6 +189,11 @@ int BluetoothFeaturePodController::
}
std::u16string BluetoothFeaturePodController::ComputeButtonSubLabel() const {
if (chromeos::features::IsBluetoothWifiQSPodRefreshEnabled() &&
!IsBluetoothAvailable()) {
return l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_BLUETOOTH_UNAVAILABLE_SHORT);
}
if (!IsButtonToggled()) {
return l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_BLUETOOTH_DISABLED_SHORT);
@ -209,6 +219,11 @@ std::u16string BluetoothFeaturePodController::ComputeButtonSubLabel() const {
}
std::u16string BluetoothFeaturePodController::ComputeTooltip() const {
if (chromeos::features::IsBluetoothWifiQSPodRefreshEnabled() &&
!IsBluetoothAvailable()) {
return l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_BLUETOOTH_UNAVAILABLE_TOOLTIP);
}
if (!first_connected_device_.has_value())
return l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_BLUETOOTH_ENABLED_TOOLTIP);
@ -244,7 +259,8 @@ void BluetoothFeaturePodController::UpdateTileStateIfExists() {
if (!tile_) {
return;
}
if (system_state_ == BluetoothSystemState::kUnavailable) {
if (!chromeos::features::IsBluetoothWifiQSPodRefreshEnabled() &&
!IsBluetoothAvailable()) {
tile_->SetVisible(false);
tile_->SetEnabled(false);
return;
@ -265,6 +281,13 @@ void BluetoothFeaturePodController::UpdateTileStateIfExists() {
tile_->SetSubLabel(ComputeButtonSubLabel());
if (!tile_->IsToggled()) {
if (chromeos::features::IsBluetoothWifiQSPodRefreshEnabled() &&
!IsBluetoothAvailable()) {
tile_->SetTooltipText(l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_BLUETOOTH_UNAVAILABLE_TOOLTIP));
tile_->icon_button()->SetEnabled(false);
return;
}
std::u16string tooltip = l10n_util::GetStringFUTF16(
IDS_ASH_STATUS_TRAY_BLUETOOTH_TOGGLE_TOOLTIP,
l10n_util::GetStringUTF16(

@ -68,6 +68,9 @@ class ASH_EXPORT BluetoothFeaturePodController
// Returns true if `tile_` is toggled, otherwise false.
bool IsButtonToggled() const;
// Returns true if Bluetooth is available, otherwise false.
bool IsBluetoothAvailable() const;
// Updates `tile_` state to reflect the cached Bluetooth state.
void UpdateTileStateIfExists();

@ -31,6 +31,7 @@
#include "chromeos/ash/services/bluetooth_config/fake_device_cache.h"
#include "chromeos/ash/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom.h"
#include "chromeos/ash/services/bluetooth_config/scoped_bluetooth_config_test_helper.h"
#include "chromeos/constants/chromeos_features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/view.h"
@ -58,9 +59,18 @@ constexpr uint8_t kCaseBatteryPercentage = 77;
// How many devices to "pair" for tests that require multiple connected devices.
constexpr int kMultipleDeviceCount = 3;
class BluetoothFeaturePodControllerTest : public AshTestBase {
class BluetoothFeaturePodControllerTest
: public AshTestBase,
public testing::WithParamInterface<bool> {
public:
BluetoothFeaturePodControllerTest() = default;
BluetoothFeaturePodControllerTest() {
scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitWithFeatureState(
chromeos::features::kBluetoothWifiQSPodRefresh,
IsBluetoothWifiQSPodRefreshEnabled());
}
bool IsBluetoothWifiQSPodRefreshEnabled() { return GetParam(); }
// AshTestBase:
void SetUp() override {
@ -73,13 +83,13 @@ class BluetoothFeaturePodControllerTest : public AshTestBase {
bluetooth_pod_controller_ =
std::make_unique<BluetoothFeaturePodController>(tray_controller());
feature_tile_ = bluetooth_pod_controller_->CreateTile();
base::RunLoop().RunUntilIdle();
}
void TearDown() override {
feature_tile_.reset();
bluetooth_pod_controller_.reset();
scoped_feature_list_.reset();
AshTestBase::TearDown();
}
@ -176,6 +186,10 @@ class BluetoothFeaturePodControllerTest : public AshTestBase {
bool IsButtonToggled() { return feature_tile_->IsToggled(); }
bool IsButtonIconEnabled() {
return feature_tile_->icon_button()->GetEnabled();
}
std::u16string GetButtonLabelText() {
return feature_tile_->label()->GetText();
}
@ -230,13 +244,25 @@ class BluetoothFeaturePodControllerTest : public AshTestBase {
std::unique_ptr<FakeHatsBluetoothRevampTriggerImpl> fake_trigger_impl_;
std::unique_ptr<BluetoothFeaturePodController> bluetooth_pod_controller_;
std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
};
TEST_F(BluetoothFeaturePodControllerTest,
INSTANTIATE_TEST_SUITE_P(
All,
BluetoothFeaturePodControllerTest,
/*IsBluetoothWifiQSPodRefreshEnabled()=*/testing::Bool());
TEST_P(BluetoothFeaturePodControllerTest,
HasCorrectButtonStateWhenBluetoothStateChanges) {
SetSystemState(BluetoothSystemState::kUnavailable);
EXPECT_FALSE(IsButtonEnabled());
EXPECT_FALSE(IsButtonVisible());
if (IsBluetoothWifiQSPodRefreshEnabled()) {
EXPECT_TRUE(IsButtonVisible());
} else {
EXPECT_FALSE(IsButtonEnabled());
EXPECT_FALSE(IsButtonVisible());
}
for (const auto& system_state :
{BluetoothSystemState::kDisabled, BluetoothSystemState::kDisabling}) {
SetSystemState(system_state);
@ -251,8 +277,9 @@ TEST_F(BluetoothFeaturePodControllerTest,
}
}
TEST_F(BluetoothFeaturePodControllerTest, PressingIconOrLabelChangesBluetooth) {
TEST_P(BluetoothFeaturePodControllerTest, PressingIconOrLabelChangesBluetooth) {
EXPECT_EQ(0u, GetTryToShowSurveyCount());
EXPECT_TRUE(IsButtonIconEnabled());
EXPECT_TRUE(IsButtonToggled());
PressIcon();
EXPECT_FALSE(IsButtonToggled());
@ -264,7 +291,7 @@ TEST_F(BluetoothFeaturePodControllerTest, PressingIconOrLabelChangesBluetooth) {
EXPECT_EQ(2u, GetTryToShowSurveyCount());
}
TEST_F(BluetoothFeaturePodControllerTest, HasCorrectMetadataWhenOff) {
TEST_P(BluetoothFeaturePodControllerTest, HasCorrectMetadataWhenOff) {
SetSystemState(BluetoothSystemState::kDisabled);
EXPECT_FALSE(IsButtonToggled());
@ -289,7 +316,7 @@ TEST_F(BluetoothFeaturePodControllerTest, HasCorrectMetadataWhenOff) {
GetButtonTooltipText());
}
TEST_F(BluetoothFeaturePodControllerTest, HasCorrectMetadataWithZeroDevices) {
TEST_P(BluetoothFeaturePodControllerTest, HasCorrectMetadataWithZeroDevices) {
SetSystemState(BluetoothSystemState::kEnabled);
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_BLUETOOTH),
@ -311,7 +338,7 @@ TEST_F(BluetoothFeaturePodControllerTest, HasCorrectMetadataWithZeroDevices) {
GetButtonTooltipText());
}
TEST_F(BluetoothFeaturePodControllerTest, HasCorrectMetadataWithOneDevice) {
TEST_P(BluetoothFeaturePodControllerTest, HasCorrectMetadataWithOneDevice) {
SetSystemState(BluetoothSystemState::kEnabled);
const std::u16string public_name = base::ASCIIToUTF16(kDevicePublicName);
@ -361,7 +388,7 @@ TEST_F(BluetoothFeaturePodControllerTest, HasCorrectMetadataWithOneDevice) {
GetButtonSubLabelText());
}
TEST_F(BluetoothFeaturePodControllerTest,
TEST_P(BluetoothFeaturePodControllerTest,
HasCorrectMetadataWithOneDevice_MultipleBatteries) {
SetSystemState(BluetoothSystemState::kEnabled);
@ -402,7 +429,7 @@ TEST_F(BluetoothFeaturePodControllerTest,
GetButtonSubLabelText());
}
TEST_F(BluetoothFeaturePodControllerTest,
TEST_P(BluetoothFeaturePodControllerTest,
HasCorrectMetadataWithMultipleDevice) {
SetSystemState(BluetoothSystemState::kEnabled);
@ -444,7 +471,7 @@ TEST_F(BluetoothFeaturePodControllerTest,
GetButtonTooltipText());
}
TEST_F(BluetoothFeaturePodControllerTest, EnablingBluetoothOnTheMainPage) {
TEST_P(BluetoothFeaturePodControllerTest, EnablingBluetoothOnTheMainPage) {
SetSystemState(BluetoothSystemState::kDisabled);
EXPECT_FALSE(IsButtonToggled());
@ -453,14 +480,14 @@ TEST_F(BluetoothFeaturePodControllerTest, EnablingBluetoothOnTheMainPage) {
IsShowingDetailedView(/*is_showing=*/false);
}
TEST_F(BluetoothFeaturePodControllerTest,
TEST_P(BluetoothFeaturePodControllerTest,
PressingLabelWithEnabledBluetoothShowsBluetoothDetailedView) {
EXPECT_TRUE(IsButtonToggled());
PressLabel();
IsShowingDetailedView();
}
TEST_F(BluetoothFeaturePodControllerTest,
TEST_P(BluetoothFeaturePodControllerTest,
FeaturePodIsDisabledWhenBluetoothCannotBeModified) {
EXPECT_TRUE(IsButtonEnabled());
@ -472,7 +499,7 @@ TEST_F(BluetoothFeaturePodControllerTest,
EXPECT_FALSE(IsButtonEnabled());
}
TEST_F(BluetoothFeaturePodControllerTest, IconUMATracking) {
TEST_P(BluetoothFeaturePodControllerTest, IconUMATracking) {
// No metrics are logged before clicking on any views.
auto histogram_tester = std::make_unique<base::HistogramTester>();
histogram_tester->ExpectTotalCount(GetToggledOnHistogramName(),
@ -521,7 +548,7 @@ TEST_F(BluetoothFeaturePodControllerTest, IconUMATracking) {
/*expected_count=*/1);
}
TEST_F(BluetoothFeaturePodControllerTest, LabelUMATracking) {
TEST_P(BluetoothFeaturePodControllerTest, LabelUMATracking) {
// No metrics logged before clicking on any views.
auto histogram_tester = std::make_unique<base::HistogramTester>();
histogram_tester->ExpectTotalCount(GetToggledOnHistogramName(),
@ -544,7 +571,7 @@ TEST_F(BluetoothFeaturePodControllerTest, LabelUMATracking) {
/*expected_count=*/1);
}
TEST_F(BluetoothFeaturePodControllerTest, VisibilityOnConstruction) {
TEST_P(BluetoothFeaturePodControllerTest, VisibilityOnConstruction) {
BluetoothFeaturePodController controller(tray_controller());
// Create a feature tile but don't spin the message loop.
auto tile = controller.CreateTile();