Fix area and role
[apps/agl-service-windowmanager.git] / src / main.cpp
index d0d7930..2584da0 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*;
  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +18,9 @@
 #include <algorithm>
 #include <mutex>
 #include <json.h>
+#include <stdlib.h>
+#include <vector>
+#include "util.hpp"
 #include "window_manager.hpp"
 #include "json_helper.hpp"
 
@@ -46,6 +49,8 @@ struct afb_instance
     ~afb_instance() = default;
 
     int init();
+
+    bool testFlg;
 };
 
 struct afb_instance *g_afb_instance;
@@ -68,6 +73,8 @@ int _binding_init()
         goto error;
     }
 
+    g_afb_instance->testFlg = false;
+
     atexit([] { delete g_afb_instance; });
 
     return 0;
@@ -223,6 +230,49 @@ void windowmanager_requestsurfacexdg(afb_req req) noexcept
     }
 }
 
+void windowmanager_setrole(afb_req req) noexcept
+{
+    std::lock_guard<std::mutex> guard(binding_m);
+    if (g_afb_instance == nullptr)
+    {
+        afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
+        return;
+    }
+    try
+    {
+        json_object *jreq = afb_req_json(req);
+
+        json_object *j_role = nullptr;
+        if (!json_object_object_get_ex(jreq, "role", &j_role))
+        {
+            afb_req_fail(req, "failed", "Need char const* argument role");
+            return;
+        }
+        char const *a_role = json_object_get_string(j_role);
+        char *appid = afb_req_get_application_id(req);
+
+        if(appid)
+        {
+            auto ret = g_afb_instance->wmgr.api_set_role(appid, a_role);
+            if (!ret)
+            {
+                afb_req_fail(req, "failed", "Couldn't register");
+            }
+            else
+            {
+                createSecurityContext(req, appid, a_role);
+                afb_req_success(req, NULL, "success");
+            }
+            free(appid);
+        }
+    }
+    catch (std::exception &e)
+    {
+        afb_req_fail_f(req, "failed", "Uncaught exception while calling requestsurfacexdg: %s", e.what());
+        return;
+    }
+}
+
 void windowmanager_activatewindow(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
@@ -251,17 +301,62 @@ void windowmanager_activatewindow(afb_req req) noexcept
         char* appid = afb_req_get_application_id(req);
         if(appid)
         {
-            g_afb_instance->wmgr.api_activate_window(
-                appid, a_drawing_name, a_drawing_area,
-                [&req](const char *errmsg) {
-                    if (errmsg != nullptr)
-                    {
-                        HMI_ERROR(errmsg);
-                        afb_req_fail(req, "failed", errmsg);
-                        return;
-                    }
-                    afb_req_success(req, NULL, "success");
-                });
+            auto reply = [&req](const char *errmsg) {
+                if (errmsg != nullptr)
+                {
+                    HMI_ERROR(errmsg);
+                    afb_req_fail(req, "failed", errmsg);
+                    return;
+                }
+                afb_req_success(req, NULL, "success");
+            };
+
+            HMI_DEBUG("activateWindow role:%s area:%s", appid, a_drawing_area);
+
+#if 0
+            std::string appidString = appid;
+            HMI_DEBUG("flg: %d", g_afb_instance->testFlg);
+            if ((appidString == "dashboard" && g_afb_instance->testFlg) || appidString == "hudspeed")
+            { 
+                HMI_DEBUG("%s is remote transfer", appid);
+                g_afb_instance->wmgr.api_activate_surface_to_master(
+                    appid, a_drawing_name, "hud.upper.left", reply);
+
+                g_afb_instance->testFlg = false;
+                return;
+            }
+
+#endif
+            if (!g_afb_instance->wmgr.wmcon.isRemoteArea(a_drawing_area))
+            {
+                g_afb_instance->wmgr.api_activate_window(
+                    appid, a_drawing_name, a_drawing_area, reply);
+            }
+            else
+            {
+                std::string ecu_name;
+                ecu_name = g_afb_instance->wmgr.wmcon.getAreaToEcuName(a_drawing_area);
+
+                // TODO: temporarily
+                if (!g_afb_instance->wmgr.wmcon.isConnectionMode())
+                {
+                    HMI_ERROR("WM Standalone Mode");
+                    afb_req_fail(req, "failed", "Standalone Mode");
+                }
+                else
+                {
+                    // If Window Manager is slave and this request is for master,
+                    // request activateWindow to master
+                    g_afb_instance->wmgr.api_activate_surface_to_master(
+                        appid, a_drawing_name, a_drawing_area, reply);
+                }
+            }
+#if 0
+            if (appidString == "dashboard")
+            {
+                g_afb_instance->testFlg = true;
+            }
+#endif
             free(appid);
         }
     }
@@ -294,17 +389,30 @@ void windowmanager_deactivatewindow(afb_req req) noexcept
         char* appid = afb_req_get_application_id(req);
         if(appid)
         {
-            g_afb_instance->wmgr.api_deactivate_window(
-                appid, a_drawing_name,
-                [&req](const char *errmsg) {
-                    if (errmsg != nullptr)
-                    {
-                        HMI_ERROR(errmsg);
-                        afb_req_fail(req, "failed", errmsg);
-                        return;
-                    }
-                    afb_req_success(req, NULL, "success");
-                });
+            auto reply = [&req](const char *errmsg) {
+                if (errmsg != nullptr)
+                {
+                    HMI_ERROR(errmsg);
+                    afb_req_fail(req, "failed", errmsg);
+                    return;
+                }
+                afb_req_success(req, NULL, "success");
+            };
+
+            // TODO: Check whether role is tbtnavi to request remote invisible
+            if (g_afb_instance->wmgr.wmcon.getAppIdToEcuName(appid) == "" ||
+                ("tbtnavi" != std::string(a_drawing_name)))
+            {
+                g_afb_instance->wmgr.api_deactivate_window(
+                    appid, a_drawing_name, reply);
+            }
+            else
+            {
+                // If Window Manager is slave and this request is for master,
+                // request deactivateWindow to master
+                g_afb_instance->wmgr.api_deactivate_surface_to_master(
+                    appid, a_drawing_name, reply);
+            }
             free(appid);
         }
     }
@@ -336,10 +444,21 @@ void windowmanager_enddraw(afb_req req) noexcept
         afb_req_success(req, NULL, "success");
 
         char* appid = afb_req_get_application_id(req);
+
         if(appid)
         {
-            g_afb_instance->wmgr.api_enddraw(appid, a_drawing_name);
-            free(appid);
+            if (!g_afb_instance->wmgr.wmcon.isRemoteEcu(appid) ||
+                !g_afb_instance->wmgr.wmcon.isSyncDrawingForRemote(appid))
+            {
+                g_afb_instance->wmgr.api_enddraw(appid, a_drawing_name);
+            }
+            else
+            {
+                // If Window Manager is slave and requesting app is syncDrawing,
+                // request endDraw to master
+                g_afb_instance->wmgr.api_enddraw_for_remote(appid, a_drawing_name);
+            }
+           free(appid);
         }
     }
     catch (std::exception &e)
@@ -414,6 +533,191 @@ void windowmanager_getareainfo_thunk(afb_req req) noexcept
     }
 }
 
