Add restriction and software keyboard layers
[apps/agl-service-windowmanager.git] / src / main.cpp
index e8ae75a..067a006 100644 (file)
 #include "result.hpp"
 #include "json_helper.hpp"
 #include "util.hpp"
-#include "wayland.hpp"
+#include "wayland_ivi_wm.hpp"
+#include "low_can_client.hpp"
 
 extern "C" {
 #include <afb/afb-binding.h>
 #include <systemd/sd-event.h>
 }
 
+typedef struct wmClientCtxt{
+    std::string name;
+    wmClientCtxt(const char* appName){
+        name = appName;
+    }
+} wmClientCtxt;
+
 struct afb_instance {
    std::unique_ptr<wl::display> display;
+   wm::LowCanClient lcc_;
    wm::App app;
 
-   afb_instance() : display{new wl::display}, app{this->display.get()} {}
+   afb_instance() : display{new wl::display}, lcc_{}, app{this->display.get()} {}
 
    int init();
 };
@@ -43,6 +52,10 @@ struct afb_instance *g_afb_instance;
 std::mutex binding_m;
 
 int afb_instance::init() {
+   // Initialize LowCanClient class
+   this->lcc_.initialize();
+
+   // Initialize App class
    return this->app.init();
 }
 
@@ -149,6 +162,30 @@ int binding_init() noexcept {
    return -1;
 }
 
+static bool checkFirstReq(afb_req req){
+    wmClientCtxt* ctxt = (wmClientCtxt*)afb_req_context_get(req);
+    return (ctxt) ? false : true;
+}
+
+static void cbRemoveClientCtxt(void* data){
+    wmClientCtxt* ctxt = (wmClientCtxt*)data;
+    if(ctxt == nullptr){
+        return;
+    }
+    HMI_DEBUG("wm","remove app %s", ctxt->name.c_str());
+    // Lookup surfaceID and remove it because App is dead.
+    auto pSid = g_afb_instance->app.id_alloc.lookup(ctxt->name.c_str());
+    if(pSid){
+        auto sid = *pSid;
+        g_afb_instance->app.id_alloc.remove_id(sid);
+        g_afb_instance->app.layers.remove_surface(sid);
+        g_afb_instance->app.controller->sprops.erase(sid);
+        g_afb_instance->app.controller->surfaces.erase(sid);
+        HMI_DEBUG("wm", "delete surfaceID %d", sid);
+    }
+    delete ctxt;
+}
+
 void windowmanager_requestsurface(afb_req req) noexcept {
    std::lock_guard<std::mutex> guard(binding_m);
    #ifdef ST
@@ -166,7 +203,30 @@ void windowmanager_requestsurface(afb_req req) noexcept {
        return;
    }
 
+   /* Create Security Context */
+   bool isFirstReq = checkFirstReq(req);
+   if(!isFirstReq){
+       wmClientCtxt* ctxt = (wmClientCtxt*)afb_req_context_get(req);
+       HMI_DEBUG("wm", "You're %s.", ctxt->name.c_str());
+       if(ctxt->name != std::string(a_drawing_name)){
+           afb_req_fail_f(req, "failed", "Dont request with other name: %s for now", a_drawing_name);
+           HMI_DEBUG("wm", "Don't request with other name: %s for now", a_drawing_name);
+           return;
+       }
+   }
+
    auto ret = g_afb_instance->app.api_request_surface(a_drawing_name);
+
+   if(isFirstReq){
+       wmClientCtxt* ctxt = new wmClientCtxt(a_drawing_name);
+       HMI_DEBUG("wm", "create session for %s", ctxt->name.c_str());
+       afb_req_session_set_LOA(req, 1);
+       afb_req_context_set(req, ctxt, cbRemoveClientCtxt);
+   }
+   else{
+       HMI_DEBUG("wm", "session already created for %s", a_drawing_name);
+   }
+
    if (ret.is_err()) {
       afb_req_fail(req, "failed", ret.unwrap_err());
       return;
@@ -244,15 +304,24 @@ void windowmanager_activatesurface(afb_req req) noexcept {
        return;
    }
 
-   auto ret = g_afb_instance->app.api_activate_surface(a_drawing_name, a_drawing_area);
-   if (ret != nullptr) {
-      afb_req_fail(req, "failed", ret);
-      return;
+   const char* a_role = afb_req_value(req, "role");
+   if(!a_role){
+       a_role = "";
    }
 
-   afb_req_success(req, NULL, "success");
+   g_afb_instance->app.allocateWindowResource("activate", a_drawing_name,
+                                              a_drawing_area, a_role,
+                                              [&req](const char* errmsg){
+      if (errmsg != nullptr) {
+         HMI_ERROR("wm", errmsg);
+         afb_req_fail(req, "failed", errmsg);
+         return;
+      }
+      afb_req_success(req, NULL, "success");
+   });
+
    } catch (std::exception &e) {
-      afb_req_fail_f(req, "failed", "Uncaught exception while calling activatesurface: %s", e.what());
+      HMI_WARNING("wm", "failed", "Uncaught exception while calling activatesurface: %s", e.what());
       return;
    }
 
@@ -275,15 +344,24 @@ void windowmanager_deactivatesurface(afb_req req) noexcept {
        return;
    }
 
-   auto ret = g_afb_instance->app.api_deactivate_surface(a_drawing_name);
-   if (ret != nullptr) {
-      afb_req_fail(req, "failed", ret);
-      return;
+   const char* a_role = afb_req_value(req, "role");
+   if(!a_role){
+       a_role = "";
    }
 
-   afb_req_success(req, NULL, "success");
+   g_afb_instance->app.allocateWindowResource("deactivate", a_drawing_name,
+                                              nullptr, a_role,
+                                              [&req](const char* errmsg){
+      if (errmsg != nullptr) {
+         HMI_ERROR("wm", errmsg);
+         afb_req_fail(req, "failed", errmsg);
+         return;
+      }
+      afb_req_success(req, NULL, "success");
+   });
+
    } catch (std::exception &e) {
-      afb_req_fail_f(req, "failed", "Uncaught exception while calling deactivatesurface: %s", e.what());
+      HMI_WARNING("wm", "Uncaught exception while calling deactivatesurface: %s", e.what());
       return;
    }
 }
@@ -304,16 +382,71 @@ void windowmanager_enddraw(afb_req req) noexcept {
        afb_req_fail(req, "failed", "Need char const* argument drawing_name");
        return;
    }
+   afb_req_success(req, NULL, "success");
 
-   auto ret = g_afb_instance->app.api_enddraw(a_drawing_name);
-   if (ret != nullptr) {
-      afb_req_fail(req, "failed", ret);
+   g_afb_instance->app.api_enddraw(a_drawing_name);
+
+   } catch (std::exception &e) {
+      HMI_WARNING("wm", "failed", "Uncaught exception while calling enddraw: %s", e.what());
       return;
    }
 
-   afb_req_success(req, NULL, "success");
+}
+
+void windowmanager_getdisplayinfo_thunk(afb_req req) noexcept {
+   std::lock_guard<std::mutex> guard(binding_m);
+   #ifdef ST
+   ST();
+   #endif
+   if (g_afb_instance == nullptr) {
+      afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
+      return;
+   }
+
+   try {
+   auto ret = g_afb_instance->app.api_get_display_info();
+   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 getdisplayinfo: %s", e.what());
+      return;
+   }
+
+}
+
+void windowmanager_getareainfo_thunk(afb_req req) noexcept {
+   std::lock_guard<std::mutex> guard(binding_m);
+   #ifdef ST
+   ST();
+   #endif
+   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_drawing_name = nullptr;
+   if (! json_object_object_get_ex(jreq, "drawing_name", &j_drawing_name)) {
+      afb_req_fail(req, "failed", "Need char const* argument drawing_name");
+      return;
+   }
+   char const* a_drawing_name = json_object_get_string(j_drawing_name);
+
+   auto ret = g_afb_instance->app.api_get_area_info(a_drawing_name);
+   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 enddraw: %s", e.what());
+      afb_req_fail_f(req, "failed", "Uncaught exception while calling getareainfo: %s", e.what());
       return;
    }
 
