Commit ba251398 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS PhoneHub] Add TetherController class

This class exposes Instant Tethering functionality to the Phone Hub UI.
For now, TetherControllerImpl does not actually do anything, but landing
it in its current state unblocks UI code from depending on it.

Bug: 1106937
Change-Id: I70ee9dd2d241e9784fac04ba227477435f407473
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2369656
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRegan Hsu <hsuregan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800748}
parent c017dddb
...@@ -32,6 +32,10 @@ static_library("phonehub") { ...@@ -32,6 +32,10 @@ static_library("phonehub") {
"phone_status_model.h", "phone_status_model.h",
"pref_names.cc", "pref_names.cc",
"pref_names.h", "pref_names.h",
"tether_controller.cc",
"tether_controller.h",
"tether_controller_impl.cc",
"tether_controller_impl.h",
] ]
deps = [ deps = [
...@@ -56,6 +60,8 @@ static_library("test_support") { ...@@ -56,6 +60,8 @@ static_library("test_support") {
"fake_feature_status_provider.h", "fake_feature_status_provider.h",
"fake_notification_access_manager.cc", "fake_notification_access_manager.cc",
"fake_notification_access_manager.h", "fake_notification_access_manager.h",
"fake_tether_controller.cc",
"fake_tether_controller.h",
"phone_model_test_util.cc", "phone_model_test_util.cc",
"phone_model_test_util.h", "phone_model_test_util.h",
] ]
...@@ -74,6 +80,7 @@ source_set("unit_tests") { ...@@ -74,6 +80,7 @@ source_set("unit_tests") {
"mutable_phone_model_unittest.cc", "mutable_phone_model_unittest.cc",
"notification_access_manager_impl_unittest.cc", "notification_access_manager_impl_unittest.cc",
"phone_status_model_unittest.cc", "phone_status_model_unittest.cc",
"tether_controller_impl_unittest.cc",
] ]
deps = [ deps = [
......
// Copyright 2020 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 "chromeos/components/phonehub/fake_tether_controller.h"
namespace chromeos {
namespace phonehub {
FakeTetherController::FakeTetherController() = default;
FakeTetherController::~FakeTetherController() = default;
void FakeTetherController::SetStatus(Status status) {
if (status_ == status)
return;
status_ = status;
NotifyStatusChanged();
}
TetherController::Status FakeTetherController::GetStatus() const {
return status_;
}
void FakeTetherController::ScanForAvailableConnection() {
if (status_ == Status::kConnectionUnavailable)
SetStatus(Status::kConnectionAvailable);
}
void FakeTetherController::AttemptConnection() {
if (status_ == Status::kConnectionUnavailable ||
status_ == Status::kConnectionAvailable) {
SetStatus(Status::kConnecting);
}
}
} // namespace phonehub
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_PHONEHUB_FAKE_TETHER_CONTROLLER_H_
#define CHROMEOS_COMPONENTS_PHONEHUB_FAKE_TETHER_CONTROLLER_H_
#include "chromeos/components/phonehub/tether_controller.h"
namespace chromeos {
namespace phonehub {
class FakeTetherController : public TetherController {
public:
FakeTetherController();
~FakeTetherController() override;
void SetStatus(Status status);
private:
// TetherController:
Status GetStatus() const override;
void ScanForAvailableConnection() override;
void AttemptConnection() override;
Status status_;
};
} // namespace phonehub
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_PHONEHUB_FAKE_TETHER_CONTROLLER_H_
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "chromeos/components/phonehub/feature_status_provider_impl.h" #include "chromeos/components/phonehub/feature_status_provider_impl.h"
#include "chromeos/components/phonehub/mutable_phone_model.h" #include "chromeos/components/phonehub/mutable_phone_model.h"
#include "chromeos/components/phonehub/notification_access_manager_impl.h" #include "chromeos/components/phonehub/notification_access_manager_impl.h"
#include "chromeos/components/phonehub/tether_controller_impl.h"
namespace chromeos { namespace chromeos {
namespace phonehub { namespace phonehub {
...@@ -30,7 +31,9 @@ PhoneHubManager::PhoneHubManager( ...@@ -30,7 +31,9 @@ PhoneHubManager::PhoneHubManager(
multidevice_setup_client)), multidevice_setup_client)),
notification_access_manager_( notification_access_manager_(
std::make_unique<NotificationAccessManagerImpl>(pref_service)), std::make_unique<NotificationAccessManagerImpl>(pref_service)),
phone_model_(std::make_unique<MutablePhoneModel>()) { phone_model_(std::make_unique<MutablePhoneModel>()),
tether_controller_(
std::make_unique<TetherControllerImpl>(multidevice_setup_client)) {
DCHECK(!g_instance); DCHECK(!g_instance);
g_instance = this; g_instance = this;
} }
...@@ -41,6 +44,7 @@ void PhoneHubManager::Shutdown() { ...@@ -41,6 +44,7 @@ void PhoneHubManager::Shutdown() {
DCHECK(g_instance); DCHECK(g_instance);
g_instance = nullptr; g_instance = nullptr;
tether_controller_.reset();
phone_model_.reset(); phone_model_.reset();
notification_access_manager_.reset(); notification_access_manager_.reset();
feature_status_provider_.reset(); feature_status_provider_.reset();
......
...@@ -27,6 +27,7 @@ namespace phonehub { ...@@ -27,6 +27,7 @@ namespace phonehub {
class FeatureStatusProvider; class FeatureStatusProvider;
class NotificationAccessManager; class NotificationAccessManager;
class PhoneModel; class PhoneModel;
class TetherController;
// Implements the core logic of the Phone Hub feature and exposes interfaces via // Implements the core logic of the Phone Hub feature and exposes interfaces via
// its public API. Implemented as a KeyedService which is keyed by the primary // its public API. Implemented as a KeyedService which is keyed by the primary
...@@ -58,6 +59,8 @@ class PhoneHubManager : public KeyedService { ...@@ -58,6 +59,8 @@ class PhoneHubManager : public KeyedService {
PhoneModel* phone_model() { return phone_model_.get(); } PhoneModel* phone_model() { return phone_model_.get(); }
TetherController* tether_controller() { return tether_controller_.get(); }
private: private:
// KeyedService: // KeyedService:
void Shutdown() override; void Shutdown() override;
...@@ -65,6 +68,7 @@ class PhoneHubManager : public KeyedService { ...@@ -65,6 +68,7 @@ class PhoneHubManager : public KeyedService {
std::unique_ptr<FeatureStatusProvider> feature_status_provider_; std::unique_ptr<FeatureStatusProvider> feature_status_provider_;
std::unique_ptr<NotificationAccessManager> notification_access_manager_; std::unique_ptr<NotificationAccessManager> notification_access_manager_;
std::unique_ptr<PhoneModel> phone_model_; std::unique_ptr<PhoneModel> phone_model_;
std::unique_ptr<TetherController> tether_controller_;
}; };
} // namespace phonehub } // namespace phonehub
......
// Copyright 2020 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 "chromeos/components/phonehub/tether_controller.h"
namespace chromeos {
namespace phonehub {
TetherController::TetherController() = default;
TetherController::~TetherController() = default;
void TetherController::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void TetherController::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
void TetherController::NotifyStatusChanged() {
for (auto& observer : observer_list_)
observer.OnStatusChanged();
}
std::ostream& operator<<(std::ostream& stream,
TetherController::Status status) {
switch (status) {
case TetherController::Status::kIneligibleForFeature:
stream << "[Ineligible for feature]";
break;
case TetherController::Status::kConnectionUnavailable:
stream << "[Connection unavailable]";
break;
case TetherController::Status::kConnectionAvailable:
stream << "[Connection available]";
break;
case TetherController::Status::kConnecting:
stream << "[Connecting]";
break;
case TetherController::Status::kConnected:
stream << "[Connected]";
break;
}
return stream;
}
} // namespace phonehub
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_H_
#define CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_H_
#include <ostream>
#include "base/observer_list.h"
#include "base/observer_list_types.h"
namespace chromeos {
namespace phonehub {
// Exposes Instant Tethering functionality to Phone Hub.
class TetherController {
public:
enum class Status {
// The device is ineligible for Instant Tethering, potentially due to the
// flag being disabled (on Chrome OS or on the phone) or due to an
// enterprise policy.
kIneligibleForFeature,
// Instant Tethering is available for use, but currently a connection is
// unavailable. There are a variety of reasons why this may be the case:
// the feature could have been disabled in settings, the phone may not have
// cellular reception, or the phone may not have Google Play Services
// notifications enabled, which are required for the feature.
kConnectionUnavailable,
// It is possible to connect, but no connection is active or in progress.
// This state can occur if a previously-active connection has been
// disconnected.
kConnectionAvailable,
// Initiating an Instant Tethering connection.
kConnecting,
// Connected via Instant Tethering.
kConnected
};
class Observer : public base::CheckedObserver {
public:
~Observer() override = default;
// Called the status has changed; use GetStatus() to get the new status.
virtual void OnStatusChanged() = 0;
};
TetherController(const TetherController&) = delete;
TetherController& operator=(const TetherController&) = delete;
virtual ~TetherController();
virtual Status GetStatus() const = 0;
// Attempts to find an available Instant Tethering connection. For a
// connection to be available, the phone must be nearby, have reception, and
// have Google Play Services notifications enabled. This function is a no-op
// if the state is not kConnectionUnavailable.
virtual void ScanForAvailableConnection() = 0;
// Initiates an Instant Tethering connection. This function is a no-op if the
// state is not one of kConnectionUnavailable or kConnectionAvailable.
virtual void AttemptConnection() = 0;
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
protected:
TetherController();
void NotifyStatusChanged();
private:
base::ObserverList<Observer> observer_list_;
};
std::ostream& operator<<(std::ostream& stream, TetherController::Status status);
} // namespace phonehub
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_H_
// Copyright 2020 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 "chromeos/components/phonehub/tether_controller_impl.h"
#include "chromeos/components/multidevice/logging/logging.h"
namespace chromeos {
namespace phonehub {
TetherControllerImpl::TetherControllerImpl(
multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client)
: multidevice_setup_client_(multidevice_setup_client) {
multidevice_setup_client_->AddObserver(this);
}
TetherControllerImpl::~TetherControllerImpl() {
multidevice_setup_client_->RemoveObserver(this);
}
TetherController::Status TetherControllerImpl::GetStatus() const {
return status_;
}
void TetherControllerImpl::ScanForAvailableConnection() {
if (status_ != Status::kConnectionUnavailable) {
PA_LOG(WARNING) << "Received request to scan for available connection, but "
<< "a scan cannot be performed because the current status "
<< "is " << status_;
return;
}
PA_LOG(INFO) << "Scanning for available connection.";
// TODO(khorimoto): Actually scan for an available connection.
}
void TetherControllerImpl::AttemptConnection() {
if (status_ != Status::kConnectionUnavailable &&
status_ != Status::kConnectionAvailable) {
PA_LOG(WARNING) << "Received request to attempt a connection, but a "
<< "connection cannot be attempted because the current "
<< "status is " << status_;
return;
}
PA_LOG(INFO) << "Attempting connection; current status is " << status_;
// TODO(khorimoto): Actually attempt a connection.
}
} // namespace phonehub
} // namespace chromeos
// Copyright 2020 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.
#ifndef CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_IMPL_H_
#define CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_IMPL_H_
#include "chromeos/components/phonehub/tether_controller.h"
#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
namespace chromeos {
namespace phonehub {
// TetherController implementation which utilizes MultiDeviceSetupClient and
// CrosNetworkConfig in order to interact with Instant Tethering.
// TODO(khorimoto): Set the status depending on the current state; currently,
// this class is a stub.
class TetherControllerImpl
: public TetherController,
public multidevice_setup::MultiDeviceSetupClient::Observer {
public:
TetherControllerImpl(
multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client);
~TetherControllerImpl() override;
private:
// TetherController:
Status GetStatus() const override;
void ScanForAvailableConnection() override;
void AttemptConnection() override;
multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_;
Status status_ = Status::kIneligibleForFeature;
};
} // namespace phonehub
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_IMPL_H_
// Copyright 2020 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 "chromeos/components/phonehub/tether_controller_impl.h"
#include <memory>
#include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace phonehub {
namespace {
class FakeObserver : public TetherController::Observer {
public:
FakeObserver() = default;
~FakeObserver() override = default;
size_t num_calls() const { return num_calls_; }
// TetherController::Observer:
void OnStatusChanged() override { ++num_calls_; }
private:
size_t num_calls_ = 0;
};
} // namespace
class TetherControllerImplTest : public testing::Test {
protected:
TetherControllerImplTest() = default;
TetherControllerImplTest(const TetherControllerImplTest&) = delete;
TetherControllerImplTest& operator=(const TetherControllerImplTest&) = delete;
~TetherControllerImplTest() override = default;
// testing::Test:
void SetUp() override {
controller_ =
std::make_unique<TetherControllerImpl>(&fake_multidevice_setup_client_);
controller_->AddObserver(&fake_observer_);
}
void TearDown() override { controller_->RemoveObserver(&fake_observer_); }
TetherController::Status GetStatus() const {
return controller_->GetStatus();
}
size_t GetNumObserverCalls() const { return fake_observer_.num_calls(); }
private:
multidevice_setup::FakeMultiDeviceSetupClient fake_multidevice_setup_client_;
FakeObserver fake_observer_;
std::unique_ptr<TetherController> controller_;
};
// TODO(khorimoto): Remove this test once we have real functionality to test.
TEST_F(TetherControllerImplTest, Initialize) {
EXPECT_EQ(TetherController::Status::kIneligibleForFeature, GetStatus());
}
} // namespace phonehub
} // namespace chromeos
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment