Add ability for daemons to subscribe to pairing session changes
Added Service::SetPairingInfoListener() to provide a callback to
be invoked when pairing session starts/ends. This will let vendor
daemons to display/indicate pairing code to the user.
BUG: 26467076
Change-Id: Ic531c6599eb0dc665670346e5df59cb2cb3ed4cf
diff --git a/libweaved/service.cc b/libweaved/service.cc
index 037c037..c48fb41 100644
--- a/libweaved/service.cc
+++ b/libweaved/service.cc
@@ -23,6 +23,7 @@
#include <brillo/message_loops/message_loop.h>
#include "android/weave/BnWeaveClient.h"
+#include "android/weave/BnWeaveServiceManagerNotificationListener.h"
#include "android/weave/IWeaveCommand.h"
#include "android/weave/IWeaveService.h"
#include "android/weave/IWeaveServiceManager.h"
@@ -139,6 +140,22 @@
DISALLOW_COPY_AND_ASSIGN(WeaveClient);
};
+class NotificationListener
+ : public android::weave::BnWeaveServiceManagerNotificationListener {
+ public:
+ explicit NotificationListener(const std::weak_ptr<ServiceImpl>& service);
+
+ private:
+ // Implementation for IWeaveServiceManagerNotificationListener interface.
+ android::binder::Status notifyServiceManagerChange(
+ const std::vector<int>& notificationIds) override;
+
+ std::weak_ptr<ServiceImpl> service_;
+
+ base::WeakPtrFactory<NotificationListener> weak_ptr_factory_{this};
+ DISALLOW_COPY_AND_ASSIGN(NotificationListener);
+};
+
// ServiceImpl is a concrete implementation of weaved::Service interface.
// This object is a wrapper around android::weave::IWeaveService binder
// interface to weaved daemon.
@@ -175,6 +192,7 @@
const std::string& property_name,
const brillo::Any& value,
brillo::ErrorPtr* error) override;
+ void SetPairingInfoListener(const PairingInfoCallback& callback) override;
// Helper method called from Service::Connect() to initiate binder connection
// to weaved. This message just posts a task to the message loop to invoke
@@ -190,6 +208,9 @@
const std::string& command_name,
const android::sp<android::weave::IWeaveCommand>& command);
+ // A callback method for NotificationListener::notifyServiceManagerChange().
+ void OnNotification(const std::vector<int>& notification_ids);
+
private:
// Connects to weaved daemon over binder if the service manager is available
// and weaved daemon itself is ready to accept connections. If not, schedules
@@ -205,7 +226,10 @@
brillo::MessageLoop* message_loop_;
ServiceSubscription* service_subscription_;
ConnectionCallback connection_callback_;
+ android::sp<android::weave::IWeaveServiceManager> weave_service_manager_;
android::sp<android::weave::IWeaveService> weave_service_;
+ PairingInfoCallback pairing_info_callback_;
+ PairingInfo pairing_info_;
struct CommandHandlerEntry {
std::string component;
@@ -245,6 +269,18 @@
return android::binder::Status::ok();
}
+NotificationListener::NotificationListener(
+ const std::weak_ptr<ServiceImpl>& service)
+ : service_{service} {}
+
+android::binder::Status NotificationListener::notifyServiceManagerChange(
+ const std::vector<int>& notificationIds) {
+ auto service_proxy = service_.lock();
+ if (service_proxy)
+ service_proxy->OnNotification(notificationIds);
+ return android::binder::Status::ok();
+}
+
ServiceImpl::ServiceImpl(android::BinderWrapper* binder_wrapper,
brillo::MessageLoop* message_loop,
ServiceSubscription* service_subscription,
@@ -324,6 +360,16 @@
error);
}
+void ServiceImpl::SetPairingInfoListener(const PairingInfoCallback& callback) {
+ pairing_info_callback_ = callback;
+ if (!pairing_info_callback_.is_null() &&
+ !pairing_info_.session_id.empty() &&
+ !pairing_info_.pairing_mode.empty() &&
+ !pairing_info_.pairing_code.empty()) {
+ callback.Run(&pairing_info_);
+ }
+}
+
void ServiceImpl::BeginConnect() {
message_loop_->PostTask(FROM_HERE,
base::Bind(&ServiceImpl::TryConnecting,
@@ -374,10 +420,13 @@
return;
}
- auto service_manager =
+ weave_service_manager_ =
android::interface_cast<android::weave::IWeaveServiceManager>(binder);
android::sp<WeaveClient> weave_client = new WeaveClient{shared_from_this()};
- service_manager->connect(weave_client);
+ weave_service_manager_->connect(weave_client);
+ android::sp<NotificationListener> notification_listener =
+ new NotificationListener{shared_from_this()};
+ weave_service_manager_->registerNotificationListener(notification_listener);
}
void ServiceImpl::OnWeaveServiceDisconnected() {
@@ -395,6 +444,45 @@
// because the object is destroyed now.
}
+void ServiceImpl::OnNotification(const std::vector<int>& notification_ids) {
+ bool pairing_info_changed = false;
+ using NotificationListener =
+ android::weave::IWeaveServiceManagerNotificationListener;
+ android::String16 string_value;
+ for (int id : notification_ids) {
+ switch (id) {
+ case NotificationListener::PAIRING_SESSION_ID:
+ if (weave_service_manager_->getPairingSessionId(&string_value).isOk()) {
+ pairing_info_changed = true;
+ pairing_info_.session_id = ToString(string_value);
+ }
+ break;
+ case NotificationListener::PAIRING_MODE:
+ if (weave_service_manager_->getPairingMode(&string_value).isOk()) {
+ pairing_info_changed = true;
+ pairing_info_.pairing_mode = ToString(string_value);
+ }
+ break;
+ case NotificationListener::PAIRING_CODE:
+ if (weave_service_manager_->getPairingCode(&string_value).isOk()) {
+ pairing_info_changed = true;
+ pairing_info_.pairing_code = ToString(string_value);
+ }
+ break;
+ }
+ }
+
+ if (!pairing_info_changed || pairing_info_callback_.is_null())
+ return;
+
+ if (pairing_info_.session_id.empty() || pairing_info_.pairing_mode.empty() ||
+ pairing_info_.pairing_code.empty()) {
+ pairing_info_callback_.Run(nullptr);
+ } else {
+ pairing_info_callback_.Run(&pairing_info_);
+ }
+}
+
std::unique_ptr<Service::Subscription> Service::Connect(
brillo::MessageLoop* message_loop,
const ConnectionCallback& callback) {
diff --git a/libweaved/service.h b/libweaved/service.h
index 415b230..02cc509 100644
--- a/libweaved/service.h
+++ b/libweaved/service.h
@@ -43,6 +43,15 @@
using CommandHandlerCallback =
base::Callback<void(std::unique_ptr<Command> command)>;
+ // Callback type for AddPairingInfoListener.
+ struct PairingInfo {
+ std::string session_id;
+ std::string pairing_mode;
+ std::string pairing_code;
+ };
+ using PairingInfoCallback =
+ base::Callback<void(const PairingInfo* pairing_info)>;
+
Service() = default;
virtual ~Service() = default;
@@ -78,6 +87,12 @@
const brillo::Any& value,
brillo::ErrorPtr* error) = 0;
+ // Specifies a callback to be invoked when the device enters/exist pairing
+ // mode. The |pairing_info| parameter is set to a pointer to pairing
+ // information on starting the pairing session and is nullptr when the pairing
+ // session ends.
+ virtual void SetPairingInfoListener(const PairingInfoCallback& callback) = 0;
+
// Service creation functionality.
// Subscription is a base class for an object responsible for life-time
// management for the service. The service instance is kept alive for as long