@@ -337,6 +470,12 @@ void windowmanager_wm_subscribe(afb_req req) noexcept {
       return;
    }
    int event_type = json_object_get_int(j);
+   if ((wm::App::Event_Val_Min > event_type)
+       || (wm::App::Event_Val_Max < event_type)) {
+      afb_req_fail(req, "failed", "Invalid EventType");
+      return;
+   }
+
    const char *event_name = g_afb_instance->app.kListEventName[event_type];
    struct afb_event event = g_afb_instance->app.map_afb_event[event_name];
    int ret = afb_req_subscribe(req, event);
@@ -508,6 +647,8 @@ const struct afb_verb_v2 windowmanager_verbs[] = {
    { "activatesurface", windowmanager_activatesurface, nullptr, nullptr, AFB_SESSION_NONE },
    { "deactivatesurface", windowmanager_deactivatesurface, 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 },
    { "wm_subscribe", windowmanager_wm_subscribe, nullptr, nullptr, AFB_SESSION_NONE },
    { "list_drawing_names", windowmanager_list_drawing_names, nullptr, nullptr, AFB_SESSION_NONE },
    { "ping", windowmanager_ping, nullptr, nullptr, AFB_SESSION_NONE },
@@ -518,5 +659,48 @@ const struct afb_verb_v2 windowmanager_verbs[] = {
    {}
 };
 
+void on_event(const char *event, struct json_object *object){
+    HMI_DEBUG("wm", "event:%s", event);
+
+    // If receive low can signal
+    if (strstr(event, "low-can")) {
+        // Analyze low can signal
+        g_afb_instance->lcc_.analyzeCanSignal(object);
+
+        if (g_afb_instance->lcc_.isChangedCarState()) {
+            // If car state is changed
+            HMI_DEBUG("wm", "Car state is changed");
+
+            // Get car state
+            const char* car_state = g_afb_instance->lcc_.getCurrentCarState();
+
+            // Allocate window resource
+            g_afb_instance->app.allocateWindowResource(car_state, nullptr,
+                                                       nullptr, nullptr,
+                                                       [](const char* errmsg){
+                if (errmsg != nullptr) {
+                    HMI_ERROR("wm", errmsg);
+                }
+            });
+        }
+        else if (g_afb_instance->lcc_.isChangedLampState()) {
+            // If lamp state is changed
+            HMI_DEBUG("wm", "Lamp state is changed");
+
+            // Get lamp state
+            const char* lamp_state = g_afb_instance->lcc_.getCurrentLampState();
+
+            // Allocate window resource
+            g_afb_instance->app.allocateWindowResource(lamp_state, nullptr,
+                                                       nullptr, nullptr,
+                                                       [](const char* errmsg){
+                if (errmsg != nullptr) {
+                    HMI_ERROR("wm", errmsg);
+                }
+            });
+        }
+    }
+}
+
 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};