diff options
author | Scott Murray <scott.murray@konsulko.com> | 2022-09-10 12:31:13 -0400 |
---|---|---|
committer | Scott Murray <scott.murray@konsulko.com> | 2022-09-10 12:42:02 -0400 |
commit | 560d902f4d2bf4ba3bb2edba6436080ee7d5a5ac (patch) | |
tree | 026c81383374b0b7ffbb867ab392ec7789f8ff45 /applauncher/AppLauncherGrpcClient.cpp | |
parent | a2d991a54f77017ced1558d289bcb83d73fe2a35 (diff) |
Add applaunchd gRPC API wrapper
Changes:
- Add applaunchd gRPC API wrapper in applauncher directory, clients
can include AppLauncherClient.h to use it.
- To facilitate generating protobuf and gRPC code with protoc,
switch from CMake to meson for building. While the code
generation can be done in CMake, it is a lot more straightforward
with meson, and if use of this library continues meson will be
easier to maintain.
Known issues:
- The behavior of the client implementation here with respect to the
server side (i.e. applaunchd) going away is currently robust, but
could stand improvement with some further investigation. As the
code stands, starting applications works when applaunchd becomes
available again, but the streaming status RPC that is tied to
window activation in the homescreen does not reconnect, and there
seem to be some things that need to be resolved with respect to
Qt object connection expiry to do so. If the Qt demos continue to
be used in a significant fashion, this may be worth picking up.
Bug-AGL: SPEC-4559
Signed-off-by: Scott Murray <scott.murray@konsulko.com>
Change-Id: I5cb480d4ce4d1cb944ebfd4114fb305f09f28ea3
Diffstat (limited to 'applauncher/AppLauncherGrpcClient.cpp')
-rw-r--r-- | applauncher/AppLauncherGrpcClient.cpp | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/applauncher/AppLauncherGrpcClient.cpp b/applauncher/AppLauncherGrpcClient.cpp new file mode 100644 index 0000000..a25b148 --- /dev/null +++ b/applauncher/AppLauncherGrpcClient.cpp @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (C) 2022 Konsulko Group + */ + +#include <QDebug> +#include "AppLauncherGrpcClient.h" +#include "AppLauncherClient.h" + +using grpc::Channel; +using grpc::ClientContext; +using grpc::ClientReader; +using grpc::Status; + +using automotivegradelinux::AppLauncher; +using automotivegradelinux::StartRequest; +using automotivegradelinux::StartResponse; +using automotivegradelinux::ListRequest; +using automotivegradelinux::ListResponse; +using automotivegradelinux::AppInfo; +using automotivegradelinux::StatusRequest; +using automotivegradelinux::StatusResponse; +using automotivegradelinux::AppStatus; + + +void AppStatusEventReader::GetStatusEvents() +{ + ClientContext context; + StatusRequest request; + StatusResponse response; + + std::unique_ptr<ClientReader<StatusResponse> > reader(stub_->GetStatusEvents(&context, request)); + while (reader->Read(&response)) { + if (response.has_app()) { + AppStatus app_status = response.app(); + emit statusUpdate(QString::fromStdString(app_status.id()), + QString::fromStdString(app_status.status())); + } + } + Status status = reader->Finish(); + if (!status.ok()) { + qWarning() << "GetStatusEvents RPC failed"; + } + + emit finished(); +} + +AppLauncherGrpcClient::AppLauncherGrpcClient(QObject *parent) : QObject(parent) +{ + stub_ = AppLauncher::NewStub(grpc::CreateChannel("localhost:50052", grpc::InsecureChannelCredentials())); + + // Create thread to read status events + AppStatusEventReader *reader = new AppStatusEventReader(stub_); + reader->moveToThread(&m_event_thread); + connect(&m_event_thread, &QThread::started, reader, &AppStatusEventReader::GetStatusEvents); + connect(reader, &AppStatusEventReader::finished, &m_event_thread, &QThread::quit); + // FIXME: Normally the thread finishing would be connected per the below + // to trigger cleaning up the object. That seems to trigger a crash + // for not entirely obvious reasons. It seems unrelated to the signal + // connection to AppLauncherClient, as not connecting does not prevent + // the crash; further investigation is required. + //connect(reader, &AppStatusEventReader::finished, reader, &AppStatusEventReader::deleteLater); + //connect(&m_event_thread, &QThread::finished, &m_event_thread, &QThread::deleteLater); + + // To avoid having an intermediary slot+signal in this class, try + // casting parent to AppLauncherClient and connect directly to its + // slot. Callers should set parent to ensure this works as required. + if (parent) { + AppLauncherClient *launcher = qobject_cast<AppLauncherClient*>(parent); + if (launcher) + connect(reader, + &AppStatusEventReader::statusUpdate, + launcher, + &AppLauncherClient::sendStatusEvent); + } + + // Start status event handling + m_event_thread.start(); +} + +bool AppLauncherGrpcClient::StartApplication(const QString &id) +{ + StartRequest request; + request.set_id(id.toStdString()); + + ClientContext context; + StartResponse response; + Status status = stub_->StartApplication(&context, request, &response); + + return status.ok(); +} + +bool AppLauncherGrpcClient::ListApplications(QList<QMap<QString, QString>> &list) +{ + ListRequest request; // empty + ClientContext context; + ListResponse response; + + Status status = stub_->ListApplications(&context, request, &response); + if (!status.ok()) + return false; + + for (int i = 0; i < response.apps_size(); i++) { + QMap<QString, QString> appinfo_map; + AppInfo appinfo = response.apps(i); + appinfo_map["id"] = QString::fromStdString(appinfo.id()); + appinfo_map["name"] = QString::fromStdString(appinfo.name()); + appinfo_map["icon_path"] = QString::fromStdString(appinfo.icon_path()); + list.append(appinfo_map); + } + + return true; +} |