+void windowmanager_getcarinfo_thunk(afb_req req) noexcept
+{
+    std::lock_guard<std::mutex> guard(binding_m);
+    if (g_afb_instance == nullptr)
+    {
+        afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
+        return;
+    }
+
+    try
+    {
+        json_object *jreq = afb_req_json(req);
+
+        json_object *j_label = nullptr;
+        if (! json_object_object_get_ex(jreq, "label", &j_label))
+        {
+            afb_req_fail(req, "failed", "Need char const* argument label");
+            return;
+        }
+        char const* a_label = json_object_get_string(j_label);
+
+        auto ret = g_afb_instance->wmgr.api_get_car_info(a_label);
+        if (ret.is_err())
+        {
+            afb_req_fail(req, "failed", ret.unwrap_err());
+            return;
+        }
+
+        afb_req_success(req, ret.unwrap(), "success");
+    }
+    catch (std::exception &e)
+    {
+        afb_req_fail_f(req, "failed", "Uncaught exception while calling getcarinfo: %s", e.what());
+        return;
+    }
+}
+
+void windowmanager_set_render_order(afb_req req) noexcept
+{
+    std::lock_guard<std::mutex> guard(binding_m);
+    if (g_afb_instance == nullptr)
+    {
+        afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
+        return;
+    }
+
+    char* appid = afb_req_get_application_id(req);
+    if(appid)
+    {
+        json_object *jreq = afb_req_json(req);
+        json_object *j_ro; // Do not free this. binder frees jreq, then free j_ro
+        if (json_object_object_get_ex(jreq, "render_order", &j_ro))
+        {
+            int size = json_object_array_length(j_ro);
+            std::vector<std::string> ro(size);
+            for(int i = 0; i < size; i++)
+            {
+                ro[i] = json_object_get_string(json_object_array_get_idx(j_ro, i));
+            }
+
+            auto ret = g_afb_instance->wmgr.api_client_set_render_order(appid, ro);
+            if (!ret)
+            {
+                afb_req_fail(req, "failed", nullptr);
+            }
+            else
+            {
+                afb_req_success(req, nullptr, nullptr);
+            }
+        }
+        free(appid);
+    }
+    else
+    {
+        afb_req_fail(req, "failed", nullptr);
+    }
+}
+
+void windowmanager_attach_app(afb_req req) noexcept
+{
+    std::lock_guard<std::mutex> guard(binding_m);
+    if (g_afb_instance == nullptr)
+    {
+        afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
+        return;
+    }
+
+    char* appid = afb_req_get_application_id(req);
+    if(appid)
+    {
+        json_object *jreq = afb_req_json(req);
+        json_object *j_dest, *j_id; // Do not free this. binder frees jreq, then free j_ro
+        if (json_object_object_get_ex(jreq, "destination", &j_dest) &&
+            json_object_object_get_ex(jreq, "service_surface", &j_id))
+        {
+            const char* dest_app = json_object_get_string(j_dest);
+            const char* service = json_object_get_string(j_id);
+
+            std::string uuid = g_afb_instance->wmgr.api_client_attach_service_surface(appid, dest_app, service);
+            if (uuid.empty())
+            {
+                afb_req_fail(req, "failed", nullptr);
+            }
+            else
+            {
+                json_object *resp = json_object_new_object();
+                json_object_object_add(resp, "uuid", json_object_new_string(uuid.c_str()));
+                afb_req_success(req, resp, nullptr);
+            }
+        }
+        free(appid);
+    }
+    else
+    {
+        afb_req_fail(req, "failed", nullptr);
+    }
+}
+
+void windowmanager_get_area_list(afb_req req) noexcept
+{
+    std::lock_guard<std::mutex> guard(binding_m);
+    json_object* ret = g_afb_instance->wmgr.api_get_area_list();
+    afb_req_success(req, ret, nullptr);
+}
+
+void windowmanager_change_area_size(afb_req req) noexcept
+{
+    std::lock_guard<std::mutex> guard(binding_m);
+    if (g_afb_instance == nullptr)
+    {
+        afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
+        return;
+    }
+
+    char* appid = afb_req_get_application_id(req);
+    if(appid)
+    {
+        ChangeAreaReq change_req;
+        change_req.appname = appid;
+        change_req.save = false;
+        json_object *jreq = afb_req_json(req);
+        json_object *jsave, *jareas;
+        HMI_INFO("json_check, %s", json_object_get_string(jreq));
+        if(json_object_object_get_ex(jreq, "save", &jsave))
+        {
+            change_req.save = json_object_get_boolean(jsave);
+        }
+        if (json_object_object_get_ex(jreq, "areas", &jareas))
+        {
+            int size = json_object_array_length(jareas);
+            for(int i = 0; i < size; i++)
+            {
+                json_object* elem = json_object_array_get_idx(jareas, i);
+                struct rect rect;
+                std::string name = jh::getStringFromJson(elem, "name");
+                json_object* jrect;
+                if(json_object_object_get_ex(elem, "rect", &jrect))
+                {
+                    rect.x = jh::getIntFromJson(jrect, "x");
+                    rect.y = jh::getIntFromJson(jrect, "y");
+                    rect.w = jh::getIntFromJson(jrect, "w");
+                    rect.h = jh::getIntFromJson(jrect, "h");
+                }
+                else
+                {
+                    HMI_ERROR("bad request @area name :%s", name.c_str());
+                    afb_req_fail(req, "failed", "bad request");
+                    return;
+                }
+                change_req.area_req[name] = rect;
+            }
+            if(change_req.area_req.size() != 0)
+            {
+                g_afb_instance->wmgr.api_change_area_size(change_req);
+            }
+            afb_req_success(req, nullptr, nullptr);
+        }
+        free(appid);
+    }
+    else
+    {
+        afb_req_fail(req, "failed", nullptr);
+    }
+}
+
 void windowmanager_wm_subscribe(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
@@ -441,6 +745,12 @@ void windowmanager_wm_subscribe(afb_req req) noexcept
             return;
         }
         afb_req_success(req, NULL, "success");
