Add chage remote app
[apps/agl-service-windowmanager.git] / src / wm_layer_control.cpp
index 28d409f..887fc58 100644 (file)
@@ -1,6 +1,5 @@
 /*
  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
- * Copyright (c) 2018 Konsulko Group
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "request.hpp"
 #include "json_helper.hpp"
 
-#define LC_AREA_FILE "areas.json"
-#define LC_LAYER_SETTING_FILE "layers.json"
+#define LC_AREA_PATH "/etc/areas.json"
+#define LC_LAYER_SETTING_PATH "/etc/layers.json"
+#define LC_WESTON_SETTING_PATH "/etc/weston.json"
 #define LC_DEFAULT_AREA "fullscreen"
 #define BACK_GROUND_LAYER "BackGroundLayer"
+#define AREA_NAME_RSE1 "rse1.normal.full"
+#define AREA_NAME_RSE2 "rse2.normal.full"
+#define AREA_NAME_HUD "hud.normal.full"
+#define AREA_NAME_HUD_UL "hud.upper.left"
+#define defaultWestonTimes 60000
+#define defaultWestonSleep 50
 
 using std::string;
 using std::vector;
@@ -57,15 +63,19 @@ static void layerCallback_static(t_ilm_layer layer,
     g_lc_ctxt->dispatchLayerPropChangeEvent(layer, layer_prop, mask);
 }
 
-LayerControl::LayerControl(const std::string& root)
+LayerControl::LayerControl(const std::string& root, const std::string& ecu_name)
 {
-    string area_path(get_file_path(LC_AREA_FILE, root.c_str()));
-    string layer_path(get_file_path(LC_LAYER_SETTING_FILE, root.c_str()));
+    string area_path = root + LC_AREA_PATH;
+    string layer_path= root + LC_LAYER_SETTING_PATH;
+    string weston_path = root + LC_WESTON_SETTING_PATH;
+
+    this->loadWestonSetting(weston_path);
+
     // load layers.setting.json
     WMError ret = this->loadLayerSetting(layer_path);
     assert(ret == WMError::SUCCESS);
     // load areas.json
-    ret = this->loadAreaDb(area_path);
+    ret = this->loadAreasConfigFile(area_path, ecu_name);
     assert(ret == WMError::SUCCESS);
 }
 
@@ -74,21 +84,37 @@ WMError LayerControl::init(const LayerControlCallbacks& cb)
     HMI_DEBUG("Initialize of ilm library and display");
     t_ilm_uint num = 0;
     t_ilm_uint *ids;
-    int cnt = 0;
-    ilmErrorTypes rc = ilm_init();
+    ilmErrorTypes rc;
+    struct timespec startTs, endTs;
+
+    if (clock_gettime(CLOCK_BOOTTIME, &startTs) != 0)
+    {
+        HMI_ERROR("Could't set time (clock_gettime() returns with error");
+        goto lc_init_error;
+    }
+
+    endTs = startTs;
 
-    while (rc != ILM_SUCCESS)
+    while ((startTs.tv_sec + (this->times / 1000)) > endTs.tv_sec)
     {
-        cnt++;
-        if (20 <= cnt)
+        rc = ilm_init();
+
+        if (rc == ILM_SUCCESS)
         {
-            HMI_ERROR("Could not connect to compositor");
-            goto lc_init_error;
+            HMI_DEBUG("Weston Connected");
+            break;
         }
+
         HMI_ERROR("Wait to start weston ...");
-        sleep(1);
-        rc = ilm_init();
+        usleep(this->sleep * 1000);
+
+        if (clock_gettime(CLOCK_BOOTTIME, &endTs) != 0)
+        {
+            HMI_ERROR("Could't set time (clock_gettime() returns with error");
+            goto lc_init_error;
+        }
     }
+
     if(rc != ILM_SUCCESS) goto lc_init_error;
 
     // Get current screen setting
@@ -99,12 +125,16 @@ WMError LayerControl::init(const LayerControlCallbacks& cb)
     for(unsigned i = 0; i < num; i++)
     {
         HMI_INFO("get screen: %d", ids[i]);
+        ilmScreenProperties prop;
+        rc = ilm_getPropertiesOfScreen(ids[i], &prop);
+
+        if(rc != ILM_SUCCESS) goto lc_init_error;
+        this->wm_screens.emplace_back(Screen(ids[i], prop.screenWidth, prop.screenHeight));
     }
+
     // Currently, 0 is only available
     this->screenID = ids[0];
 
-    rc = ilm_getPropertiesOfScreen(this->screenID, &this->screen_prop);
-
     if(rc != ILM_SUCCESS) goto lc_init_error;
 
     // Register Callback to Window Manager and from ILM
@@ -134,7 +164,22 @@ void LayerControl::createNewLayer(unsigned id)
     this->renderLayers();
 }
 
-unsigned LayerControl::getNewLayerID(const string& role)
+void LayerControl::createNewRemoteLayer(unsigned id)
+{
+    HMI_INFO("create new ID :%d (For remote layer)", id);
+    struct rect rct = {640, 720, 0, 0};
+    ilm_layerCreateWithDimension(&id, rct.w, rct.h);
+    //ilm_layerSetSourceRectangle(id, rct.x, rct.y, rct.w, rct.h);
+    ilm_layerSetDestinationRectangle(id, this->offset_x, this->offset_y, rct.w, rct.h);
+    ilm_layerSetOpacity(id, 1.0);
+    ilm_layerSetVisibility(id, ILM_FALSE);
+    ilm_commitChanges();
+    auto wm_layer = getWMLayer(id);
+    wm_layer->addLayerToState(id);
+    this->renderLayers();
+}
+
+unsigned LayerControl::getNewLayerID(const string& role, string* layer_name)
 {
     unsigned ret = 0;
     for(const auto& l: this->wm_layers)
@@ -142,6 +187,7 @@ unsigned LayerControl::getNewLayerID(const string& role)
         ret = l->getNewLayerID(role);
         if(ret != 0)
         {
+            *layer_name = l->layerName();
             unsigned wmlid = l->getWMLayerID();
             this->lid2wmlid[ret] = wmlid;
             break;
@@ -179,6 +225,10 @@ void LayerControl::setupArea(const rectangle& base_rct, double scaling)
     this->offset_x = base_rct.left();
     this->offset_y = base_rct.top();
 
+    // TODO: set all screen
+    this->wm_screens[0].setScale(scaling);
+    this->wm_screens[0].setOffset(offset_x, offset_y);
+
     for (auto &i : this->area2size)
     {
         i.second.x = static_cast<int>(scaling * i.second.x + 0.5);
@@ -193,7 +243,7 @@ void LayerControl::setupArea(const rectangle& base_rct, double scaling)
 
 Screen LayerControl::getScreenInfo()
 {
-    return Screen(this->screen_prop.screenWidth, this->screen_prop.screenHeight);
+    return wm_screens[0];
 }
 
 double LayerControl::scale()
@@ -201,55 +251,69 @@ double LayerControl::scale()
     return this->scaling;
 }
 
+WMError LayerControl::updateLayer(LayerState& layer_state)
+{
+    return WMError::SUCCESS;
+}
+
 WMError LayerControl::renderLayers()
 {
     HMI_INFO("Commit change");
     WMError rc = WMError::SUCCESS;
 
-    // Check the number of layers
-    vector<unsigned> ivi_l_ids;
-    for(auto& l : this->wm_layers)
+    // Create render order for each screen and set render order
+    for(const auto& screen : this->wm_screens)
     {
-        auto state = l->getLayerState();
-        HMI_DEBUG("layer %s", l->layerName().c_str());
-        for(const auto& id : state.getIviIdList())
+        unsigned size_ids = 0;
+        for(const auto& wm_l : this->wm_layers)
         {
-            HMI_DEBUG("Add %d", id);
-            ivi_l_ids.push_back(id);
+            if(wm_l->getScreenID() == screen.id())
+            {
+                for(const auto& id : wm_l->getLayerState().getIviIdList())
+                {
+                    ++size_ids;
+                }
+            }
+        }
+        t_ilm_layer* id_array = new t_ilm_layer[size_ids];
+        if(id_array == nullptr)
+        {
+            HMI_WARNING("short memory");
+            this->undoUpdate();
+            return WMError::FAIL;
+        }
+        int idx = 0;
+        for(const auto& wm_l : this->wm_layers)
+        {
+            if(wm_l->getScreenID() == screen.id())
+            {
+                for(const auto& id : wm_l->getLayerState().getIviIdList())
+                {
+                    id_array[idx] = id;
+                    ++idx;
+                }
+            }
         }
-    }
-
-    // Create render order
-    t_ilm_layer* id_array = new t_ilm_layer[ivi_l_ids.size()];
-    if(id_array == nullptr)
-    {
-        HMI_WARNING("short memory");
-        this->undoUpdate();
-        return WMError::FAIL;
-    }
-    int count = 0;
-    for(const auto& i : ivi_l_ids)
-    {
-        id_array[count] = i;
-        ++count;
-    }
 
-    // Display
-    ilmErrorTypes ret = ilm_displaySetRenderOrder(this->screenID, id_array, ivi_l_ids.size());
-    if(ret != ILM_SUCCESS)
-    {
-        this->undoUpdate();
-        rc = WMError::FAIL;
-    }
-    else
-    {
-        for(auto& l : this->wm_layers)
+        // Send to display
+        ilmErrorTypes ret = ilm_displaySetRenderOrder(screen.id(), id_array, size_ids);
+        if(ret != ILM_SUCCESS)
+        {
+            this->undoUpdate();
+            return WMError::FAIL;
+        }
+        else
         {
-            l->update();
+            for(auto& l : this->wm_layers)
+            {
+                if(l->getScreenID() == screen.id()) {
+                    l->update();
+                }
+            }
         }
+        ilm_commitChanges();
+        delete id_array;
     }
-    ilm_commitChanges();
-    delete id_array;
     return rc;
 }
 
@@ -276,6 +340,31 @@ void LayerControl::undoUpdate()
     }
 }
 
+int LayerControl::loadWestonSetting(const string &path)
+{
+    HMI_DEBUG("loading Weston(Conpositor Time Out) Setting from %s", path.c_str());
+
+    json_object *json_obj;
+
+    int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
+    if (0 > ret)
+    {
+        HMI_ERROR("Could not open %s, so use default", path.c_str());
+        this->times = defaultWestonTimes;
+        this->sleep = defaultWestonSleep;
+        return 0;
+    }
+    HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
+
+    long times = jh::getIntFromJson(json_obj, "times");
+    this->times = (0 != times) ? times : defaultWestonTimes;
+
+    long sleep = jh::getIntFromJson(json_obj, "sleep");
+    this->sleep = (0 != sleep) ? sleep : defaultWestonSleep;
+
+    return 0;
+}
+
 WMError LayerControl::loadLayerSetting(const string &path)
 {
     HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path);
@@ -304,15 +393,25 @@ WMError LayerControl::loadLayerSetting(const string &path)
         HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
 
         this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp, i));
+
+        int screen = jh::getIntFromJson(json_tmp, "screen");
+        if (screen > 0)
+        {
+            std::string layerName = jh::getStringFromJson(json_tmp, "name");
+
+            HMI_DEBUG("Remote Layer Name:%s Screen: %d", layerName.c_str(), screen);
+            this->wm_remoteLayerName.push_back(layerName);
+        }
+
     }
     json_object_put(json_obj);
 
     return WMError::SUCCESS;
 }
 
-WMError LayerControl::loadAreaDb(const std::string& path)
+WMError LayerControl::loadAreasConfigFile(const std::string& path, const std::string& ecu_name)
 {
-    // Load area.db
+    // Load areas config file
     json_object *json_obj;
     int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
     if (0 > ret)
@@ -322,54 +421,115 @@ WMError LayerControl::loadAreaDb(const std::string& path)
     }
     HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj));
 
-    // Perse areas
+    // Parse ecus
     json_object *json_cfg;
-    if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))
+    if (!json_object_object_get_ex(json_obj, "ecus", &json_cfg))
     {
         HMI_ERROR("Parse Error!!");
         return WMError::FAIL;
     }
 
-    int len = json_object_array_length(json_cfg);
-    HMI_DEBUG("json_cfg len:%d", len);
+    int num_ecu = json_object_array_length(json_cfg);
+    HMI_DEBUG("json_cfg(ecus) len:%d", num_ecu);
 
-    const char *area;
-    for (int i = 0; i < len; i++)
+    const char* c_ecu_name;
+    json_object *json_ecu;
+    for (int i = 0; i < num_ecu; i++)
     {
-        json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
-        HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
+        json_ecu= json_object_array_get_idx(json_cfg, i);
 
-        area = jh::getStringFromJson(json_tmp, "name");
-        if (nullptr == area)
+        c_ecu_name = jh::getStringFromJson(json_ecu, "name");
+        if (nullptr == c_ecu_name)
         {
             HMI_ERROR("Parse Error!!");
             return WMError::FAIL;
         }
-        HMI_DEBUG("> area:%s", area);
 
-        json_object *json_rect;
-        if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))
+        if (ecu_name == string(c_ecu_name))
         {
-            HMI_ERROR("Parse Error!!");
-            return WMError::FAIL;
+            break;
+        }
+        else
+        {
+            json_ecu = nullptr;
         }
-        HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));
+    }
 
-        struct rect area_size;
-        area_size.x = jh::getIntFromJson(json_rect, "x");
-        area_size.y = jh::getIntFromJson(json_rect, "y");
-        area_size.w = jh::getIntFromJson(json_rect, "w");
-        area_size.h = jh::getIntFromJson(json_rect, "h");
+    if (!json_ecu)
+    {
+        HMI_ERROR("Areas for ecu:%s is NOT exist!!", ecu_name.c_str());
+        return WMError::FAIL;
+    }
 
-        this->area2size[area] = area_size;
+    // Parse screens
+    if (!json_object_object_get_ex(json_ecu, "screens", &json_cfg))
+    {
+        HMI_ERROR("Parse Error!!");
+        return WMError::FAIL;
     }
 
-    // Check
-    for (const auto& itr : this->area2size)
+    int num_screen = json_object_array_length(json_cfg);
+    HMI_DEBUG("json_cfg(screens) len:%d", num_screen);
+
+    json_object *json_screen;
+    for (int i = 0; i < num_screen; i++)
     {
-        HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",
-                  itr.first.c_str(), itr.second.x, itr.second.y,
-                  itr.second.w, itr.second.h);
+        int screen_id;
+        json_screen = json_object_array_get_idx(json_cfg, i);
+        HMI_INFO("json_cfg dump:%s", json_object_get_string(json_cfg));
+
+        // TODO: Currently only one display is connected to a ECU.
+
+        screen_id = jh::getIntFromJson(json_screen, "id"); // screen_id is not used currently
+
+        // Parse areas
+        json_object *json_tmp;
+        if (!json_object_object_get_ex(json_screen, "areas", &json_tmp))
+        {
+            HMI_ERROR("Parse Error!!");
+            return WMError::FAIL;
+        }
+
+        int num_area = json_object_array_length(json_tmp);
+        HMI_DEBUG("json_tmp(areas) len:%d", num_area);
+
+        const char *area;
+        for (int j = 0; j < num_area; j++)
+        {
+            json_object *json_area = json_object_array_get_idx(json_tmp, j);
+
+            area = jh::getStringFromJson(json_area, "name");
+            if (nullptr == area)
+            {
+                HMI_ERROR("Parse Error!!");
+                return WMError::FAIL;
+            }
+            HMI_DEBUG("> area:%s", area);
+
+            json_object *json_rect;
+            if (!json_object_object_get_ex(json_area, "rect", &json_rect))
+            {
+                HMI_ERROR("Parse Error!!");
+                return WMError::FAIL;
+            }
+
+            struct rect area_size;
+            area_size.x = jh::getIntFromJson(json_rect, "x");
+            area_size.y = jh::getIntFromJson(json_rect, "y");
+            area_size.w = jh::getIntFromJson(json_rect, "w");
+            area_size.h = jh::getIntFromJson(json_rect, "h");
+            HMI_INFO("%d, %d, %d, %d, ", area_size.x, area_size.y, area_size.w, area_size.h);
+
+            this->area2size[area] = area_size;
+        }
+
+        // Check
+        for (const auto& itr : this->area2size)
+        {
+            HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",
+                      itr.first.c_str(), itr.second.x, itr.second.y,
+                      itr.second.w, itr.second.h);
+        }
     }
 
     // Release json_object
@@ -380,7 +540,9 @@ WMError LayerControl::loadAreaDb(const std::string& path)
 
 WMError LayerControl::layoutChange(const WMAction& action)
 {
-    if (action.visible == TaskVisible::INVISIBLE)
+    if ((action.visible == TaskVisible::INVISIBLE) ||
+        (action.visible == TaskVisible::REQ_REMOTE_VISIBLE) ||
+        (action.visible == TaskVisible::REQ_REMOTE_INVISIBLE))
     {
         // Visibility is not change -> no redraw is required
         return WMError::SUCCESS;
@@ -394,26 +556,22 @@ WMError LayerControl::layoutChange(const WMAction& action)
     unsigned surface = action.client->surfaceID();
 
     auto rect = this->getAreaSize(action.area);
-    HMI_SEQ_INFO(action.req_num, "Set layout %d, %d, %d, %d",rect.x, rect.y, rect.w, rect.h);
+    HMI_DEBUG("Set layout %d, %d, %d, %d",rect.x, rect.y, rect.w, rect.h);
 
+    // TO BE FIXED:
     // Sometimes, ivi_wm_surface_size signal doesn't reach window manager,
-    // then, Window Manager set set source size = 0.
-    if(!action.client->isSourceSizeSet())
-    {
-        ilmSurfaceProperties sp;
-        ilm_getPropertiesOfSurface(surface, &sp);
-        if((sp.origSourceHeight != sp.sourceHeight) || (sp.origSourceWidth != sp.sourceWidth))
-        {
-            HMI_SEQ_NOTICE(action.req_num, "set source size w:%d h%d", sp.origSourceWidth, sp.origSourceHeight);
-            ilm_surfaceSetSourceRectangle(surface, 0, 0, sp.origSourceWidth, sp.origSourceHeight);
-            ilm_commitChanges();
-            action.client->setSurfaceSizeCorrectly();
-        }
+    // then, Window Manager can't set source size.
+    // This fixes it but it takes about 200ns(on R-Car M3) wastefully
+    ilmSurfaceProperties sp;
+    ilm_getPropertiesOfSurface(surface, &sp);
+    if(sp.origSourceHeight != sp.sourceHeight) {
+        HMI_SEQ_NOTICE(action.req_num, "WORK AROUND: set source size w:%d h%d", sp.origSourceWidth, sp.origSourceHeight);
+        ilm_surfaceSetSourceRectangle(surface, 0, 0, sp.origSourceWidth, sp.origSourceHeight);
+        ilm_commitChanges();
     }
 
     ilm_surfaceSetDestinationRectangle(surface, rect.x, rect.y, rect.w, rect.h);
     ilm_commitChanges();
-    action.client->setArea(action.area);
     for(auto &wm_layer: this->wm_layers)
     {
         // Store the state who is assigned to the area
@@ -439,15 +597,30 @@ WMError LayerControl::visibilityChange(const WMAction& action)
         return WMError::NOT_REGISTERED;
     }
 
-    if (action.visible == TaskVisible::VISIBLE)
+    if (action.visible == TaskVisible::VISIBLE) 
     {
         ret = this->makeVisible(action.client);
     }
-    else if (action.visible == TaskVisible::INVISIBLE)
+    else if (action.visible == TaskVisible::INVISIBLE) 
     {
         ret = this->makeInvisible(action.client);
     }
-    ilm_commitChanges();
+    else if (action.visible == TaskVisible::REMOTE_VISIBLE)
+    {
+        ret = this->makeVisible(action.client);
+        this->moveRemote(action.client->layerID(), action.area);
+    }
+    else if (action.visible == TaskVisible::REMOTE_INVISIBLE)
+    {
+        ret = this->makeInvisible(action.client);
+        this->moveLocal(action.client->layerID());
+    }
+    else // TaskVisible::REQ_REMOTE_VISIBLE || TaskVisible::REQ_REMOTE_INVISIBLE
+    {
+        // Visibility is not change
+        ret = WMError::SUCCESS;
+    }
+
     return ret;
 }
 
@@ -519,6 +692,7 @@ void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool c
                 return;
             }
             this->cb.surfaceCreated(sp.creatorPid, id);
+            ilm_surfaceSetSourceRectangle(id, 0, 0, sp.origSourceWidth, sp.origSourceHeight);
             ilm_surfaceAddNotification(id, surfaceCallback_static);
             ilm_surfaceSetVisibility(id, ILM_TRUE);
             ilm_surfaceSetType(id, ILM_SURFACETYPE_DESKTOP);
@@ -684,4 +858,102 @@ bool LayerControl::moveForeGround(const shared_ptr<WMClient> client)
     return ret;
 }
 
+bool LayerControl::moveRemote(unsigned layer, const std::string& area)
+{
+    bool ret = false;
+    std::string remote_layer;
+    std::string ecu_name = area;
+
+    if (area.find('.') != std::string::npos)
+    {
+        std::vector<std::string> elements;
+        elements = parseString(area, '.');
+        ecu_name = elements[0];
+    }
+
+    remote_layer = this->areaToRemoteLayer(ecu_name);
+
+    auto remote = this->getWMLayer(remote_layer);
+    
+    if(remote != nullptr)
+    {
+        ret = true;
+        if(remote->hasLayerID(layer))
+        {
+            HMI_DEBUG("Already moved layer %d", layer);
+            remote->dump();
+            return ret;
+        }
+
+        shared_ptr<WMLayer> wm_layer;
+        std::string wm_layer_name = this->hasRemoteLayer(layer);
+
+        if(wm_layer_name == "")
+        {
+            wm_layer = this->getWMLayer(layer);
+        }
+        else
+        {
+            wm_layer = this->getWMLayer(wm_layer_name);
+        }
+
+        remote->addLayerToState(layer);
+        wm_layer->removeLayerFromState(layer);
+        wm_layer->dump();
+        remote->dump();
+    }
+
+    return ret;
+}
+
+bool LayerControl::moveLocal(unsigned layer)
+{
+    bool ret = false;
+    std::string remote_layer;
+
+    remote_layer = this->hasRemoteLayer(layer);
+
+    auto remote = this->getWMLayer(remote_layer);
+    if(remote != nullptr)
+    {
+        remote->removeLayerFromState(layer);
+        auto wm_layer = this->getWMLayer(layer);
+        wm_layer->addLayerToState(layer);
+        wm_layer->dump();
+        remote->dump();
+        ret = true;
+    }
+
+    return ret;
+}
+
+std::string LayerControl::hasRemoteLayer(unsigned layer)
+{
+    for (auto itr = wm_remoteLayerName.begin(); itr != wm_remoteLayerName.end(); ++itr)
+    {
+        auto remote = this->getWMLayer(*itr);
+        if(remote != nullptr)
+        {
+            if(remote->hasLayerFromState(layer))
+            {
+                return *itr;
+            }
+        }
+    }
+
+    return "";
+}
+
+std::string LayerControl::areaToRemoteLayer(std::string area)
+{
+    for (auto itr = wm_remoteLayerName.begin(); itr != wm_remoteLayerName.end(); ++itr)
+    {
+        if (std::regex_search(*itr, std::regex(area, std::regex::icase)))
+        {
+            return *itr;
+        }
+    }
+
+    return wm_remoteLayerName[0];
+}
 } // namespace wm