aboutsummaryrefslogtreecommitdiffstats
path: root/launcher/src
diff options
context:
space:
mode:
Diffstat (limited to 'launcher/src')
-rw-r--r--launcher/src/appfwhandler.cpp212
-rw-r--r--launcher/src/appfwhandler.h76
-rw-r--r--launcher/src/applicationmodel.cpp68
-rw-r--r--launcher/src/applicationmodel.h1
-rw-r--r--launcher/src/main.cpp5
5 files changed, 356 insertions, 6 deletions
diff --git a/launcher/src/appfwhandler.cpp b/launcher/src/appfwhandler.cpp
new file mode 100644
index 0000000..9df6d7d
--- /dev/null
+++ b/launcher/src/appfwhandler.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include "appfwhandler.h"
+#include "hmi-debug.h"
+
+AppFwHandler* AppFwHandler::myself = nullptr;
+
+// called when pws hangsup
+static void _on_pws_hangup(void *closure)
+{
+ if(AppFwHandler::myself)
+ AppFwHandler::myself->on_pws_hangup();
+}
+
+static void _on_pws_reply(void *closure, void *request, struct json_object *obj, const char *error, const char *info)
+{
+ HMI_DEBUG("AppFwHandler", "%s called,error=[%s], info=[%s], obj=[%s]", __FUNCTION__, error, info, json_object_to_json_string(obj));
+ if(json_object_is_type(obj, json_type_object)) {
+ struct json_object *obj1, *obj2, *obj3;
+ json_object_object_get_ex(obj, "icon", &obj1);
+ json_object_object_get_ex(obj, "name", &obj2);
+ json_object_object_get_ex(obj, "id", &obj3);
+ if(json_object_is_type(obj3, json_type_null))
+ return;
+ QString icon = json_object_get_string(obj1);
+ QString name = json_object_get_string(obj2);
+ QString id = json_object_get_string(obj3);
+ QStringList info;
+ info << icon << name << id;
+ emit AppFwHandler::myself->applistupdate(info);
+ }
+}
+
+static void _on_pws_event_broadcast(void *closure, const char *event_name, struct json_object *data)
+{
+ HMI_DEBUG("AppFwHandler", "%s called,event=%s, [%s]", __FUNCTION__, event_name, json_object_to_json_string(data));
+ QStringList list = QString(event_name).split('/');
+ if(list[0] == "afm-main" && list[1] == "application-list-changed") {
+ struct json_object *obj1, *obj2;
+ json_object_object_get_ex(data, "operation", &obj1);
+ json_object_object_get_ex(data, "data", &obj2);
+ QString oper = json_object_get_string(obj1);
+ QString id = json_object_get_string(obj2);
+
+ if(oper == "uninstall") {
+ QStringList info;
+ // icon, name, id
+ info << "" << "" << id;
+ emit AppFwHandler::myself->applistupdate(info);
+ }
+ else if (oper == "install") {
+ // call state
+ AppFwHandler::myself->detail(id);
+ }
+ else {
+ HMI_DEBUG("AppFwHandler","data error");
+ }
+ }
+}
+
+// the callback interface for pws
+static struct afb_proto_ws_client_itf pws_itf = {
+ .on_reply = _on_pws_reply,
+ .on_event_create = nullptr,
+ .on_event_remove = nullptr,
+ .on_event_subscribe = nullptr,
+ .on_event_unsubscribe = nullptr,
+ .on_event_push = nullptr,
+ .on_event_broadcast = _on_pws_event_broadcast,
+};
+
+AppFwHandler::AppFwHandler(const char* appname, QObject *parent) : QObject(parent)
+{
+ myself = this;
+ int uid = getuid();
+ QString _uid;
+ if(uid == 0)
+ _uid = QString('0');
+ else
+ _uid = QString(uid);
+
+ m_sessionid = _uid + QString(appname);
+ m_uri = "unix:/run/user/" + _uid + "/apis/ws/afm-main";
+ HMI_NOTICE("AppFwHandler","m_uri=%s, m_sessionid=%s", m_uri.toStdString().c_str(), m_sessionid.toStdString().c_str());
+}
+
+int AppFwHandler::init(void)
+{
+ // get default loop
+ int rc = sd_event_default(&m_evloop);
+ if(rc < 0)
+ {
+ HMI_ERROR("AppFwHandler", "can't create event loop");
+ return 1;
+ }
+
+ // connect to framework
+ if (!try_connect_pws()) {
+ HMI_ERROR("connection to %s failed: %m\n", m_uri.toStdString().c_str());
+ return 1;
+ }
+// runnables();
+ return 0;
+}
+
+int AppFwHandler::runnables(void)
+{
+ int ret = 1;
+ if(call(__FUNCTION__, "{\"info\":\"test my guess\"}") < 0)
+ ret = 0;
+ return ret;
+}
+
+int AppFwHandler::detail(QString id)
+{
+ int ret = 1;
+ HMI_DEBUG("AppFwHandler", "detail id is %s\n", id.toStdString().c_str());
+ if(call(__FUNCTION__, id.toStdString().c_str()) < 0)
+ ret = 0;
+ return ret;
+}
+
+int AppFwHandler::try_connect_pws(void)
+{
+ m_pws = afb_ws_client_connect_api(m_evloop, m_uri.toStdString().c_str(), &pws_itf, NULL);
+ if (m_pws == nullptr) {
+ HMI_ERROR("AppFwHandler", "connection to %s failed!\n", m_uri.toStdString().c_str());
+ return 0;
+ }
+ afb_proto_ws_on_hangup(m_pws, _on_pws_hangup);
+ return 1;
+}
+
+void AppFwHandler::on_pws_hangup(void)
+{
+ struct afb_proto_ws *apw = m_pws;
+ m_pws = nullptr;
+ afb_proto_ws_unref(apw);
+ attempt_connect_pws(10);
+}
+
+void AppFwHandler::attempt_connect_pws(int count)
+{
+ if(m_time != nullptr) {
+ HMI_NOTICE("AppFwHandler", "attempt_connect_pws retrying!\n");
+ return;
+ }
+ if(count > 0)
+ m_retry = count;
+ else
+ return;
+
+ m_time = new QTimer(this);
+ connect(m_time, SIGNAL(timeout()), this, SLOT(connect_pws_timer_slot()));
+ m_time->start(5000);
+}
+
+void AppFwHandler::connect_pws_timer_slot(void)
+{
+ --m_retry;
+ int ret = try_connect_pws();
+ if(ret) {
+ m_retry = 0;
+ disconnect(m_time, 0, 0, 0);
+ delete m_time;
+ m_time = nullptr;
+ }
+ else {
+ if(m_retry > 0)
+ m_time->start(5000);
+ }
+}
+
+int AppFwHandler::call(const char *verb, const char *object)
+{
+ static int num = 0;
+ if(verb == nullptr) {
+ HMI_NOTICE("AppFwHandler", "parameter is null!\n");
+ return 0;
+ }
+ num++;
+
+ QString key = QString(num) + ':' + QString(verb);
+ enum json_tokener_error jerr;
+ struct json_object *obj = json_tokener_parse_verbose(object, &jerr);
+ if (jerr != json_tokener_success)
+ obj = json_object_new_string(object);
+
+ int rc = afb_proto_ws_client_call(m_pws, verb, obj, m_sessionid.toStdString().c_str(), key.toLatin1().data(), NULL);
+ json_object_put(obj);
+ if (rc < 0) {
+ HMI_ERROR("AppFwHandler", "calling %s(%s) failed!\n", verb, object);
+ }
+
+ return rc;
+}
diff --git a/launcher/src/appfwhandler.h b/launcher/src/appfwhandler.h
new file mode 100644
index 0000000..25a401b
--- /dev/null
+++ b/launcher/src/appfwhandler.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018 TOYOTA MOTOR CORPORATION
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APPFWHANDLER_H
+#define APPFWHANDLER_H
+
+#include <QObject>
+#include <QString>
+#include <QTimer>
+#include <json-c/json.h>
+#include <systemd/sd-event.h>
+extern "C" {
+#include <afb/afb-proto-ws.h>
+#include <afb/afb-ws-client.h>
+}
+
+class AppFwHandler : public QObject
+{
+ Q_OBJECT
+public:
+ AppFwHandler(const char* appname, QObject *parent = nullptr);
+ AppFwHandler(AppFwHandler&) = delete;
+ AppFwHandler &operator=(AppFwHandler&) = delete;
+ ~AppFwHandler() = default;
+
+ int init(void);
+ int runnables(void);
+ int detail(QString id);
+ void on_pws_hangup(void);
+ void registerCallback(
+ /* can't be NULL */
+ void (*on_reply_cb)(void *closure, void *request, struct json_object *obj, const char *error, const char *info),
+
+ /* can be NULL */
+ void (*on_event_create_cb)(void *closure, const char *event_name, int event_id) = nullptr,
+ void (*on_event_remove_cb)(void *closure, const char *event_name, int event_id) = nullptr,
+ void (*on_event_subscribe_cb)(void *closure, void *request, const char *event_name, int event_id) = nullptr,
+ void (*on_event_unsubscribe_cb)(void *closure, void *request, const char *event_name, int event_id) = nullptr,
+ void (*on_event_push_cb)(void *closure, const char *event_name, int event_id, struct json_object *data) = nullptr,
+ void (*on_event_broadcast_cb)(void *closure, const char *event_name, struct json_object *data) = nullptr);
+
+ static AppFwHandler* myself;
+signals:
+ void applistupdate(QStringList info);
+
+private slots:
+ void connect_pws_timer_slot(void);
+
+private:
+ int try_connect_pws(void);
+ void attempt_connect_pws(int count);
+ int call(const char *verb, const char *object);
+
+ QString m_api = "afm-main";
+ QString m_uri;
+ QString m_sessionid;
+ sd_event *m_evloop = nullptr;
+ afb_proto_ws *m_pws = nullptr;
+ QTimer* m_time;
+ int m_retry = 0;
+};
+
+#endif // APPFWHANDLER_H
diff --git a/launcher/src/applicationmodel.cpp b/launcher/src/applicationmodel.cpp
index 090a300..003fe61 100644
--- a/launcher/src/applicationmodel.cpp
+++ b/launcher/src/applicationmodel.cpp
@@ -33,6 +33,9 @@ class ApplicationModel::Private
public:
Private();
+ void addApp(QString icon, QString name, QString id);
+ void removeApp(QString id);
+
QList<AppInfo> data;
};
@@ -61,17 +64,46 @@ ApplicationModel::Private::Private()
auto const icon = get_icon_name(jso);
// Hide HomeScreen icon itself
- if (name != "launcher" &&
- name != "homescreen-2017" &&
- name != "homescreen" &&
- !name.contains("OnScreen", Qt::CaseInsensitive)) {
- this->data.append(AppInfo(icon, name, id));
- }
+ if (name != "launcher" &&
+ name != "homescreen-2017" &&
+ name != "homescreen" &&
+ name != "restriction" &&
+ !name.contains("OnScreen", Qt::CaseInsensitive)) {
+ this->data.append(AppInfo(icon, name, id));
+ }
HMI_DEBUG("launcher","name: %s icon: %s id: %s.", name.toStdString().c_str(), icon.toStdString().c_str(), id.toStdString().c_str());
}
}
+void ApplicationModel::Private::addApp(QString icon, QString name, QString id)
+{
+ HMI_DEBUG("addApp","name: %s icon: %s id: %s.", name.toStdString().c_str(), icon.toStdString().c_str(), id.toStdString().c_str());
+ for(int i = 0; i < this->data.size(); ++i) {
+ if(this->data[i].id() == id)
+ return;
+ }
+
+ QString _icon = name.toLower();
+ if ( !QFile::exists(QString(":/images/%1_active.svg").arg(_icon)) ||
+ !QFile::exists(QString(":/images/%1_inactive.svg").arg(_icon)) )
+ {
+ _icon = "blank";
+ }
+ this->data.append(AppInfo(_icon, name, id));
+}
+
+void ApplicationModel::Private::removeApp(QString id)
+{
+ HMI_DEBUG("removeApp","id: %s.",id.toStdString().c_str());
+ for (int i = 0; i < this->data.size(); ++i) {
+ if (this->data.at(i).id() == id) {
+ this->data.removeAt(i);
+ break;
+ }
+ }
+}
+
ApplicationModel::ApplicationModel(QObject *parent)
: QAbstractListModel(parent)
, d(new Private())
@@ -155,3 +187,27 @@ void ApplicationModel::move(int from, int to)
HMI_NOTICE("launcher","from : %d, to : %d. false.", from, to);
}
}
+
+void ApplicationModel::updateApplist(QStringList info)
+{
+ QString icon = info.at(0);
+ QString name = info.at(1);
+ QString id = info.at(2);
+ QString appid = id.split('@')[0];
+
+ if ( appid == "launcher" ||
+ appid == "homescreen-2017" ||
+ appid == "homescreen" ||
+ appid.contains("onscreen", Qt::CaseInsensitive)) {
+ return;
+ }
+ beginResetModel();
+ if(icon == "") { // uninstall
+ d->removeApp(id);
+ }
+ else {
+ // new app
+ d->addApp(icon, name, id);
+ }
+ endResetModel();
+}
diff --git a/launcher/src/applicationmodel.h b/launcher/src/applicationmodel.h
index 8398b62..750bf75 100644
--- a/launcher/src/applicationmodel.h
+++ b/launcher/src/applicationmodel.h
@@ -34,6 +34,7 @@ public:
Q_INVOKABLE QString id(int index) const;
Q_INVOKABLE QString name(int index) const;
Q_INVOKABLE void move(int from, int to);
+ Q_INVOKABLE void updateApplist(QStringList info);
private:
class Private;
diff --git a/launcher/src/main.cpp b/launcher/src/main.cpp
index d79e880..8cdb76a 100644
--- a/launcher/src/main.cpp
+++ b/launcher/src/main.cpp
@@ -31,6 +31,7 @@
#include "afm_user_daemon_proxy.h"
#include "qlibhomescreen.h"
#include "hmi-debug.h"
+#include "appfwhandler.h"
// XXX: We want this DBus connection to be shared across the different
// QML objects, is there another way to do this, a nice way, perhaps?
@@ -128,6 +129,9 @@ int main(int argc, char *argv[])
layoutHandler->activateSurface(myname);
});
+ AppFwHandler* appfwhandler = new AppFwHandler(myname.toStdString().c_str());
+ appfwhandler->init();
+
QUrl bindingAddress;
bindingAddress.setScheme(QStringLiteral("ws"));
bindingAddress.setHost(QStringLiteral("localhost"));
@@ -154,6 +158,7 @@ int main(int argc, char *argv[])
engine.rootContext()->setContextProperty(QStringLiteral("homescreenHandler"), homescreenHandler);
engine.rootContext()->setContextProperty(QStringLiteral("launcher"), launcher);
engine.rootContext()->setContextProperty(QStringLiteral("screenInfo"), &screenInfo);
+ engine.rootContext()->setContextProperty(QStringLiteral("appfwhandler"), appfwhandler);
engine.load(QUrl(QStringLiteral("qrc:/Launcher.qml")));
QObject *root = engine.rootObjects().first();