+
+        if (event_id == 7)
+        {
+            //g_afb_instance->wmgr.api_handshake();
+            g_afb_instance->wmgr.setSubscribed(true);
+        }
     }
     catch (std::exception &e)
     {
@@ -449,6 +759,23 @@ void windowmanager_wm_subscribe(afb_req req) noexcept
     }
 }
 
+void windowmanager_connect(afb_req req) noexcept
+{
+    std::lock_guard<std::mutex> guard(binding_m);
+
+    HMI_DEBUG("WM - HS Connect");
+
+    if (g_afb_instance == nullptr)
+    {
+        afb_req_fail(req, "Failed", "Not Start WindowManager");
+        return;
+    }
+    else
+    {
+        afb_req_success(req, NULL, "success");
+    }
+}
+
 void windowmanager_ping(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
@@ -491,18 +818,30 @@ void windowmanager_debug_terminate(afb_req req) noexcept
     }
 }
 
+void on_event(const char *event, struct json_object *object)
+{
+    g_afb_instance->wmgr.analyzeReceivedEvent(event, object);
+}
+
 const struct afb_verb_v2 windowmanager_verbs[] = {
     {"requestSurface", windowmanager_requestsurface, nullptr, nullptr, AFB_SESSION_NONE},
-    {"requestSurfaceXDG", windowmanager_requestsurfacexdg, nullptr, nullptr, AFB_SESSION_NONE},
+    {"requestSurfaceXdg", windowmanager_requestsurfacexdg, nullptr, nullptr, AFB_SESSION_NONE},
+    {"setRole", windowmanager_setrole, nullptr, nullptr, AFB_SESSION_NONE},
     {"activateWindow", windowmanager_activatewindow, nullptr, nullptr, AFB_SESSION_NONE},
     {"deactivateWindow", windowmanager_deactivatewindow, nullptr, nullptr, AFB_SESSION_NONE},
     {"endDraw", windowmanager_enddraw, nullptr, nullptr, AFB_SESSION_NONE},
     {"getDisplayInfo", windowmanager_getdisplayinfo_thunk, nullptr, nullptr, AFB_SESSION_NONE},
     {"getAreaInfo", windowmanager_getareainfo_thunk, nullptr, nullptr, AFB_SESSION_NONE},
+    {"getCarInfo", windowmanager_getcarinfo_thunk, nullptr, nullptr, AFB_SESSION_NONE },
+    {"setRenderOrder", windowmanager_set_render_order, nullptr, nullptr, AFB_SESSION_NONE},
+    {"changeAreaSize", windowmanager_change_area_size, nullptr, nullptr, AFB_SESSION_NONE},
+    {"getAreaList", windowmanager_get_area_list, nullptr, nullptr, AFB_SESSION_NONE},
+    {"attachApp", windowmanager_attach_app, nullptr, nullptr, AFB_SESSION_NONE},
     {"wm_subscribe", windowmanager_wm_subscribe, nullptr, nullptr, AFB_SESSION_NONE},
+    {"wm_connect", windowmanager_connect, nullptr, nullptr, AFB_SESSION_NONE},
     {"ping", windowmanager_ping, nullptr, nullptr, AFB_SESSION_NONE},
     {"debug_terminate", windowmanager_debug_terminate, nullptr, nullptr, AFB_SESSION_NONE},
     {}};
 
 extern "C" const struct afb_binding_v2 afbBindingV2 = {
-    "windowmanager", nullptr, nullptr, windowmanager_verbs, nullptr, binding_init, nullptr, 0};
+    "windowmanager", nullptr, nullptr, windowmanager_verbs, nullptr, binding_init, on_event, 0};