aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorfukubayashi.akio <fukubayashi.akio@genetec.co.jp>2019-06-03 17:59:13 +0900
committerfukubayashi.akio <fukubayashi.akio@genetec.co.jp>2019-06-03 17:59:13 +0900
commit98006b6538c5be44350746ec3756f004a5c68af8 (patch)
treef76ed8991d3837678c00722a23b779c4e2dcb67b /src
parentb6644e5cffa84e40d62e38f4ee0c14e64e0faf48 (diff)
Add boot sequence and multi ecu transfer
Signed-off-by: fukubayashi.akio <fukubayashi.akio@genetec.co.jp>
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt15
-rw-r--r--src/applist.cpp49
-rw-r--r--src/applist.hpp1
-rw-r--r--src/config/areas.json306
-rw-r--r--src/config/connection.json48
-rw-r--r--src/config/old_roles.json68
-rw-r--r--src/config/timeout.json4
-rw-r--r--src/config/weston.json4
-rw-r--r--src/json_helper.cpp12
-rw-r--r--src/json_helper.hpp2
-rw-r--r--src/low_can_client.cpp187
-rw-r--r--src/low_can_client.hpp113
-rw-r--r--src/main.cpp375
-rw-r--r--src/pm_wrapper.cpp193
-rw-r--r--src/pm_wrapper.hpp3
-rw-r--r--src/request.cpp9
-rw-r--r--src/request.hpp35
-rw-r--r--src/util.cpp55
-rw-r--r--src/util.hpp12
-rw-r--r--src/window_manager.cpp1860
-rw-r--r--src/window_manager.hpp131
-rw-r--r--src/wm_client.cpp255
-rw-r--r--src/wm_client.hpp45
-rw-r--r--src/wm_connection.cpp845
-rw-r--r--src/wm_connection.hpp117
-rw-r--r--src/wm_layer.cpp14
-rw-r--r--src/wm_layer.hpp4
-rw-r--r--src/wm_layer_control.cpp448
-rw-r--r--src/wm_layer_control.hpp38
29 files changed, 4655 insertions, 593 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fc19a18..093b356 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -35,7 +35,9 @@ add_library(${TARGETS_WM} MODULE
wm_client.cpp
wm_error.cpp
wm_layer.cpp
- wm_layer_control.cpp)
+ wm_layer_control.cpp
+ wm_connection.cpp
+ low_can_client.cpp)
target_include_directories(${TARGETS_WM}
PRIVATE
@@ -56,7 +58,7 @@ target_link_libraries(${TARGETS_WM}
target_compile_definitions(${TARGETS_WM}
PRIVATE
- AFB_BINDING_VERSION=3
+ AFB_BINDING_VERSION=2
# We do not want source location of messages
AFB_BINDING_PRAGMA_NO_VERBOSE_DETAILS
WINMAN_VERSION_STRING="${PACKAGE_VERSION}"
@@ -70,7 +72,7 @@ endif()
target_compile_options(${TARGETS_WM}
PRIVATE
- -Wall -Wextra -Wno-unused-parameter -Wno-comment -Wno-missing-field-initializers)
+ -Wall -Wextra -Wno-unused-parameter -Wno-comment)
set_target_properties(${TARGETS_WM}
PROPERTIES
@@ -111,8 +113,11 @@ add_custom_command(TARGET ${TARGETS_WM} POST_BUILD
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/root/lib
COMMAND cp -rf ${PROJECT_BINARY_DIR}/src/${TARGETS_WM}.so ${PROJECT_BINARY_DIR}/package/root/lib
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/root/etc
- COMMAND cp -f ${CMAKE_SOURCE_DIR}/conf/layers.json ${PROJECT_BINARY_DIR}/package/root/etc
- COMMAND cp -f ${CMAKE_SOURCE_DIR}/conf/areas.json ${PROJECT_BINARY_DIR}/package/root/etc
+ COMMAND cp -f ${PROJECT_SOURCE_DIR}/layers.json ${PROJECT_BINARY_DIR}/package/root/etc
+ COMMAND cp -f ${PROJECT_SOURCE_DIR}/src/config/old_roles.json ${PROJECT_BINARY_DIR}/package/root/etc
+ COMMAND cp -f ${PROJECT_SOURCE_DIR}/src/config/areas.json ${PROJECT_BINARY_DIR}/package/root/etc
+ COMMAND cp -f ${PROJECT_SOURCE_DIR}/src/config/connection.json ${PROJECT_BINARY_DIR}/package/root/etc
+ COMMAND cp -f ${PROJECT_SOURCE_DIR}/src/config/timeout.json ${PROJECT_BINARY_DIR}/package/root/etc
)
add_custom_target(package DEPENDS ${PROJECT_BINARY_DIR}/package/root
diff --git a/src/applist.cpp b/src/applist.cpp
index 473d687..8ef08dd 100644
--- a/src/applist.cpp
+++ b/src/applist.cpp
@@ -82,27 +82,6 @@ void AppList::addClient(const string &appid, unsigned layer, const string &role)
}
/**
- * Add Client to the list
- *
- * This function is overload function.
- * But this function just register application.
- * So an application does not have role, surface, layer.
- * Client need to register role and layer afterward.
- *
- * @param string[in] Application id. This will be the key to withdraw the information.
- * @return None
- * @attention This function should be called once for the app
- * Caller should take care not to be called more than once.
- */
-void AppList::addClient(const string &appid)
-{
- std::lock_guard<std::mutex> lock(this->mtx);
- shared_ptr<WMClient> client = std::make_shared<WMClient>(appid, 0, "");
- this->app2client[appid] = client;
- this->clientDump();
-}
-
-/**
* Remove WMClient from the list
*
* @param string[in] Application id. This will be the key to withdraw the information.
@@ -332,8 +311,8 @@ const vector<struct WMAction> &AppList::getActions(unsigned req_num, bool* found
}
HMI_SEQ_ERROR(req_num, "Couldn't get action with the request : %d", req_num);
{
- static vector<struct WMAction> empty;
- return empty;
+ static vector<struct WMAction> empty;
+ return empty;
}
}
@@ -402,7 +381,7 @@ WMError AppList::setAction(unsigned req_num, shared_ptr<WMClient> client, const
}
// If visible task is not invisible, redraw is required -> true
bool edraw_f = (visible != TaskVisible::INVISIBLE) ? false : true;
- WMAction action{req_num, client, role, area, visible, edraw_f};
+ WMAction action{req_num, client, role, area, visible, edraw_f, TaskCarState::NO_TASK};
x.sync_draw_req.push_back(action);
result = WMError::SUCCESS;
@@ -438,11 +417,23 @@ bool AppList::setEndDrawFinished(unsigned req_num, const string &appid, const st
{
for (auto &y : x.sync_draw_req)
{
- if (y.client->appID() == appid && y.role == role)
+ if (nullptr != y.client)
+ {
+ if (y.client->appID() == appid && y.role == role)
+ {
+ HMI_SEQ_INFO(req_num, "Role %s finish redraw", y.role.c_str());
+ y.end_draw_finished = true;
+ result = true;
+ }
+ }
+ else
{
- HMI_SEQ_INFO(req_num, "Role %s finish redraw", y.role.c_str());
- y.end_draw_finished = true;
- result = true;
+ if (y.role == role)
+ {
+ HMI_SEQ_INFO(req_num, "Role %s finish redraw", y.role.c_str());
+ y.end_draw_finished = true;
+ result = true;
+ }
}
}
}
@@ -553,7 +544,7 @@ void AppList::reqDump()
{
DUMP(
"Action : (APPID :%s, ROLE :%s, AREA :%s, VISIBLE : %s, END_DRAW_FINISHED: %d)",
- y.client->appID().c_str(),
+ (y.client) ? y.client->appID().c_str() : "-",
y.role.c_str(),
y.area.c_str(),
(y.visible == TaskVisible::INVISIBLE) ? "invisible" : "visible",
diff --git a/src/applist.hpp b/src/applist.hpp
index 0fe3bbd..085504a 100644
--- a/src/applist.hpp
+++ b/src/applist.hpp
@@ -45,7 +45,6 @@ class AppList
void addClient(const std::string &appid, unsigned layer,
unsigned surface, const std::string &role);
void addClient(const std::string &appid, unsigned layer, const std::string &role);
- void addClient(const std::string &appid);
void removeClient(const std::string &appid);
bool contains(const std::string &appid) const;
int countClient() const;
diff --git a/src/config/areas.json b/src/config/areas.json
new file mode 100644
index 0000000..cd54725
--- /dev/null
+++ b/src/config/areas.json
@@ -0,0 +1,306 @@
+{
+ "ecus": [
+ {
+ "name": "master",
+ "screens": [
+ {
+ "id": 0,
+ "areas": [
+ {
+ "name": "fullscreen",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 1080
+ }
+ },
+ {
+ "name": "normal.full",
+ "rect": {
+ "x": 0,
+ "y": 180,
+ "w": 1920,
+ "h": 720
+ }
+ },
+ {
+ "name": "split.main",
+ "rect": {
+ "x": 0,
+ "y": 180,
+ "w": 1280,
+ "h": 720
+ }
+ },
+ {
+ "name": "split.sub",
+ "rect": {
+ "x": 1280,
+ "y": 180,
+ "w": 640,
+ "h": 720
+ }
+ },
+ {
+ "name": "software_keyboard",
+ "rect": {
+ "x": 0,
+ "y": 962,
+ "w": 1080,
+ "h": 744
+ }
+ },
+ {
+ "name": "restriction.normal",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 1080
+ }
+ },
+ {
+ "name": "restriction.split.main",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 540
+ }
+ },
+ {
+ "name": "restriction.split.sub",
+ "rect": {
+ "x": 0,
+ "y": 540,
+ "w": 1920,
+ "h": 540
+ }
+ },
+ {
+ "name": "on_screen",
+ "rect": {
+ "x": 1280,
+ "y": 0,
+ "w": 640,
+ "h": 720
+ }
+ },
+ {
+ "name": "master.split.sub",
+ "rect": {
+ "x": 1280,
+ "y": 0,
+ "w": 640,
+ "h": 720
+ }
+ },
+ {
+ "name": "hud.upper.left",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 480,
+ "h": 180
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "slave",
+ "screens": [
+ {
+ "id": 0,
+ "areas": [
+ {
+ "name": "fullscreen",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1080,
+ "h": 1920
+ }
+ },
+ {
+ "name": "normal.full",
+ "rect": {
+ "x": 0,
+ "y": 218,
+ "w": 1080,
+ "h": 1488
+ }
+ },
+ {
+ "name": "split.main",
+ "rect": {
+ "x": 0,
+ "y": 218,
+ "w": 1080,
+ "h": 744
+ }
+ },
+ {
+ "name": "split.sub",
+ "rect": {
+ "x": 0,
+ "y": 962,
+ "w": 1080,
+ "h": 744
+ }
+ },
+ {
+ "name": "software_keyboard",
+ "rect": {
+ "x": 0,
+ "y": 962,
+ "w": 1080,
+ "h": 744
+ }
+ },
+ {
+ "name": "restriction.normal",
+ "rect": {
+ "x": 0,
+ "y": 218,
+ "w": 1080,
+ "h": 1488
+ }
+ },
+ {
+ "name": "restriction.split.main",
+ "rect": {
+ "x": 0,
+ "y": 218,
+ "w": 1080,
+ "h": 744
+ }
+ },
+ {
+ "name": "restriction.split.sub",
+ "rect": {
+ "x": 0,
+ "y": 962,
+ "w": 1080,
+ "h": 744
+ }
+ },
+ {
+ "name": "on_screen",
+ "rect": {
+ "x": 0,
+ "y": 218,
+ "w": 1080,
+ "h": 1488
+ }
+ },
+ {
+ "name": "master.split.sub",
+ "rect": {
+ "x": 0,
+ "y": 180,
+ "w": 640,
+ "h": 720
+ }
+ },
+ {
+ "name": "rse1.normal.full",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 720
+ }
+ },
+ {
+ "name": "rse2.normal.full",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 720
+ }
+ },
+ {
+ "name": "hud.normal.full",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 720
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "rse1",
+ "screens": [
+ {
+ "id": 0,
+ "areas": [
+ {
+ "name": "rse1.normal.full",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 720
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "rse2",
+ "screens": [
+ {
+ "id": 0,
+ "areas": [
+ {
+ "name": "rse2.normal.full",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 720
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "hud",
+ "screens": [
+ {
+ "id": 0,
+ "areas": [
+ {
+ "name": "hud.normal.full",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 1920,
+ "h": 720
+ }
+ },
+ {
+ "name": "hud.upper.left",
+ "rect": {
+ "x": 0,
+ "y": 0,
+ "w": 480,
+ "h": 180
+ }
+ }
+ ]
+ }
+ ]
+ },
+ ]
+}
diff --git a/src/config/connection.json b/src/config/connection.json
new file mode 100644
index 0000000..18dc7ad
--- /dev/null
+++ b/src/config/connection.json
@@ -0,0 +1,48 @@
+{
+ "screen_name": "master",
+ "wm_port": 54400,
+ "areas": [
+ {
+ "area_name": "fullscreen",
+ "transmitter_port": 54401,
+ "width": 1920,
+ "height": 1080
+ }
+ ],
+ "connections": [
+ {
+ "screen_name": "slave",
+ "ip": "192.168.200.101",
+ "wm_port": 54410,
+ "master_mode": false,
+ "areas": [
+ {
+ "area_name": "split.sub",
+ "transmitter_port": 54411,
+ "width": 640,
+ "height": 720
+ }
+ ]
+ },
+ {
+ "screen_name": "hud",
+ "ip": "192.168.200.102",
+ "wm_port": 54420,
+ "master_mode": false,
+ "areas": [
+ {
+ "area_name": "fullscreen",
+ "transmitter_port": 54421,
+ "width": 1920,
+ "height": 1080
+ },
+ {
+ "area_name": "leftup",
+ "transmitter_port": 54422,
+ "width": 640,
+ "height": 720
+ }
+ ]
+ }
+ ]
+}
diff --git a/src/config/old_roles.json b/src/config/old_roles.json
new file mode 100644
index 0000000..02a4c2d
--- /dev/null
+++ b/src/config/old_roles.json
@@ -0,0 +1,68 @@
+{
+ "old_roles": [
+ {
+ "name": "HomeScreen",
+ "new": "homescreen"
+ },
+ {
+ "name": "Music",
+ "new": "music"
+ },
+ {
+ "name": "MediaPlayer",
+ "new": "music"
+ },
+ {
+ "name": "Video",
+ "new": "video"
+ },
+ {
+ "name": "VideoPlayer",
+ "new": "video"
+ },
+ {
+ "name": "WebBrowser",
+ "new": "browser"
+ },
+ {
+ "name": "Radio",
+ "new": "radio"
+ },
+ {
+ "name": "Phone",
+ "new": "phone"
+ },
+ {
+ "name": "Navigation",
+ "new": "map"
+ },
+ {
+ "name": "HVAC",
+ "new": "hvac"
+ },
+ {
+ "name": "Settings",
+ "new": "settings"
+ },
+ {
+ "name": "Dashboard",
+ "new": "dashboard"
+ },
+ {
+ "name": "POI",
+ "new": "poi"
+ },
+ {
+ "name": "Mixer",
+ "new": "mixer"
+ },
+ {
+ "name": "Restriction",
+ "new": "restriction"
+ },
+ {
+ "name": "^OnScreen.*",
+ "new": "on_screen"
+ }
+ ]
+}
diff --git a/src/config/timeout.json b/src/config/timeout.json
new file mode 100644
index 0000000..a3e4419
--- /dev/null
+++ b/src/config/timeout.json
@@ -0,0 +1,4 @@
+{
+ "times": 60000,
+ "sleep": 50
+}
diff --git a/src/config/weston.json b/src/config/weston.json
new file mode 100644
index 0000000..44e379c
--- /dev/null
+++ b/src/config/weston.json
@@ -0,0 +1,4 @@
+{
+ "times": 60000,
+ "sleep": 50
+}
diff --git a/src/json_helper.cpp b/src/json_helper.cpp
index 72ae36a..d9cf5eb 100644
--- a/src/json_helper.cpp
+++ b/src/json_helper.cpp
@@ -69,6 +69,18 @@ int getIntFromJson(json_object *obj, const char *key)
return json_object_get_int(tmp);
}
+double getDoubleFromJson(json_object *obj, const char *key)
+{
+ json_object *tmp;
+ if (!json_object_object_get_ex(obj, key, &tmp))
+ {
+ HMI_DEBUG("Not found key \"%s\"", key);
+ return 0;
+ }
+
+ return json_object_get_double(tmp);
+}
+
json_bool getBoolFromJson(json_object *obj, const char *key)
{
json_object *tmp;
diff --git a/src/json_helper.hpp b/src/json_helper.hpp
index 6ccbcc1..d4ae85a 100644
--- a/src/json_helper.hpp
+++ b/src/json_helper.hpp
@@ -21,12 +21,12 @@
#include <vector>
struct json_object;
-
json_object *to_json(std::vector<uint32_t> const &v);
namespace jh {
const char* getStringFromJson(json_object* obj, const char* key);
int getIntFromJson(json_object *obj, const char *key);
+double getDoubleFromJson(json_object *obj, const char *key);
json_bool getBoolFromJson(json_object *obj, const char *key);
int inputJsonFilie(const char* file, json_object** obj);
} // namespace jh
diff --git a/src/low_can_client.cpp b/src/low_can_client.cpp
new file mode 100644
index 0000000..090aa14
--- /dev/null
+++ b/src/low_can_client.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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 "low_can_client.hpp"
+#include "json_helper.hpp"
+#include "util.hpp"
+
+extern "C"
+{
+#include <afb/afb-binding.h>
+}
+
+namespace wm
+{
+
+LowCanClient::LowCanClient()
+ : vehicle_speed(0),
+ trans_gear_pos(0),
+ headlamp_status(FALSE),
+ parking_brake_status(TRUE),
+ accel_pedal_pos(0),
+ accel_pedal_stt(FALSE),
+ lightstatus_brake_status(TRUE),
+ is_changed_accel_pedal_stt(false)
+{
+}
+
+void LowCanClient::initialize()
+{
+ int ret;
+
+ // Require API "low-can"
+ ret = afb_daemon_require_api_v2("low-can", 1);
+ if (0 > ret)
+ {
+ HMI_INFO("Requirement API \"low-can\" failed");
+ return;
+ }
+
+ // Subscribe low-level-can
+ // low-can subscribe { "event": "vehicle.speed" }
+ // low-can subscribe { "event": "transmission_gear_position" }
+ // low-can subscribe { "event": "headlamp_status" }
+ // low-can subscribe { "event": "parking_brake_status" }
+ // low-can subscribe { "event": "accelerator.pedal.position" }
+ // low-can subscribe { "event": "lightstatus.brake" }
+ for (int i = SignalNoMin; i <= SignalNoMax; i++)
+ {
+ // Set Event
+ json_object *json_obj = json_object_new_object();
+ json_object_object_add(json_obj, "event",
+ json_object_new_string(this->kSignalName[i]));
+
+ // Set filter
+ if (0 != strcmp("", this->kFilterValue[i]))
+ {
+ json_object_object_add(json_obj, "filter",
+ json_tokener_parse(this->kFilterValue[i]));
+ }
+ HMI_DEBUG("subscribe message:%s", json_object_get_string(json_obj));
+
+ // Subscribe
+ afb_service_call("low-can", "subscribe", json_obj,
+ [](void *closure, int status, json_object *result) {
+ HMI_DEBUG("subscribe result:%s", json_object_get_string(result));
+ },
+ nullptr);
+ }
+
+ return;
+}
+
+const char *LowCanClient::analyzeCanSignal(struct json_object *object)
+{
+ HMI_DEBUG("object:%s", json_object_get_string(object));
+
+ const char *name = jh::getStringFromJson(object, "name");
+ HMI_DEBUG("CAN signal name:%s", name);
+
+ if (strstr(name, this->kSignalName[SignalNoVehicliSpeed]))
+ {
+ // Update vehicle speed
+ this->vehicle_speed = jh::getIntFromJson(object, "value");
+ HMI_DEBUG("Update vehicle speed:%d", this->vehicle_speed);
+ }
+ else if (strstr(name, this->kSignalName[SignalNoTransGearPos]))
+ {
+ // Update transmission gear position
+ this->trans_gear_pos = jh::getIntFromJson(object, "value");
+ HMI_DEBUG("Update transmission gear position:%d", this->trans_gear_pos);
+ }
+ else if (strstr(name, this->kSignalName[SignalNoHeadlame]))
+ {
+ // Update headlamp status
+ this->headlamp_status = jh::getBoolFromJson(object, "value");
+ HMI_DEBUG("Update headlamp status:%d", this->headlamp_status);
+ }
+ else if (strstr(name, this->kSignalName[SignalNoParkingBrake]))
+ {
+ // Update parking gear status
+ this->parking_brake_status = jh::getBoolFromJson(object, "value");
+ HMI_DEBUG("Update parking brake status:%d", this->parking_brake_status);
+ }
+ else if (strstr(name, this->kSignalName[SignalNoAccelPedalPos]))
+ {
+ // Clear flag for whether accel pedal state is changed
+ this->is_changed_accel_pedal_stt = false;
+
+ // Update accelerator pedal status
+ this->accel_pedal_pos = jh::getDoubleFromJson(object, "value");
+ HMI_DEBUG("Update accelerator pedal position:%lf", this->accel_pedal_pos);
+
+ bool accel_pedal_stt;
+ if (0 != this->accel_pedal_pos)
+ {
+ accel_pedal_stt = true;
+ }
+ else
+ {
+ accel_pedal_stt = false;
+ }
+
+ if (accel_pedal_stt != this->accel_pedal_stt)
+ {
+ this->is_changed_accel_pedal_stt = true;
+ this->accel_pedal_stt = accel_pedal_stt;
+ }
+ }
+ else if (strstr(name, this->kSignalName[SignalNoLightstatusBrake]))
+ {
+ // Update lightstatus brake status
+ this->lightstatus_brake_status = jh::getBoolFromJson(object, "value");
+ HMI_DEBUG("Update lightstatus brake status:%d", this->lightstatus_brake_status);
+ }
+
+ return name;
+}
+
+bool LowCanClient::isChangedAccelPedalState()
+{
+ return this->is_changed_accel_pedal_stt;
+}
+
+int LowCanClient::getCurrentTransGearState()
+{
+ return this->trans_gear_pos;
+}
+
+bool LowCanClient::getCurrentHeadlampState()
+{
+ return (bool)this->headlamp_status;
+}
+
+bool LowCanClient::getCurrentParkingBrakeState()
+{
+ return (bool)this->parking_brake_status;
+}
+
+double LowCanClient::getCurrentAccelPedalPosition()
+{
+ return this->accel_pedal_pos;
+}
+
+bool LowCanClient::getCurrentAccelPedalState()
+{
+ return this->accel_pedal_stt;
+}
+
+bool LowCanClient::getCurrentLightstatusBrakeState()
+{
+ return (bool)this->lightstatus_brake_status;
+}
+
+} // namespace wm
diff --git a/src/low_can_client.hpp b/src/low_can_client.hpp
new file mode 100644
index 0000000..9b7f509
--- /dev/null
+++ b/src/low_can_client.hpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2017 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 TMCAGLWM_LOW_CAN_CLIENT_HPP
+#define TMCAGLWM_LOW_CAN_CLIENT_HPP
+
+#include <string>
+#include <vector>
+#include <json-c/json.h>
+
+namespace wm
+{
+
+class LowCanClient
+{
+
+ public:
+ explicit LowCanClient();
+ ~LowCanClient() = default;
+
+ enum SignalNo
+ {
+ SignalNoVehicliSpeed = 0,
+ SignalNoTransGearPos,
+ SignalNoHeadlame,
+ SignalNoParkingBrake,
+ SignalNoAccelPedalPos,
+ SignalNoLightstatusBrake,
+
+ SignalNum,
+
+ SignalNoMin = SignalNoVehicliSpeed,
+ SignalNoMax = SignalNum - 1,
+ };
+
+ const std::vector<const char *> kSignalName{
+ "vehicle.speed",
+ "transmission_gear_position",
+ "headlamp_status",
+ "parking_brake_status",
+ "accelerator.pedal.position",
+ "lightstatus.brake",
+ };
+
+ void initialize();
+ const char *analyzeCanSignal(struct json_object *object);
+
+ int getCurrentTransGearState();
+ bool getCurrentHeadlampState();
+ bool getCurrentParkingBrakeState();
+ double getCurrentAccelPedalPosition();
+ bool getCurrentAccelPedalState();
+ bool getCurrentLightstatusBrakeState();
+
+ bool isChangedAccelPedalState();
+
+ private:
+ // Disable copy and move
+ LowCanClient(LowCanClient const &) = delete;
+ LowCanClient &operator=(LowCanClient const &) = delete;
+ LowCanClient(LowCanClient &&) = delete;
+ LowCanClient &operator=(LowCanClient &&) = delete;
+
+ enum TransGearPosVal
+ {
+ TransGearPosValD1 = 1,
+ TransGearPosValD2,
+ TransGearPosValD3,
+ TransGearPosValD4,
+ TransGearPosValD5,
+ TransGearPosValD6,
+ TransGearPosValD7,
+ TransGearPosValD8,
+ TransGearPosValR,
+ TransGearPosValN,
+ };
+
+ const std::vector<const char *> kFilterValue{
+ "", // vehicle.speed
+ "", // transmission_gear_position
+ "", // headlamp_status
+ "", // parking_brake_status
+ "", // accelerator.pedal.position
+ "", // lightstatus.brake
+ };
+
+ int vehicle_speed;
+ int trans_gear_pos;
+ json_bool headlamp_status;
+ json_bool parking_brake_status;
+ double accel_pedal_pos;
+ bool accel_pedal_stt;
+ json_bool lightstatus_brake_status;
+
+ bool is_changed_accel_pedal_stt;
+};
+
+} // namespace wm
+
+#endif // TMCAGLWM_LOW_CAN_CLIENT_HPP
diff --git a/src/main.cpp b/src/main.cpp
index 6483655..6fff161 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -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"
@@ -56,7 +59,7 @@ int afb_instance::init()
return this->wmgr.init();
}
-static int _binding_init()
+int _binding_init()
{
HMI_NOTICE("WinMan ver. %s", WINMAN_VERSION_STRING);
@@ -78,7 +81,7 @@ error:
return -1;
}
-static int binding_init (afb_api_t api) noexcept
+int binding_init() noexcept
{
try
{
@@ -110,20 +113,21 @@ static void cbRemoveClientCtxt(void *data)
delete ctxt;
}
-static void createSecurityContext(afb_req_t req, const char* appid, const char* role)
+static void createSecurityContext(afb_req req, const char* appid, const char* role)
{
WMClientCtxt *ctxt = (WMClientCtxt *)afb_req_context_get(req);
if (!ctxt)
{
// Create Security Context at first time
- WMClientCtxt *ctxt = new WMClientCtxt(appid, role);
+ const char *new_role = g_afb_instance->wmgr.convertRoleOldToNew(role);
+ WMClientCtxt *ctxt = new WMClientCtxt(appid, new_role);
HMI_DEBUG("create session for %s", ctxt->name.c_str());
afb_req_session_set_LOA(req, 1);
afb_req_context_set(req, ctxt, cbRemoveClientCtxt);
}
}
-void windowmanager_requestsurface(afb_req_t req) noexcept
+void windowmanager_requestsurface(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -169,7 +173,7 @@ void windowmanager_requestsurface(afb_req_t req) noexcept
}
}
-void windowmanager_requestsurfacexdg(afb_req_t req) noexcept
+void windowmanager_requestsurfacexdg(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -222,7 +226,50 @@ void windowmanager_requestsurfacexdg(afb_req_t req) noexcept
}
}
-void windowmanager_activatewindow(afb_req_t 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);
if (g_afb_instance == nullptr)
@@ -250,17 +297,40 @@ void windowmanager_activatewindow(afb_req_t 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");
+ };
+
+ 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);
+ }
+ }
free(appid);
}
}
@@ -272,7 +342,7 @@ void windowmanager_activatewindow(afb_req_t req) noexcept
}
}
-void windowmanager_deactivatewindow(afb_req_t req) noexcept
+void windowmanager_deactivatewindow(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -293,17 +363,30 @@ void windowmanager_deactivatewindow(afb_req_t 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);
}
}
@@ -315,7 +398,7 @@ void windowmanager_deactivatewindow(afb_req_t req) noexcept
}
}
-void windowmanager_enddraw(afb_req_t req) noexcept
+void windowmanager_enddraw(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -337,8 +420,18 @@ void windowmanager_enddraw(afb_req_t req) noexcept
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.getAppIdToEcuName(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)
@@ -349,7 +442,7 @@ void windowmanager_enddraw(afb_req_t req) noexcept
}
}
-void windowmanager_getdisplayinfo_thunk(afb_req_t req) noexcept
+void windowmanager_getdisplayinfo_thunk(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -376,7 +469,7 @@ void windowmanager_getdisplayinfo_thunk(afb_req_t req) noexcept
}
}
-void windowmanager_getareainfo_thunk(afb_req_t req) noexcept
+void windowmanager_getareainfo_thunk(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -413,14 +506,132 @@ void windowmanager_getareainfo_thunk(afb_req_t req) noexcept
}
}
-void windowmanager_get_area_list(afb_req_t 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_t req) noexcept
+void windowmanager_change_area_size(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -480,7 +691,7 @@ void windowmanager_change_area_size(afb_req_t req) noexcept
}
}
-void windowmanager_wm_subscribe(afb_req_t req) noexcept
+void windowmanager_wm_subscribe(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -498,15 +709,20 @@ void windowmanager_wm_subscribe(afb_req_t req) noexcept
afb_req_fail(req, "failed", "Need char const* argument event");
return;
}
- wm::WindowManager::EventType event_id = (wm::WindowManager::EventType)json_object_get_int(j);
- bool ret = g_afb_instance->wmgr.api_subscribe(req, event_id);
+ int event_id = json_object_get_int(j);
+ int ret = g_afb_instance->wmgr.api_subscribe(req, event_id);
- if (!ret)
+ if (ret)
{
afb_req_fail(req, "failed", "Error: afb_req_subscribe()");
return;
}
afb_req_success(req, NULL, "success");
+
+ if (event_id == g_afb_instance->wmgr.Event_Handshake)
+ {
+ g_afb_instance->wmgr.api_handshake();
+ }
}
catch (std::exception &e)
{
@@ -515,7 +731,24 @@ void windowmanager_wm_subscribe(afb_req_t req) noexcept
}
}
-void windowmanager_ping(afb_req_t 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);
@@ -530,7 +763,7 @@ void windowmanager_ping(afb_req_t req) noexcept
}
}
-void windowmanager_debug_terminate(afb_req_t req) noexcept
+void windowmanager_debug_terminate(afb_req req) noexcept
{
std::lock_guard<std::mutex> guard(binding_m);
if (g_afb_instance == nullptr)
@@ -557,32 +790,30 @@ void windowmanager_debug_terminate(afb_req_t req) noexcept
}
}
-const afb_verb_t windowmanager_verbs[] = {
- { .verb = "requestSurface", .callback = windowmanager_requestsurface },
- { .verb = "requestSurfaceXDG", .callback = windowmanager_requestsurfacexdg },
- { .verb = "activateWindow", .callback = windowmanager_activatewindow },
- { .verb = "deactivateWindow", .callback = windowmanager_deactivatewindow },
- { .verb = "endDraw", .callback = windowmanager_enddraw },
- { .verb = "getDisplayInfo", .callback = windowmanager_getdisplayinfo_thunk },
- { .verb = "getAreaInfo", .callback = windowmanager_getareainfo_thunk },
- { .verb = "changeAreaSize", .callback = windowmanager_change_area_size },
- { .verb = "getAreaList", .callback = windowmanager_get_area_list },
- { .verb = "wm_subscribe", .callback = windowmanager_wm_subscribe },
- { .verb = "ping", .callback = windowmanager_ping },
- { .verb = "debug_terminate", .callback = windowmanager_debug_terminate },
- {} };
-
-extern "C" const afb_binding_t afbBindingExport = {
- .api = "windowmanager",
- .specification = "windowmanager",
- .info = "windowmanager",
- .verbs = windowmanager_verbs,
- .preinit = nullptr,
- .init = binding_init,
- .onevent = nullptr,
- .userdata = nullptr,
- .provide_class = nullptr,
- .require_class = nullptr,
- .require_api = nullptr,
- .noconcurrency = 0
-};
+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},
+ {"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, on_event, 0};
diff --git a/src/pm_wrapper.cpp b/src/pm_wrapper.cpp
index 8706128..7cf90f0 100644
--- a/src/pm_wrapper.cpp
+++ b/src/pm_wrapper.cpp
@@ -43,14 +43,14 @@ static void onError(json_object *json_out)
PMWrapper::PMWrapper() {}
-int PMWrapper::initialize()
+int PMWrapper::initialize(std::string ecu_name)
{
int ret = 0;
- ret = this->pm.initialize();
+ ret = this->pm.initialize(ecu_name);
if (0 > ret)
{
- HMI_ERROR("Faild to initialize PolicyManager");
+ HMI_ERROR("wm:pmw", "Faild to initialize PolicyManager");
}
g_context = this;
@@ -81,7 +81,39 @@ int PMWrapper::setInputEventData(Task task, std::string role, std::string area)
{
event = "deactivate";
}
- else
+ else if (Task::TASK_PARKING_BRAKE_OFF == task)
+ {
+ event = "parking_brake_off";
+ }
+ else if (Task::TASK_PARKING_BRAKE_ON == task)
+ {
+ event = "parking_brake_on";
+ }
+ else if (Task::TASK_ACCEL_PEDAL_OFF == task)
+ {
+ event = "accel_pedal_off";
+ }
+ else if (Task::TASK_ACCEL_PEDAL_ON == task)
+ {
+ event = "accel_pedal_on";
+ }
+ else if (Task::TASK_HEDLAMP_OFF == task)
+ {
+ event = "headlamp_off";
+ }
+ else if (Task::TASK_HEDLAMP_ON == task)
+ {
+ event = "headlamp_on";
+ }
+ else if (Task::TASK_LIGHTSTATUS_BRAKE_OFF == task)
+ {
+ event = "lightstatus_brake_off";
+ }
+ else if (Task::TASK_LIGHTSTATUS_BRAKE_ON == task)
+ {
+ event = "lightstatus_brake_on";
+ }
+ else
{
event = "";
}
@@ -95,7 +127,7 @@ int PMWrapper::setInputEventData(Task task, std::string role, std::string area)
ret = this->pm.setInputEventData(json_in);
if (0 > ret)
{
- HMI_ERROR("Faild to set input event data to PolicyManager");
+ HMI_ERROR("wm:pmw", "Faild to set input event data to PolicyManager");
}
json_object_put(json_in);
@@ -108,7 +140,7 @@ int PMWrapper::executeStateTransition()
ret = this->pm.executeStateTransition();
if (0 > ret)
{
- HMI_ERROR("Failed to execute state transition for PolicyManager");
+ HMI_ERROR("wm:pmw", "Failed to execute state transition for PolicyManager");
}
return ret;
@@ -127,11 +159,151 @@ void PMWrapper::updateStates(json_object *json_out)
HMI_DEBUG("json_out dump:%s", json_object_get_string(json_out));
+ this->createCarStateChangeAction(json_out, actions);
this->createLayoutChangeAction(json_out, actions);
this->on_state_transitioned(actions);
}
+void PMWrapper::createCarStateChangeAction(json_object *json_out, std::vector<WMAction> &actions)
+{
+ json_object *json_car_ele;
+ if (!json_object_object_get_ex(json_out, "car_elements", &json_car_ele))
+ {
+ HMI_DEBUG("Not found key \"car_elements\"");
+ return;
+ }
+
+ int len = json_object_array_length(json_car_ele);
+ HMI_DEBUG("json_car_ele len:%d", len);
+
+ for (int i = 0; i < len; i++)
+ {
+ json_object *json_tmp = json_object_array_get_idx(json_car_ele, i);
+
+ std::string car_ele_name = jh::getStringFromJson(json_tmp, "name");
+ std::string state = jh::getStringFromJson(json_tmp, "state");
+ json_bool changed = jh::getBoolFromJson(json_tmp, "changed");
+ HMI_DEBUG("car_element:%s changed:%d", car_ele_name.c_str(), changed);
+
+ if (changed)
+ {
+ TaskCarState task = TaskCarState::NO_TASK;
+ if ("parking_brake" == car_ele_name)
+ {
+ if ("off" == state)
+ {
+ task = TaskCarState::PARKING_BRAKE_OFF;
+ }
+ else if ("on" == state)
+ {
+ task = TaskCarState::PARKING_BRAKE_ON;
+ }
+ else
+ {
+ HMI_DEBUG("Unknown parking brake state: %s", state.c_str());
+ }
+ }
+ else if ("accel_pedal" == car_ele_name)
+ {
+ if ("off" == state)
+ {
+ task = TaskCarState::ACCEL_PEDAL_OFF;
+ }
+ else if ("on" == state)
+ {
+ task = TaskCarState::ACCEL_PEDAL_ON;
+ }
+ else
+ {
+ HMI_DEBUG("Unknown accel pedal state: %s", state.c_str());
+ }
+ }
+ else if ("lamp" == car_ele_name)
+ {
+ if ("off" == state)
+ {
+ task = TaskCarState::HEDLAMP_OFF;
+ }
+ else if ("on" == state)
+ {
+ task = TaskCarState::HEDLAMP_ON;
+ }
+ else
+ {
+ HMI_DEBUG("Unknown lamp state: %s", state.c_str());
+ }
+ }
+ else if ("lightstatus_brake" == car_ele_name)
+ {
+ if ("off" == state)
+ {
+ task = TaskCarState::LIGHTSTATUS_BRAKE_OFF;
+ }
+ else if ("on" == state)
+ {
+ task = TaskCarState::LIGHTSTATUS_BRAKE_ON;
+ }
+ else
+ {
+ HMI_DEBUG("Unknown lightstatus brake state: %s", state.c_str());
+ }
+ }
+ else if ("running" == car_ele_name)
+ {
+ if ("stop" == state)
+ {
+ task = TaskCarState::CAR_STOP;
+ }
+ else if ("run" == state)
+ {
+ task = TaskCarState::CAR_RUN;
+ }
+ else
+ {
+ HMI_DEBUG("Unknown car state: %s", state.c_str());
+ }
+ }
+ else if ("restriction_mode" == car_ele_name)
+ {
+ if ("off" == state)
+ {
+ task = TaskCarState::RESTRICTION_MODE_OFF;
+ }
+ else if ("on" == state)
+ {
+ task = TaskCarState::RESTRICTION_MODE_ON;
+ }
+ else
+ {
+ HMI_DEBUG("Unknown car state: %s", state.c_str());
+ }
+ }
+ else
+ {
+ HMI_DEBUG("Unknown car element: %s", car_ele_name.c_str());
+ }
+
+ // Set action
+ if (TaskCarState::NO_TASK != task)
+ {
+ bool end_draw_finished = true;
+ WMAction act
+ {
+ 0,
+ nullptr,
+ "",
+ "",
+ TaskVisible::NO_CHANGE,
+ end_draw_finished,
+ task
+ };
+ actions.push_back(act);
+ }
+ }
+ }
+}
+
void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAction> &actions)
{
// Get displayed roles from previous layout
@@ -197,7 +369,8 @@ void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAc
role_name,
area_name,
TaskVisible::VISIBLE,
- end_draw_finished
+ end_draw_finished,
+ TaskCarState::NO_TASK
};
actions.push_back(act);
}
@@ -220,7 +393,8 @@ void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAc
role_name,
area_name,
TaskVisible::VISIBLE,
- end_draw_finished
+ end_draw_finished,
+ TaskCarState::NO_TASK
};
actions.push_back(act);
}
@@ -245,7 +419,8 @@ void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAc
i_prv.first,
"",
TaskVisible::INVISIBLE,
- end_draw_finished
+ end_draw_finished,
+ TaskCarState::NO_TASK
};
actions.push_back(act);
}
diff --git a/src/pm_wrapper.hpp b/src/pm_wrapper.hpp
index 31ec002..84d68df 100644
--- a/src/pm_wrapper.hpp
+++ b/src/pm_wrapper.hpp
@@ -41,7 +41,7 @@ class PMWrapper
using StateTransitionHandler = std::function<void(std::vector<WMAction>)>;
using ErrorHandler = std::function<void(void)>;
- int initialize();
+ int initialize(std::string ecu_name);
void registerCallback(StateTransitionHandler on_state_transitioned,
ErrorHandler on_error);
int setInputEventData(Task task, std::string role, std::string area);
@@ -67,6 +67,7 @@ class PMWrapper
std::map<std::string, RoleState> prvlayer2rolestate;
std::map<std::string, RoleState> crrlayer2rolestate;
+ void createCarStateChangeAction(json_object *json_out, std::vector<WMAction> &actions);
void createLayoutChangeAction(json_object *json_out, std::vector<WMAction> &actions);
};
diff --git a/src/request.cpp b/src/request.cpp
index 069f8ff..0d8e5d4 100644
--- a/src/request.cpp
+++ b/src/request.cpp
@@ -30,6 +30,13 @@ WMRequest::WMRequest(string appid, string role, string area, Task task)
{
}
+WMRequest::WMRequest(Task task)
+ : req_num(0),
+ trigger{"", "", "", task},
+ sync_draw_req(0)
+{
+}
+
WMRequest::~WMRequest()
{
}
@@ -41,4 +48,4 @@ WMRequest::WMRequest(const WMRequest &obj)
this->sync_draw_req = obj.sync_draw_req;
}
-} // namespace wm \ No newline at end of file
+} // namespace wm
diff --git a/src/request.hpp b/src/request.hpp
index 0f0e199..9827627 100644
--- a/src/request.hpp
+++ b/src/request.hpp
@@ -31,6 +31,16 @@ enum Task
TASK_ALLOCATE,
TASK_RELEASE,
TASK_CHANGE_AREA,
+ TASK_PARKING_BRAKE_OFF,
+ TASK_PARKING_BRAKE_ON,
+ TASK_ACCEL_PEDAL_OFF,
+ TASK_ACCEL_PEDAL_ON,
+ TASK_HEDLAMP_OFF,
+ TASK_HEDLAMP_ON,
+ TASK_LIGHTSTATUS_BRAKE_OFF,
+ TASK_LIGHTSTATUS_BRAKE_ON,
+ TASK_RESTRICTION_MODE_OFF,
+ TASK_RESTRICTION_MODE_ON,
TASK_INVALID
};
@@ -38,9 +48,30 @@ enum TaskVisible
{
VISIBLE,
INVISIBLE,
+ REQ_REMOTE_VISIBLE,
+ REQ_REMOTE_INVISIBLE,
+ REMOTE_VISIBLE,
+ REMOTE_INVISIBLE,
NO_CHANGE
};
+enum TaskCarState
+{
+ PARKING_BRAKE_OFF,
+ PARKING_BRAKE_ON,
+ ACCEL_PEDAL_OFF,
+ ACCEL_PEDAL_ON,
+ HEDLAMP_OFF,
+ HEDLAMP_ON,
+ LIGHTSTATUS_BRAKE_OFF,
+ LIGHTSTATUS_BRAKE_ON,
+ CAR_STOP,
+ CAR_RUN,
+ RESTRICTION_MODE_OFF,
+ RESTRICTION_MODE_ON,
+ NO_TASK,
+};
+
struct WMTrigger
{
std::string appid;
@@ -57,6 +88,7 @@ struct WMAction
std::string area;
TaskVisible visible;
bool end_draw_finished;
+ TaskCarState car_state;
};
struct WMRequest
@@ -64,6 +96,7 @@ struct WMRequest
WMRequest();
explicit WMRequest(std::string appid, std::string role,
std::string area, Task task);
+ explicit WMRequest(Task task);
virtual ~WMRequest();
WMRequest(const WMRequest &obj);
@@ -74,4 +107,4 @@ struct WMRequest
} // namespace wm
-#endif //WMREQUEST_HPP \ No newline at end of file
+#endif //WMREQUEST_HPP
diff --git a/src/util.cpp b/src/util.cpp
index 0591d55..7d000b8 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -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.
@@ -17,11 +16,11 @@
#include "util.hpp"
+#include <sstream>
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
-#include <fstream>
#include <unistd.h>
@@ -31,7 +30,7 @@ void rectangle::fit(unsigned long to_width, unsigned long to_height)
{
// fit rect within (to_width x to_height)
- if (to_width <= (unsigned long)width()) {
+ if (to_width <= width()) {
// scale to fit with
set_bottom(top() + (static_cast<long>(to_width) * height() / width()) - 1);
set_right(left() + to_width - 1);
@@ -143,38 +142,32 @@ void _DUMP(enum LOG_LEVEL level, const char *log, ...)
free(message);
}
-std::string get_file_path(const char *file_name, const char *root_path)
+std::vector<std::string> parseString(std::string str, char delimiter)
{
- char const *default_base_path = root_path;
- std::string path("");
-
- if(!file_name) {
- return path;
- }
-
- if (!default_base_path) {
- default_base_path = getenv("AFM_APP_INSTALL_DIR");
- if (!default_base_path) {
- HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
+ // Parse string by delimiter
+ std::vector<std::string> vct;
+ std::stringstream ss{str};
+ std::string buf;
+ while (std::getline(ss, buf, delimiter))
+ {
+ if (!buf.empty())
+ {
+ // Delete space and push back to vector
+ vct.push_back(deleteSpace(buf));
}
}
- if (default_base_path) {
- path = default_base_path;
- path.append("/etc/");
- path.append(file_name);
- }
+ return vct;
+}
- // Check for over-ride in /etc/xdg/windowmanager
- std::string override_path("/etc/xdg/windowmanager/");
- override_path.append(file_name);
- std::ifstream i(override_path);
- if (i.good()) {
- path = override_path;
+std::string deleteSpace(std::string str)
+{
+ std::string ret = str;
+ size_t pos;
+ while ((pos = ret.find_first_of(" ")) != std::string::npos)
+ {
+ ret.erase(pos, 1);
}
- i.close();
-
- HMI_INFO("Using %s", path.c_str());
- return path;
+ return ret;
}
void ChangeAreaReq::dump()
@@ -192,4 +185,4 @@ void ChangeAreaReq::dump()
DUMP("update change app : %s, area:%s", req.first.c_str(), req.second.c_str());
}
DUMP("======== dump end =========");
-}
+} \ No newline at end of file
diff --git a/src/util.hpp b/src/util.hpp
index 9540772..4c3870f 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -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.
@@ -20,6 +19,8 @@
#include <functional>
#include <thread>
+#include <string>
+#include <vector>
#include <unordered_map>
#include <sys/poll.h>
#include <string.h>
@@ -54,6 +55,9 @@ void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, const in
void _HMI_SEQ_LOG(enum LOG_LEVEL level, const char* file, const char* func, const int line, unsigned seq_num, const char* log, ...);
void _DUMP(enum LOG_LEVEL level, const char *log, ...);
+std::vector<std::string> parseString(std::string str, char delimiter);
+std::string deleteSpace(std::string str);
+
struct rect
{
int32_t w, h;
@@ -119,9 +123,6 @@ class rectangle
long _bottom;
};
-// Configuration file path helper
-std::string get_file_path(const char *file_name, const char *root_path = NULL);
-
typedef struct ChangeAreaReq {
std::string appname;
std::unordered_map<std::string, struct rect> area_req;
@@ -132,5 +133,4 @@ typedef struct ChangeAreaReq {
ChangeAreaReq(const ChangeAreaReq& val) = default;
void dump();
} ChangeAreaReq;
-
-#endif // WM_UTIL_HPP
+#endif // !WM_UTIL_HPP
diff --git a/src/window_manager.cpp b/src/window_manager.cpp
index f9070f6..1432769 100644
--- a/src/window_manager.cpp
+++ b/src/window_manager.cpp
@@ -26,6 +26,8 @@ extern "C"
#include <systemd/sd-event.h>
}
+#define WM_LASTMODE_PATH "/etc/lastmode.json"
+
using std::string;
using std::vector;
using std::unordered_map;
@@ -65,13 +67,33 @@ static const vector<string> kListEventName{
"syncDraw",
"flushDraw",
"screenUpdated",
+ "handshake",
+ "headlampOff",
+ "headlampOn",
+ "parkingBrakeOff",
+ "parkingBrakeOn",
+ "lightstatusBrakeOff",
+ "lightstatusBrakeOn",
+ "carStop",
+ "carRun",
"error"};
+static const char kPathOldRolesConfigFile[] = "/etc/old_roles.json";
static sd_event_source *g_timer_ev_src = nullptr;
static AppList g_app_list;
static WindowManager *g_context;
static vector<string> white_list_area_size_change = {
- "homescreen", "settings"
+ "homescreen"
+};
+
+struct AfbClosure {
+public:
+ AfbClosure(unsigned pid, unsigned ppid, unsigned surface)
+ : pid(pid), ppid(ppid), surface(surface) {}
+ ~AfbClosure() = default;
+ unsigned pid;
+ unsigned ppid;
+ unsigned surface;
};
namespace
@@ -93,14 +115,22 @@ static void onError()
{
g_context->processError(WMError::LAYOUT_CHANGE_FAIL);
}
+
+static void onReceiveRemoteRequest(json_object *data)
+{
+ g_context->processForRemoteRequest(data);
+}
} // namespace
/**
* WindowManager Impl
*/
WindowManager::WindowManager()
- : id_alloc{}
+ : wmcon{},
+ id_alloc{}
{
+ this->end_init = false;
+
const char *path = getenv("AFM_APP_INSTALL_DIR");
if (!path)
{
@@ -108,39 +138,61 @@ WindowManager::WindowManager()
}
string root = path;
- this->lc = std::make_shared<LayerControl>(root);
+ // TODO: ECU name should be decide by config file
+ // Get mode and decide ECU name
+ string ecu_name = this->wmcon.getEcuName();
+
+ this->lc = std::make_shared<LayerControl>(root, ecu_name);
HMI_DEBUG("Layer Controller initialized");
}
int WindowManager::init()
{
+ WMError err;
+
LayerControlCallbacks lmcb;
lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){
- this->surface_created(surface);
+ this->surface_created(pid, surface);
};
lmcb.surfaceDestroyed = [&](unsigned surface){
this->surface_removed(surface);
};
- if(this->lc->init(lmcb) != WMError::SUCCESS)
+ err = this->lc->init(lmcb);
+ if (err == WMError::FAIL)
{
+ HMI_ERROR("Could not connect to weston");
return -1;
}
+ // TODO: application requests by old role,
+ // so create role map (old, new)
+ // Load old_roles config file
+ this->loadOldRolesConfigFile();
+
+ // Initialize LowCanClient
+ this->lcc.initialize();
+
// Store my context for calling callback from PolicyManager
g_context = this;
// Initialize PMWrapper
- this->pmw.initialize();
+ this->pmw.initialize(this->wmcon.getEcuName());
// Register callback to PolicyManager
this->pmw.registerCallback(onStateTransitioned, onError);
- // Make afb event for subscriber
- for (int i = Event_ScreenUpdated; i < Event_Error; i++)
+ // Initialize WMConnection
+ this->wmcon.initialize();
+
+ // Register callback to WMConnection
+ this->wmcon.registerCallback(onReceiveRemoteRequest);
+
+ // Make afb event
+ for (int i = Event_Val_Min; i <= Event_Val_Max; i++)
{
- map_afb_event[kListEventName[i]] = afb_api_make_event(afbBindingV3root, kListEventName[i].c_str());
+ map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i].c_str());
}
const struct rect css_bg = this->lc->getAreaSize("fullscreen");
@@ -156,47 +208,65 @@ int WindowManager::init()
double scale = static_cast<double>(dp_bg.height()) / css_bg.h;
this->lc->setupArea(dp_bg, scale);
- return 0;
+ this->end_init = true;
+
+ return 0; //init_layers();
}
result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name)
{
- string str_id = appid;
- string role = drawing_name;
- unsigned lid = 0;
-
- if(!g_app_list.contains(str_id))
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *role = this->convertRoleOldToNew(drawing_name);
+ string l_name;
+ string s_appid = appid;
+ string s_role = role;
+
+ if(!g_app_list.contains(s_appid))
{
- lid = this->generateLayerForClient(role);
- if (lid == 0)
+ unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
+ if (l_id == 0)
{
- return Err<int>("Designated role does not match any role, fallback is disabled");
+ // register drawing_name as fallback and make it displayed.
+ l_id = this->lc->getNewLayerID("fallback", &l_name);
+ HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
+ if (l_id == 0)
+ {
+ return Err<int>("Designated role does not match any role, fallback is disabled");
+ }
}
- // add client into the db
- g_app_list.addClient(str_id, lid, role);
- }
- else
- {
- // This case occurs when an client calls "subscribe" before request_surface.
- // Then application doesn't have layer and role yet.
- auto client = g_app_list.lookUpClient(str_id);
- if(client->layerID() == 0)
+
+ // TODO: remote layer size is fixed value
+ if ("Remote" == l_name)
+ {
+ this->lc->createNewRemoteLayer(l_id);
+ }
+ else
{
- client->setLayerID(this->generateLayerForClient(role));
+ this->lc->createNewLayer(l_id);
}
- client->setRole(role);
+
+ // add client into the db
+ g_app_list.addClient(s_appid, l_id, s_role);
}
// generate surface ID for ivi-shell application
- auto rname = this->id_alloc.lookup(role);
+
+ auto rname = this->id_alloc.lookup(string(role));
if (!rname)
{
// name does not exist yet, allocate surface id...
auto id = int(this->id_alloc.generate_id(role));
- this->tmp_surface2app[id] = {str_id, lid};
+ this->tmp_surface2app[id] = {s_appid, 0};
+
+ // Work Around
+ HMI_NOTICE("WORK AROUND: add surface on request surface");
+ auto client = g_app_list.lookUpClient(s_appid);
+ client->addSurface(id);
+ ///////////////
- auto client = g_app_list.lookUpClient(str_id);
- client->registerSurface(id);
+ // Set role map of (new, old)
+ this->rolenew2old[role] = string(drawing_name);
return Ok<int>(id);
}
@@ -208,10 +278,8 @@ result<int> WindowManager::api_request_surface(char const *appid, char const *dr
char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name,
char const *ivi_id)
{
- string str_id = appid;
- string role = drawing_name;
-
unsigned sid = std::stol(ivi_id);
+
HMI_DEBUG("This API(requestSurfaceXDG) is for XDG Application using runXDG");
/*
* IVI-shell doesn't send surface_size event via ivi-wm protocol
@@ -226,30 +294,45 @@ char const *WindowManager::api_request_surface(char const *appid, char const *dr
return "fail";
}
- if(!g_app_list.contains(str_id))
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *role = this->convertRoleOldToNew(drawing_name);
+ string s_role = role;
+ string s_appid = appid;
+ string l_name;
+
+ if(!g_app_list.contains(s_appid))
{
- unsigned l_id = this->generateLayerForClient(role);
+ // auto lid = this->layers.get_layer_id(string(role));
+ unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
if (l_id == 0)
{
- return "Designated role does not match any role, fallback is disabled";
+ /**
+ * register drawing_name as fallback and make it displayed.
+ */
+ l_id = this->lc->getNewLayerID("fallback", &l_name);
+ HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
+ if (l_id == 0)
+ {
+ return "Designated role does not match any role, fallback is disabled";
+ }
}
- // add client into the db
- g_app_list.addClient(str_id, l_id, role);
- }
- else
- {
- // This case occurs when an client calls "subscribe" before request_surface.
- // Then application doesn't have layer and role yet.
- auto client = g_app_list.lookUpClient(str_id);
- if(client->layerID() == 0)
+
+ // TODO: remote layer size is fixed value
+ if ("Remote" == l_name)
{
- client->setLayerID(this->generateLayerForClient(role));
+ this->lc->createNewRemoteLayer(l_id);
+ }
+ else
+ {
+ this->lc->createNewLayer(l_id);
}
- client->setRole(role);
- }
- auto rname = this->id_alloc.lookup(role);
+ // add client into the db
+ g_app_list.addClient(s_appid, l_id, s_role);
+ }
+ auto rname = this->id_alloc.lookup(s_role);
if (rname)
{
return "Surface already present";
@@ -258,17 +341,121 @@ char const *WindowManager::api_request_surface(char const *appid, char const *dr
// register pair drawing_name and ivi_id
this->id_alloc.register_name_id(role, sid);
- auto client = g_app_list.lookUpClient(str_id);
+ auto client = g_app_list.lookUpClient(s_appid);
client->addSurface(sid);
+ // Set role map of (new, old)
+ this->rolenew2old[role] = string(drawing_name);
+
return nullptr;
}
+bool WindowManager::api_set_role(char const *appid, char const *drawing_name)
+{
+ bool ret = false;
+
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *role = this->convertRoleOldToNew(drawing_name);
+ string s_role = role;
+ string s_appid = appid;
+ string l_name;
+
+ // Create WMClient
+ if(!g_app_list.contains(s_appid))
+ {
+ // auto lid = this->layers.get_layer_id(string(role));
+ unsigned l_id = this->lc->getNewLayerID(s_role, &l_name);
+ if (l_id == 0)
+ {
+ /**
+ * register drawing_name as fallback and make it displayed.
+ */
+ l_id = this->lc->getNewLayerID("fallback", &l_name);
+ HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role);
+ if (l_id == 0)
+ {
+ HMI_ERROR("Designated role does not match any role, fallback is disabled");
+ return ret;
+ }
+ }
+
+ // TODO: remote layer size is fixed value
+ if ("Remote" == l_name)
+ {
+ this->lc->createNewRemoteLayer(l_id);
+ }
+ else
+ {
+ this->lc->createNewLayer(l_id);
+ }
+
+ // add client into the db
+ g_app_list.addClient(s_appid, l_id, s_role);
+ // Set role map of (new, old)
+ this->rolenew2old[role] = string(drawing_name);
+ }
+
+ // for(auto itr = this->tmp_surface2app.begin();
+ // itr != this->tmp_surface2app.end() ; ++itr)
+ // {
+ for(auto& x : this->tmp_surface2app)
+ {
+ if(x.second.appid == s_appid)
+ {
+ unsigned surface = x.first;
+ auto client = g_app_list.lookUpClient(s_appid);
+ client->addSurface(surface);
+ this->tmp_surface2app.erase(surface);
+ this->id_alloc.register_name_id(s_role, surface);
+ break;
+ }
+ }
+
+/* if(0 != pid){
+ // search floating surfaceID from pid if pid is designated.
+ wm_err = g_app_list.popFloatingSurface(pid, &surface);
+ }
+ else{
+ // get floating surface with appid. If WM queries appid from pid,
+ // WM can bind surface and role with appid(not implemented yet)
+ //wm_err = g_app_list.popFloatingSurface(id);
+ }
+ if(wm_err != WMError::SUCCESS){
+ HMI_ERROR("No floating surface for app: %s", id.c_str());
+ g_app_list.addFloatingClient(id, lid, role);
+ HMI_NOTICE("%s : Waiting for surface creation", id.c_str());
+ return ret;
+ }
+
+ ret = true;
+ if (g_app_list.contains(id))
+ {
+ HMI_INFO("Add role: %s with surface: %d. Client %s has multi surfaces.",
+ role.c_str(), surface, id.c_str());
+ auto client = g_app_list.lookUpClient(id);
+ client->appendRole(role);
+ }
+ else{
+ HMI_INFO("Create new client: %s, surface: %d into layer: %d with role: %s",
+ id.c_str(), surface, lid, role.c_str());
+ g_app_list.addClient(id, lid, role);
+ } */
+
+ // register pair drawing_name and ivi_id
+
+ return true;
+}
+
void WindowManager::api_activate_window(char const *appid, char const *drawing_name,
char const *drawing_area, const reply_func &reply)
{
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
string id = appid;
- string role = drawing_name;
+ string role = c_role;
string area = drawing_area;
if(!g_app_list.contains(id))
@@ -278,12 +465,51 @@ void WindowManager::api_activate_window(char const *appid, char const *drawing_n
}
auto client = g_app_list.lookUpClient(id);
+ // unsigned srfc = client->surfaceID(role);
+ // unsigned layer = client->layerID();
+
+ // g_app_list.removeFloatingSurface(client->surfaceID());
+ // g_app_list.removeFloatingSurface(client);i
+ unsigned layer = client->layerID();
+
+ //TODO Deactivate remote viewing app for remote view change to local view.
+ if(this->lc->hasRemoteLayer(layer) && this->wmcon.getAppIdToEcuName(appid) != "")
+ {
+ HMI_DEBUG("Deactivate remote App %s", drawing_name);
+ std::string tmp_area = this->wmcon.getAppIdToEcuName(appid) + ".split.sub";
+ HMI_DEBUG("Deactivate area name: %s", tmp_area.c_str());
+ this->wmcon.sendRequest("deactivateWindow", appid, drawing_name, tmp_area.c_str());
+
+ unsigned req_num = g_app_list.currentRequestNumber();
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+ bool end_draw_finished = true;
+ WMAction act
+ {
+ req_num,
+ client,
+ string(c_role),
+ "",
+ TaskVisible::REMOTE_INVISIBLE,
+ end_draw_finished,
+ TaskCarState::NO_TASK
+ };
+
+ this->lc->visibilityChange(act);
+ this->lc->renderLayers();
+
+ this->emit_invisible(role);
+ this->emit_deactivated(role);
+ }
+
Task task = Task::TASK_ALLOCATE;
unsigned req_num = 0;
WMError ret = WMError::UNKNOWN;
ret = this->setRequest(id, role, area, task, &req_num);
+ //vector<WMLayerState> current_states = this->lc->getCurrentStates();
+ // ret = this->setRequest(id, role, area, task, current_states, &req_num);
+
if(ret != WMError::SUCCESS)
{
HMI_ERROR(errorDescription(ret));
@@ -291,6 +517,8 @@ void WindowManager::api_activate_window(char const *appid, char const *drawing_n
return;
}
+ this->wmcon.setAppIdToEcuName(id, "");
+
reply(nullptr);
if (req_num != g_app_list.currentRequestNumber())
{
@@ -299,7 +527,9 @@ void WindowManager::api_activate_window(char const *appid, char const *drawing_n
return;
}
- // Do allocate tasks
+ /*
+ * Do allocate tasks
+ */
ret = this->checkPolicy(req_num);
if (ret != WMError::SUCCESS)
@@ -311,12 +541,156 @@ void WindowManager::api_activate_window(char const *appid, char const *drawing_n
}
}
+void WindowManager::api_activate_surface_for_slave(
+ char const *appid, char const *drawing_name,
+ char const *drawing_area, const reply_func &reply)
+{
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
+ string id = appid;
+ string role = c_role;
+ string area = drawing_area;
+
+ if(!g_app_list.contains(id))
+ {
+ // Request surface of app in slave to register app information
+ this->api_request_surface(appid, drawing_name);
+
+ // Set role of app in slave to register app information
+ this->api_set_role(appid, drawing_name);
+ }
+ auto client = g_app_list.lookUpClient(id);
+
+ // unsigned srfc = client->surfaceID(role);
+ // unsigned layer = client->layerID();
+
+ // g_app_list.removeFloatingSurface(client->surfaceID());
+ // g_app_list.removeFloatingSurface(client);
+
+ Task task = Task::TASK_ALLOCATE;
+ unsigned req_num = 0;
+ WMError ret = WMError::UNKNOWN;
+
+ ret = this->setRequestForSlave(id, role, area, task, &req_num);
+
+ //vector<WMLayerState> current_states = this->lc->getCurrentStates();
+ // ret = this->setRequest(id, role, area, task, current_states, &req_num);
+
+ if(ret != WMError::SUCCESS)
+ {
+ HMI_ERROR(errorDescription(ret));
+ reply("Failed to set request");
+ return;
+ }
+
+ this->wmcon.setAppIdToReceivedEcuName(id);
+
+ reply(nullptr);
+ if (req_num != g_app_list.currentRequestNumber())
+ {
+ // Add request, then invoked after the previous task is finished
+ HMI_SEQ_DEBUG(req_num, "request is accepted");
+ return;
+ }
+
+ /*
+ * Do allocate tasks
+ */
+ ret = this->checkPolicyForSlave(req_num);
+
+ if (ret != WMError::SUCCESS)
+ {
+ //this->emit_error()
+ HMI_SEQ_ERROR(req_num, errorDescription(ret));
+ g_app_list.removeRequest(req_num);
+ this->processNextRequest();
+ }
+}
+
+void WindowManager::api_activate_surface_to_master(
+ char const *appid, char const *drawing_name,
+ char const *drawing_area, const reply_func &reply)
+{
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
+ string id = appid;
+ string role = c_role;
+ string area = drawing_area;
+
+ if(!g_app_list.contains(id))
+ {
+ reply("app doesn't request 'requestSurface' or 'setRole' yet");
+ return;
+ }
+ auto client = g_app_list.lookUpClient(id);
+
+ // unsigned srfc = client->surfaceID(role);
+ // unsigned layer = client->layerID();
+
+ // g_app_list.removeFloatingSurface(client->surfaceID());
+ // g_app_list.removeFloatingSurface(client);
+
+ Task task = Task::TASK_ALLOCATE;
+ unsigned req_num = 0;
+ WMError ret = WMError::UNKNOWN;
+
+ ret = this->setRequest(id, role, area, task, &req_num);
+
+ //vector<WMLayerState> current_states = this->lc->getCurrentStates();
+ // ret = this->setRequest(id, role, area, task, current_states, &req_num);
+
+ if(ret != WMError::SUCCESS)
+ {
+ HMI_ERROR(errorDescription(ret));
+ reply("Failed to set request");
+ return;
+ }
+
+ std::string ecu_name;
+ ecu_name = this->wmcon.getAreaToEcuName(area.c_str());
+
+ this->wmcon.setAppIdToEcuName(id, ecu_name);
+
+ reply(nullptr);
+ if (req_num != g_app_list.currentRequestNumber())
+ {
+ // Add request, then invoked after the previous task is finished
+ HMI_SEQ_DEBUG(req_num, "request is accepted");
+ return;
+ }
+
+ /*
+ * Do allocate tasks
+ */
+ int i_ret = this->wmcon.sendRequest("activateWindow", appid,
+ drawing_name, drawing_area);
+ if (0 > i_ret)
+ {
+ //this->emit_error()
+ HMI_SEQ_ERROR(req_num, errorDescription(ret));
+ g_app_list.removeRequest(req_num);
+ this->processNextRequest();
+ }
+
+ this->setTimer();
+}
+
void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name,
const reply_func &reply)
{
- // Check Phase
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
+ /*
+ * Check Phase
+ */
string id = appid;
- string role = drawing_name;
+ string role = c_role;
string area = ""; //drawing_area;
Task task = Task::TASK_RELEASE;
unsigned req_num = 0;
@@ -339,7 +713,9 @@ void WindowManager::api_deactivate_window(char const *appid, char const *drawing
return;
}
- // Do allocate tasks
+ /*
+ * Do allocate tasks
+ */
ret = this->checkPolicy(req_num);
if (ret != WMError::SUCCESS)
@@ -351,10 +727,112 @@ void WindowManager::api_deactivate_window(char const *appid, char const *drawing
}
}
+void WindowManager::api_deactivate_surface_for_slave(char const *appid, char const *drawing_name,
+ const reply_func &reply)
+{
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
+ /*
+ * Check Phase
+ */
+ string id = appid;
+ string role = c_role;
+ string area = "";//drawing_area;
+ Task task = Task::TASK_RELEASE;
+ unsigned req_num = 0;
+ WMError ret = WMError::UNKNOWN;
+
+ ret = this->setRequest(id, role, area, task, &req_num);
+
+ if (ret != WMError::SUCCESS)
+ {
+ HMI_ERROR(errorDescription(ret));
+ reply("Failed to set request");
+ return;
+ }
+
+ reply(nullptr);
+ if (req_num != g_app_list.currentRequestNumber())
+ {
+ // Add request, then invoked after the previous task is finished
+ HMI_SEQ_DEBUG(req_num, "request is accepted");
+ return;
+ }
+
+ /*
+ * Do allocate tasks
+ */
+ ret = this->checkPolicyForSlave(req_num);
+
+ if (ret != WMError::SUCCESS)
+ {
+ //this->emit_error()
+ HMI_SEQ_ERROR(req_num, errorDescription(ret));
+ g_app_list.removeRequest(req_num);
+ this->processNextRequest();
+ }
+}
+
+void WindowManager::api_deactivate_surface_to_master(char const *appid, char const *drawing_name,
+ const reply_func &reply)
+{
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
+ /*
+ * Check Phase
+ */
+ string id = appid;
+ string role = c_role;
+ string area = "";//drawing_area;
+ Task task = Task::TASK_RELEASE;
+ unsigned req_num = 0;
+ WMError ret = WMError::UNKNOWN;
+
+ ret = this->setRequest(id, role, area, task, &req_num);
+
+ if (ret != WMError::SUCCESS)
+ {
+ HMI_ERROR(errorDescription(ret));
+ reply("Failed to set request");
+ return;
+ }
+
+ reply(nullptr);
+ if (req_num != g_app_list.currentRequestNumber())
+ {
+ // Add request, then invoked after the previous task is finished
+ HMI_SEQ_DEBUG(req_num, "request is accepted");
+ return;
+ }
+
+ /*
+ * Do allocate tasks
+ */
+ int i_ret = this->wmcon.sendRequest("deactivateWindow", appid,
+ drawing_name, "");
+ if (0 > i_ret)
+ {
+ //this->emit_error()
+ HMI_SEQ_ERROR(req_num, errorDescription(ret));
+ g_app_list.removeRequest(req_num);
+ this->processNextRequest();
+ }
+
+ this->setTimer();
+}
+
void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
{
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
string id = appid;
- string role = drawing_name;
+ string role = c_role;
unsigned current_req = g_app_list.currentRequestNumber();
bool result = g_app_list.setEndDrawFinished(current_req, id, role);
@@ -381,6 +859,8 @@ void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
this->emitScreenUpdated(current_req);
HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret));
+ this->saveLastModeData(current_req);
+
g_app_list.removeRequest(current_req);
this->processNextRequest();
@@ -392,6 +872,67 @@ void WindowManager::api_enddraw(char const *appid, char const *drawing_name)
}
}
+int WindowManager::api_subscribe(afb_req req, int event_id)
+{
+ struct afb_event event = this->map_afb_event[kListEventName[event_id]];
+ return afb_req_subscribe(req, event);
+}
+
+void WindowManager::api_handshake()
+{
+ if (this->end_init && this->wmcon.getEndInit())
+ {
+ this->send_event(kListEventName[Event_Handshake]);
+ }
+}
+
+void WindowManager::api_enddraw_for_remote(char const *appid, char const *drawing_name)
+{
+ int ret = this->wmcon.sendRequest("endDraw", appid, drawing_name, "");
+ if (0 > ret)
+ {
+ //this->emit_error()
+
+ this->pmw.undoState();
+ this->lc->undoUpdate();
+
+ unsigned current_req = g_app_list.currentRequestNumber();
+ g_app_list.removeRequest(current_req);
+ this->processNextRequest();
+
+ return;
+ }
+
+ this->api_enddraw(appid, drawing_name);
+}
+
+bool WindowManager::api_client_set_render_order(char const* appid, const vector<string>& render_order)
+{
+ bool ret = false;
+ string id = appid;
+ auto client = g_app_list.lookUpClient(id);
+ if(client)
+ {
+ client->setRenderOrder(render_order);
+ }
+ return ret;
+}
+
+string WindowManager::api_client_attach_service_surface
+ (const char* appid, const char* dest, const char* service_surface)
+{
+ string uuid, s_dest = dest;
+ auto client = g_app_list.lookUpClient(s_dest);
+ if(!client)
+ {
+ HMI_ERROR("Failed to look up destination [%s]", dest);
+ return uuid;
+ }
+ uuid = client->attachTmpServiceSurface(appid, service_surface);
+ this->tmp_services.emplace_back(TmpService{appid, dest, service_surface, uuid});
+ return uuid;
+}
+
json_object* WindowManager::api_get_area_list()
{
json_object* ret = json_object_new_object();
@@ -480,46 +1021,9 @@ void WindowManager::api_change_area_size(ChangeAreaReq &areas)
// Request change size to applications
for(const auto &action : g_app_list.getActions(req_num, &found))
{
- struct rect r = this->lc->getAreaSize(action.area);
- action.client->emitSyncDraw(action.area, r);
- }
-}
-
-bool WindowManager::api_subscribe(afb_req_t req, EventType event_id)
-{
- bool ret = false;
- char* appid = afb_req_get_application_id(req);
- if(event_id < Event_Val_Min || event_id > Event_Val_Max)
- {
- HMI_ERROR("not defined in Window Manager", event_id);
- return ret;
- }
- HMI_INFO("%s subscribe %s : %d", appid, kListEventName[event_id].c_str(), event_id);
- if(event_id == Event_ScreenUpdated)
- {
- // Event_ScreenUpdated should be emitted to subscriber
- afb_event_t event = this->map_afb_event[kListEventName[event_id]];
- int rc = afb_req_subscribe(req, event);
- if(rc == 0)
- {
- ret = true;
- }
- }
- else if(appid)
- {
- string id = appid;
- free(appid);
- if(!g_app_list.contains(id))
- {
- g_app_list.addClient(id);
- }
- g_app_list.lookUpClient(id)->subscribe(req, kListEventName[event_id]);
- }
- else
- {
- HMI_ERROR("appid is not set");
+ string old_role = this->rolenew2old[action.role];
+ this->emit_syncdraw(old_role, action.area);
}
- return ret;
}
result<json_object *> WindowManager::api_get_display_info()
@@ -541,7 +1045,9 @@ result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
{
HMI_DEBUG("called");
- string role = drawing_name;
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *role = this->convertRoleOldToNew(drawing_name);
// Check drawing name, surface/layer id
auto const &surface_id = this->id_alloc.lookup(role);
@@ -551,7 +1057,7 @@ result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
}
// Set area rectangle
- struct rect area_info = this->area_info[*surface_id];
+ rect area_info = this->area_info[*surface_id];
json_object *object = json_object_new_object();
json_object_object_add(object, kKeyX, json_object_new_int(area_info.x));
json_object_object_add(object, kKeyY, json_object_new_int(area_info.y));
@@ -561,10 +1067,166 @@ result<json_object *> WindowManager::api_get_area_info(char const *drawing_name)
return Ok<json_object *>(object);
}
+result<json_object *> WindowManager::api_get_car_info(char const *label)
+{
+ json_object *j_in = nullptr;
+ json_object *j_out = nullptr;
+
+ if (0 == strcmp("parking_brake_status", label))
+ {
+ // Get parking brake status
+ json_bool val = (this->crr_car_info.parking_brake_stt) ? TRUE : FALSE;
+ j_in = json_object_new_boolean(val);
+ }
+ else if (0 == strcmp("accelerator.pedal.position", label))
+ {
+ // Get accelerator pedal position
+ double val = this->crr_car_info.accel_pedal_pos;
+ j_in = json_object_new_double(val);
+ }
+ else if (0 == strcmp("car_state", label))
+ {
+ // Get running state
+ const char* val = (this->crr_car_info.running_stt) ? "run" : "stop";
+ j_in = json_object_new_string(val);
+ }
+ else if (0 == strcmp("lightstatus.brake", label)) {
+ // Get lightstatus brake status
+ json_bool val = (this->crr_car_info.lightstatus_brake_stt) ? TRUE : FALSE;
+ j_in = json_object_new_boolean(val);
+ }
+ else
+ {
+ return Err<json_object *>("Car info does not exist");
+ }
+
+ // Create output object
+ j_out = json_object_new_object();
+ json_object_object_add(j_out, "value", j_in);
+
+ return Ok<json_object *>(j_out);
+}
+
+void WindowManager::send_event(const string& evname)
+{
+ HMI_DEBUG("%s: %s", __func__, evname.c_str());
+
+ int ret = afb_event_push(this->map_afb_event[evname], nullptr);
+ if (ret != 0)
+ {
+ HMI_DEBUG("afb_event_push: %m");
+ }
+}
+
+void WindowManager::send_event(const string& evname, const string& role)
+{
+ HMI_DEBUG("%s: %s(%s)", __func__, evname.c_str(), role.c_str());
+
+ json_object *j = json_object_new_object();
+ json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
+
+ int ret = afb_event_push(this->map_afb_event[evname], j);
+ if (ret != 0)
+ {
+ HMI_DEBUG("afb_event_push failed: %m");
+ }
+}
+
+void WindowManager::send_event(const string& evname, const string& role, const string& area,
+ int x, int y, int w, int h)
+{
+ HMI_DEBUG("%s: %s(%s, %s) x:%d y:%d w:%d h:%d",
+ __func__, evname.c_str(), role.c_str(), area.c_str(), x, y, w, h);
+
+ json_object *j_rect = json_object_new_object();
+ json_object_object_add(j_rect, kKeyX, json_object_new_int(x));
+ json_object_object_add(j_rect, kKeyY, json_object_new_int(y));
+ json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w));
+ json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h));
+
+ json_object *j = json_object_new_object();
+ json_object_object_add(j, kKeyDrawingName, json_object_new_string(role.c_str()));
+ json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area.c_str()));
+ json_object_object_add(j, kKeyDrawingRect, j_rect);
+
+ int ret = afb_event_push(this->map_afb_event[evname], j);
+ if (ret != 0)
+ {
+ HMI_DEBUG("afb_event_push failed: %m");
+ }
+}
+
+string WindowManager::searchApp(unsigned pid, unsigned ppid, unsigned surface, json_object* resp)
+{
+ // retrieve appid from pid from application manager
+ string appid;
+ // check appid then add it to the client
+ HMI_INFO("Runners:%s", json_object_get_string(resp));
+ int size = json_object_array_length(resp);
+ HMI_INFO("pid %d, ppid %d, surface %d",pid, ppid, surface);
+ for(int i = 0; i < size; i++)
+ {
+ json_object *j = json_object_array_get_idx(resp, i);
+ int runid = jh::getIntFromJson(j, "runid");
+ const char* id = jh::getStringFromJson(j, "id");
+ HMI_DEBUG("Appid %s, runid %d", id, runid);
+ if(id && (runid == ppid))
+ {
+ string s_id = id;
+ s_id.erase(s_id.find('@'));
+ appid = s_id;
+ HMI_INFO("App found %s", appid.c_str());
+ break;
+ }
+ }
+ if(appid.empty())
+ {
+ HMI_WARNING("Failed to retrieve id");
+ }
+ return appid;
+}
+
+void WindowManager::storeSurface(const string& appid, unsigned ppid, unsigned surface)
+{
+ auto elem = std::find_if(this->tmp_services.begin(), this->tmp_services.end(),
+ [&appid](TmpService& ts){
+ return (ts.dest == appid );
+ });
+
+ this->lc->setXDGSurfaceOriginSize(surface);
+ if(elem != this->tmp_services.end())
+ {
+ // attachApp
+ auto client = g_app_list.lookUpClient(elem->dest);
+ if(client == nullptr)
+ {
+ return;
+ }
+ HMI_INFO("Attach surface %d (service %s) to app %s", surface, elem->service.c_str(), elem->dest.c_str());
+ client->attachServiceSurface(elem->service, surface);
+ }
+ else
+ {
+ // setRole
+ auto client = g_app_list.lookUpClient(appid);
+ if(client != nullptr)
+ {
+ client->addSurface(surface);
+ this->id_alloc.register_name_id(client->role(), surface);
+ }
+ else
+ {
+ // Store tmp surface and appid for application
+ // who requests setRole after creating shell surface
+ this->tmp_surface2app.emplace(surface, TmpClient{appid, ppid});
+ }
+ }
+}
+
/**
* proxied events
*/
-void WindowManager::surface_created(unsigned surface_id)
+void WindowManager::surface_created(unsigned pid, unsigned surface_id)
{
// requestSurface
if(this->tmp_surface2app.count(surface_id) != 0)
@@ -582,6 +1244,52 @@ void WindowManager::surface_created(unsigned surface_id)
}
this->tmp_surface2app.erase(surface_id);
}
+ else
+ {
+ HMI_NOTICE("Unknown surface %d", surface_id);
+ // retrieve ppid
+ std::ostringstream os;
+ os << pid ;
+ string path = "/proc/" + os.str() + "/stat";
+ std::ifstream ifs(path.c_str());
+ string str;
+ unsigned ppid = 0;
+ if(!ifs.fail() && std::getline(ifs, str))
+ {
+ std::sscanf(str.data(), "%*d %*s %*c %d", &ppid);
+ HMI_INFO("Retrieve ppid %d", ppid);
+ }
+ else
+ {
+ HMI_ERROR("Failed to open /proc/%d/stat", pid);
+ HMI_ERROR("File system may be different");
+ return;
+ }
+ struct AfbClosure* c = new struct AfbClosure(pid, ppid, surface_id);
+ // search pid from surfaceID
+ afb_service_call("afm-main", "runners", json_object_new_object(),
+ [](void* closure, int stat, json_object* resp){
+ HMI_DEBUG("check %s", json_object_get_string(resp));
+ struct AfbClosure* c = static_cast<struct AfbClosure*>(closure);
+ HMI_DEBUG("check");
+ if(stat != 0)
+ {
+ HMI_ERROR("Failed to call runners");
+ }
+ else
+ {
+ json_object* j;
+ json_object_object_get_ex(resp, "response", &j);
+ string appid = g_context->searchApp(c->pid, c->ppid, c->surface, j);
+ if(!appid.empty())
+ {
+ g_context->storeSurface(appid, c->ppid, c->surface);
+ }
+ }
+ json_object_put(resp);
+ delete c;
+ }, c);
+ }
}
void WindowManager::surface_removed(unsigned surface_id)
@@ -608,6 +1316,25 @@ void WindowManager::exceptionProcessForTransition()
this->processNextRequest();
}
+void WindowManager::analyzeReceivedEvent(const char *event, struct json_object *object)
+{
+ HMI_DEBUG("event:%s", event);
+
+ // If receive low can signal
+ if (strstr(event, "low-can"))
+ {
+ // Analyze low can signal
+ const char *signal_name = this->lcc.analyzeCanSignal(object);
+
+ // Create task for car state and input it to PolicyManager
+ Task task = this->convertCanSignalToCarStateTask(signal_name);
+ if (Task::TASK_INVALID != task)
+ {
+ this->inputCarStateTask(task);
+ }
+ }
+}
+
void WindowManager::timerHandler()
{
unsigned req_num = g_app_list.currentRequestNumber();
@@ -619,8 +1346,10 @@ void WindowManager::timerHandler()
void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
{
- WMError ret;
+ WMError ret = WMError::UNKNOWN;
+ // req_num is guaranteed by Window Manager
unsigned req_num = g_app_list.currentRequestNumber();
+ Task task = Task::TASK_INVALID;
if (actions.empty())
{
@@ -636,27 +1365,58 @@ void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
}
}
+ // Check weather there is the no request task
+ // [The no request task]
+ // - TaskCarState::RESTRICTION_MODE_OFF
+ // - TaskCarState::RESTRICTION_MODE_ON
+ for (const auto &act : actions)
+ {
+ if (TaskCarState::RESTRICTION_MODE_OFF == act.car_state)
+ {
+ task = Task::TASK_RESTRICTION_MODE_OFF;
+ break;
+ }
+ else if (TaskCarState::RESTRICTION_MODE_ON == act.car_state)
+ {
+ task = Task::TASK_RESTRICTION_MODE_ON;
+ break;
+ }
+ }
+
+ // If there is the request-less task, set request here
+ if (Task::TASK_INVALID != task) {
+ unsigned req_num;
+ ret = this->setRequest(task, &req_num);
+
+ if(ret != WMError::SUCCESS)
+ {
+ goto error;
+ }
+ }
+
for (auto &act : actions)
{
if ("" != act.role)
{
bool found;
- auto const &surface_id = this->id_alloc.lookup(act.role);
+ auto const &surface_id = this->id_alloc.lookup(act.role.c_str());
if(surface_id == nullopt)
{
- goto proc_remove_request;
+ HMI_SEQ_DEBUG(req_num, "There is not surface id for role:%s", act.role.c_str());
+ continue;
}
+
string appid = g_app_list.getAppID(*surface_id, &found);
if (!found)
{
if (TaskVisible::INVISIBLE == act.visible)
{
- // App is killed, so do not set this action
+ HMI_SEQ_DEBUG(req_num, "role:%s is killed, so do not set this action", act.role.c_str());
continue;
}
else
{
- HMI_SEQ_ERROR(req_num, "appid which is visible is not found");
+ HMI_SEQ_ERROR(req_num, "appid of role:%s which is visible is not found", act.role.c_str());
ret = WMError::FAIL;
goto error;
}
@@ -664,6 +1424,20 @@ void WindowManager::startTransitionWrapper(vector<WMAction> &actions)
auto client = g_app_list.lookUpClient(appid);
act.req_num = req_num;
act.client = client;
+
+ if (this->wmcon.getAppIdToEcuName(appid) != "")
+ {
+ if (TaskVisible::VISIBLE == act.visible && this->wmcon.getAreaToEcuName(act.area.c_str()) == this->wmcon.getEcuName())
+ {
+ HMI_DEBUG("Set TaskVisible::REQ_REMOTE_VISIBLE");
+ act.visible = TaskVisible::REQ_REMOTE_VISIBLE;
+ }
+ else
+ {
+ HMI_DEBUG("Set TaskVisible::REQ_REMOTE_INVISIBLE");
+ act.visible = TaskVisible::REQ_REMOTE_INVISIBLE;
+ }
+ }
}
ret = g_app_list.setAction(req_num, act);
@@ -711,22 +1485,246 @@ void WindowManager::processError(WMError error)
this->processNextRequest();
}
-unsigned WindowManager::generateLayerForClient(const string& role)
+void WindowManager::processForRemoteRequest(json_object *data)
{
- unsigned lid = this->lc->getNewLayerID(role);
- if (lid == 0)
+ const char *req = jh::getStringFromJson(data, "req");
+ const char *appid = jh::getStringFromJson(data, "appid");
+ const char *drawing_name = jh::getStringFromJson(data, "drawing_name");
+ const char *drawing_area = jh::getStringFromJson(data, "drawing_area");
+ string request = req;
+ string role = drawing_name;
+ string area = drawing_area;
+
+ if (!req || !drawing_name)
{
- // register drawing_name as fallback and make it displayed.
- lid = this->lc->getNewLayerID(string("fallback"));
- HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str());
- if (lid == 0)
+ HMI_ERROR("Parse Error!!");
+ return;
+ }
+
+ if (this->wmcon.getAreaToEcuName(drawing_area) == this->wmcon.getEcuName())
+ {
+ if (!appid)
{
- return lid;
+ HMI_ERROR("Parse Error!!");
+ return;
+ }
+
+ auto reply = [](const char *errmsg) {
+ if (errmsg != nullptr)
+ {
+ HMI_ERROR(errmsg);
+ return;
+ }
+ };
+
+ if ("activateWindow" == request)
+ {
+ if (!drawing_area)
+ {
+ HMI_ERROR("Parse Error!!");
+ return;
+ }
+
+ this->api_activate_surface_for_slave(
+ appid, drawing_name, drawing_area, reply);
+ }
+ else if ("deactivateWindow" == request)
+ {
+ this->api_deactivate_surface_for_slave(
+ appid, drawing_name, reply);
+ }
+ else if ("endDraw" == request)
+ {
+ this->api_enddraw(appid, drawing_name);
}
}
- this->lc->createNewLayer(lid);
- // add client into the db
- return lid;
+ else
+ {
+ if ("syncDraw" == request)
+ {
+ this->stopTimer();
+
+ if (!appid || !drawing_area)
+ {
+ HMI_ERROR("Parse Error!!");
+ return;
+ }
+
+ unsigned req_num = g_app_list.currentRequestNumber();
+ auto client = g_app_list.lookUpClient(appid);
+
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
+ // Create action
+ bool end_draw_finished = false;
+ WMAction act
+ {
+ req_num,
+ client,
+ string(c_role),
+ area,
+ TaskVisible::REMOTE_VISIBLE,
+ end_draw_finished,
+ TaskCarState::NO_TASK
+ };
+
+ // Set action
+ WMError ret = g_app_list.setAction(req_num, act);
+ if (ret != WMError::SUCCESS)
+ {
+ HMI_SEQ_ERROR(req_num, "Setting action is failed");
+ return;
+ }
+
+ this->emit_syncdraw(role, area);
+ this->wmcon.startSyncDrawForRemote(appid);
+ this->setTimer();
+ }
+ else if ("activated" == request)
+ {
+ this->emit_visible(role);
+ this->emit_activated(area);
+ }
+ else if ("deactivated" == request)
+ {
+ this->stopTimer();
+
+ if (!appid || !drawing_area)
+ {
+ HMI_ERROR("Parse Error!!");
+ return;
+ }
+
+ unsigned req_num = g_app_list.currentRequestNumber();
+ auto client = g_app_list.lookUpClient(appid);
+
+ // TODO: application requests by old role,
+ // so convert role old to new
+ const char *c_role = this->convertRoleOldToNew(drawing_name);
+
+ if(!this->lc->hasRemoteLayer(client->layerID()))
+ {
+ HMI_DEBUG("Deactivated");
+ return;
+ }
+
+ // Create action
+ bool end_draw_finished = true;
+ WMAction act
+ {
+ req_num,
+ client,
+ string(c_role),
+ "",
+ TaskVisible::REMOTE_INVISIBLE,
+ end_draw_finished,
+ TaskCarState::NO_TASK
+ };
+
+ this->lc->visibilityChange(act);
+ this->lc->renderLayers();
+
+ this->emit_invisible(role);
+ this->emit_deactivated(role);
+ }
+ else if ("flushDraw" == request)
+ {
+ this->emit_flushdraw(role);
+ }
+ }
+}
+
+/*
+ ******* Private Functions *******
+ */
+
+void WindowManager::emit_activated(const string& role)
+{
+ this->send_event(kListEventName[Event_Active], role);
+}
+
+void WindowManager::emit_deactivated(const string& role)
+{
+ this->send_event(kListEventName[Event_Inactive], role);
+}
+
+void WindowManager::emit_syncdraw(const string& role, char const *area, int x, int y, int w, int h)
+{
+ this->send_event(kListEventName[Event_SyncDraw], role, area, x, y, w, h);
+}
+
+void WindowManager::emit_syncdraw(const string &role, const string &area)
+{
+ struct rect rect = this->lc->getAreaSize(area);
+ this->send_event(kListEventName[Event_SyncDraw],
+ role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h);
+}
+
+void WindowManager::emit_flushdraw(const string& role)
+{
+ this->send_event(kListEventName[Event_FlushDraw], role);
+}
+
+void WindowManager::emit_visible(const string& role, bool is_visible)
+{
+ this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], role);
+}
+
+void WindowManager::emit_invisible(const string& role)
+{
+ return emit_visible(role, false);
+}
+
+void WindowManager::emit_visible(const string& role) { return emit_visible(role, true); }
+
+void WindowManager::emitHeadlampOff()
+{
+ // Send HeadlampOff event for all application
+ this->send_event(kListEventName[Event_HeadlampOff]);
+}
+
+void WindowManager::emitHeadlampOn()
+{
+ // Send HeadlampOn event for all application
+ this->send_event(kListEventName[Event_HeadlampOn]);
+}
+
+void WindowManager::emitParkingBrakeOff()
+{
+ // Send ParkingBrakeOff event for all application
+ this->send_event(kListEventName[Event_ParkingBrakeOff]);
+}
+
+void WindowManager::emitParkingBrakeOn()
+{
+ // Send ParkingBrakeOn event for all application
+ this->send_event(kListEventName[Event_ParkingBrakeOn]);
+}
+
+void WindowManager::emitLightstatusBrakeOff()
+{
+ // Send LightstatusBrakeOff event for all application
+ this->send_event(kListEventName[Event_LightstatusBrakeOff]);
+}
+
+void WindowManager::emitLightstatusBrakeOn()
+{
+ // Send LightstatusBrakeOn event for all application
+ this->send_event(kListEventName[Event_LightstatusBrakeOn]);
+}
+
+void WindowManager::emitCarStop()
+{
+ // Send CarStop event for all application
+ this->send_event(kListEventName[Event_CarStop]);
+}
+
+void WindowManager::emitCarRun()
+{
+ // Send CarRun event for all application
+ this->send_event(kListEventName[Event_CarRun]);
}
WMError WindowManager::setRequest(const string& appid, const string &role, const string &area,
@@ -761,6 +1759,48 @@ WMError WindowManager::setRequest(const string& appid, const string &role, const
return WMError::SUCCESS;
}
+WMError WindowManager::setRequest(Task task, unsigned* req_num)
+{
+ /*
+ * Queueing Phase
+ */
+ unsigned current = g_app_list.currentRequestNumber();
+
+ WMRequest req = WMRequest(task);
+ unsigned new_req = g_app_list.addRequest(req);
+ *req_num = new_req;
+ g_app_list.reqDump();
+
+ HMI_SEQ_DEBUG(current, "start sequence for task:%d", task);
+
+ return WMError::SUCCESS;
+}
+
+WMError WindowManager::setRequestForSlave(const string& appid, const string &role, const string &area,
+ Task task, unsigned* req_num)
+{
+ /*
+ * Queueing Phase
+ */
+ unsigned current = g_app_list.currentRequestNumber();
+ unsigned requested_num = g_app_list.getRequestNumber(appid);
+ if (requested_num != 0)
+ {
+ HMI_SEQ_INFO(requested_num,
+ "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str());
+ return REQ_REJECTED;
+ }
+
+ WMRequest req = WMRequest(appid, role, area, task);
+ unsigned new_req = g_app_list.addRequest(req);
+ *req_num = new_req;
+ g_app_list.reqDump();
+
+ HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str());
+
+ return WMError::SUCCESS;
+}
+
WMError WindowManager::checkPolicy(unsigned req_num)
{
/*
@@ -777,6 +1817,54 @@ WMError WindowManager::checkPolicy(unsigned req_num)
}
string req_area = trigger.area;
+ if (trigger.task == Task::TASK_ALLOCATE)
+ {
+ const char *msg = this->check_surface_exist(trigger.role.c_str());
+
+ if (msg)
+ {
+ HMI_SEQ_ERROR(req_num, msg);
+ return ret;
+ }
+ }
+
+ // Input event data to PolicyManager
+ if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
+ {
+ HMI_SEQ_ERROR(req_num, "Failed to set input event data to PolicyManager");
+ return ret;
+ }
+
+ // Execute state transition of PolicyManager
+ if (0 > this->pmw.executeStateTransition())
+ {
+ HMI_SEQ_ERROR(req_num, "Failed to execute state transition of PolicyManager");
+ return ret;
+ }
+
+ ret = WMError::SUCCESS;
+
+ g_app_list.reqDump();
+
+ return ret;
+}
+
+WMError WindowManager::checkPolicyForSlave(unsigned req_num)
+{
+ /*
+ * Check Policy
+ */
+ // get current trigger
+ bool found = false;
+ WMError ret = WMError::LAYOUT_CHANGE_FAIL;
+ auto trigger = g_app_list.getRequest(req_num, &found);
+ if (!found)
+ {
+ ret = WMError::NO_ENTRY;
+ return ret;
+ }
+ string req_area = trigger.area;
+
// Input event data to PolicyManager
if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area))
{
@@ -815,11 +1903,28 @@ WMError WindowManager::startTransition(unsigned req_num)
g_app_list.reqDump();
for (const auto &action : actions)
{
+ // TODO: application requests by old role,
+ // so convert role new to old for emitting event
+ string old_role = this->rolenew2old[action.role];
+
if (action.visible == TaskVisible::VISIBLE)
{
sync_draw_happen = true;
- struct rect r = this->lc->getAreaSize(action.area);
- action.client->emitSyncDraw(action.area, r);
+
+ this->emit_syncdraw(old_role, action.area);
+ /* TODO: emit event for app not subscriber
+ if(g_app_list.contains(y.appid))
+ g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */
+ }
+ else if(action.visible == TaskVisible::REQ_REMOTE_VISIBLE)
+ {
+ // If this action is for slave, send to slave
+ this->wmcon.sendRequest("syncDraw", action.client->appID().c_str(),
+ old_role.c_str(), action.area.c_str());
+ }
+ else if (action.car_state != TaskCarState::NO_TASK)
+ {
+ this->transitionCarState(action.car_state);
}
}
@@ -834,7 +1939,28 @@ WMError WindowManager::startTransition(unsigned req_num)
for (const auto &x : actions)
{
this->lc->visibilityChange(x);
- x.client->emitVisible(false);
+ string old_role = this->rolenew2old[x.role];
+
+ if (x.visible == TaskVisible::INVISIBLE)
+ {
+ emit_deactivated(old_role);
+ }
+ else if (x.visible == TaskVisible::REQ_REMOTE_INVISIBLE)
+ {
+ // If this action is for slave, send to slave
+ int i_ret = this->wmcon.sendRequest("deactivated", x.client->appID().c_str(),
+ old_role.c_str(), "");
+ if (0 > i_ret)
+ {
+ ret = WMError::FAIL;
+ }
+ }
+
+ /* if (g_app_list.contains(x.appid))
+ {
+ auto client = g_app_list.lookUpClient(x.appid);
+ //this->deactivate(client->surfaceID(x.role));
+ } */
}
this->lc->renderLayers();
ret = WMError::NO_LAYOUT_CHANGE;
@@ -842,10 +1968,63 @@ WMError WindowManager::startTransition(unsigned req_num)
return ret;
}
+void WindowManager::transitionCarState(TaskCarState task)
+{
+ if (TaskCarState::PARKING_BRAKE_OFF == task)
+ {
+ this->crr_car_info.parking_brake_stt = false;
+ this->emitParkingBrakeOff();
+ }
+ else if (TaskCarState::PARKING_BRAKE_ON == task)
+ {
+ this->crr_car_info.parking_brake_stt = true;
+ this->emitParkingBrakeOn();
+ }
+ else if (TaskCarState::ACCEL_PEDAL_OFF == task)
+ {
+ this->crr_car_info.accel_pedal_stt = false;
+ }
+ else if (TaskCarState::ACCEL_PEDAL_ON == task)
+ {
+ this->crr_car_info.accel_pedal_stt = true;
+ }
+ else if (TaskCarState::HEDLAMP_OFF == task)
+ {
+ this->crr_car_info.headlamp_stt = false;
+ this->emitHeadlampOff();
+ }
+ else if (TaskCarState::HEDLAMP_ON == task)
+ {
+ this->crr_car_info.headlamp_stt = true;
+ this->emitHeadlampOn();
+ }
+ else if (TaskCarState::LIGHTSTATUS_BRAKE_OFF == task)
+ {
+ this->crr_car_info.lightstatus_brake_stt = false;
+ this->emitLightstatusBrakeOff();
+ }
+ else if (TaskCarState::LIGHTSTATUS_BRAKE_ON == task)
+ {
+ this->crr_car_info.lightstatus_brake_stt = true;
+ this->emitLightstatusBrakeOn();
+ }
+ else if (TaskCarState::CAR_STOP == task)
+ {
+ this->crr_car_info.running_stt = false;
+ this->emitCarStop();
+ }
+ else if (TaskCarState::CAR_RUN == task)
+ {
+ this->crr_car_info.running_stt = true;
+ this->emitCarRun();
+ }
+}
+
WMError WindowManager::doEndDraw(unsigned req_num)
{
// get actions
bool found;
+ bool trigger_homescreen = false;
auto actions = g_app_list.getActions(req_num, &found);
WMError ret = WMError::SUCCESS;
if (!found)
@@ -853,6 +2032,13 @@ WMError WindowManager::doEndDraw(unsigned req_num)
ret = WMError::NO_ENTRY;
return ret;
}
+ auto trigger = g_app_list.getRequest(req_num, &found);
+ HMI_SEQ_INFO(req_num, "trigger.role = %s", trigger.role.c_str());
+
+ if(trigger.role == "homescreen")
+ {
+ trigger_homescreen = true;
+ }
HMI_SEQ_INFO(req_num, "do endDraw");
@@ -869,8 +2055,46 @@ WMError WindowManager::doEndDraw(unsigned req_num)
"Failed to manipulate surfaces while state change : %s", errorDescription(ret));
return ret;
}
- ret = this->lc->visibilityChange(act);
- act.client->emitVisible((act.visible == VISIBLE));
+
+ if(trigger_homescreen && (act.visible == TaskVisible::INVISIBLE))
+ {
+ HMI_SEQ_NOTICE(req_num, "don't change visible if homescreen role is trigger");
+ }
+ else
+ {
+ ret = this->lc->visibilityChange(act);
+ }
+
+ // Emit active/deactive event
+ string old_role = this->rolenew2old[act.role];
+ switch(act.visible)
+ {
+ case TaskVisible::VISIBLE :
+ emit_visible(old_role);
+ emit_activated(old_role);
+ break;
+ case TaskVisible::REQ_REMOTE_VISIBLE :
+ {
+ // If this action is for slave, send to slave
+ int i_ret = this->wmcon.sendRequest("activated", "", old_role.c_str(), "");
+ if (0 > i_ret)
+ {
+ ret = WMError::FAIL;
+ }
+ break;
+ }
+ case TaskVisible::INVISIBLE :
+ if(!trigger_homescreen)
+ {
+ emit_invisible(old_role);
+ emit_deactivated(old_role);
+ }
+ break;
+ default :
+ // TaskVisible::REMOTE_VISIBLE, TaskVisible::REMOTE_INVISIBLE is this case
+ // If this action is for slave, send to slave
+ break;
+ }
if (ret != WMError::SUCCESS)
{
@@ -887,9 +2111,18 @@ WMError WindowManager::doEndDraw(unsigned req_num)
for(const auto &act_flush : actions)
{
+ // TODO: application requests by old role,
+ // so convert role new to old for emitting event
+ string old_role = this->rolenew2old[act_flush.role];
+
if(act_flush.visible == TaskVisible::VISIBLE)
{
- act_flush.client->emitFlushDraw();
+ this->emit_flushdraw(old_role);
+ }
+ else if(act_flush.visible == TaskVisible::REQ_REMOTE_VISIBLE)
+ {
+ // If this action is for slave, send to slave
+ this->wmcon.sendRequest("flushDraw", "", old_role.c_str(), "");
}
}
@@ -902,7 +2135,8 @@ void WindowManager::emitScreenUpdated(unsigned req_num)
HMI_SEQ_DEBUG(req_num, "emit screen updated");
bool found = false;
auto actions = g_app_list.getActions(req_num, &found);
- if (!found)
+
+ if(!found)
{
HMI_SEQ_ERROR(req_num,
"Window Manager bug :%s : Action is not set",
@@ -910,13 +2144,15 @@ void WindowManager::emitScreenUpdated(unsigned req_num)
return;
}
+ HMI_DEBUG("@@@@@");
// create json object
json_object *j = json_object_new_object();
json_object *jarray = json_object_new_array();
for(const auto& action: actions)
{
- if(action.visible != TaskVisible::INVISIBLE)
+ if((action.visible == TaskVisible::VISIBLE) ||
+ (action.visible == TaskVisible::REMOTE_VISIBLE))
{
json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str()));
}
@@ -926,7 +2162,7 @@ void WindowManager::emitScreenUpdated(unsigned req_num)
int ret = afb_event_push(
this->map_afb_event[kListEventName[Event_ScreenUpdated]], j);
- if (ret < 0)
+ if (ret != 0)
{
HMI_DEBUG("afb_event_push failed: %m");
}
@@ -944,7 +2180,7 @@ void WindowManager::setTimer()
if (g_timer_ev_src == nullptr)
{
// firsttime set into sd_event
- int ret = sd_event_add_time(afb_api_get_event_loop(afbBindingV3root), &g_timer_ev_src,
+ int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src,
CLOCK_BOOTTIME, (uint64_t)(ts.tv_sec + kTimeOut) * 1000000ULL, 1, processTimerHandler, this);
if (ret < 0)
{
@@ -990,4 +2226,374 @@ void WindowManager::processNextRequest()
}
}
+const char* WindowManager::convertRoleOldToNew(char const *old_role)
+{
+ const char *new_role = nullptr;
+
+ for (auto const &on : this->roleold2new)
+ {
+ std::regex regex = std::regex(on.first);
+ if (std::regex_match(old_role, regex))
+ {
+ // role is old. So convert to new.
+ new_role = on.second.c_str();
+ break;
+ }
+ }
+
+ if (nullptr == new_role)
+ {
+ // role is new or fallback.
+ new_role = old_role;
+ }
+
+ HMI_DEBUG("old:%s -> new:%s", old_role, new_role);
+
+ return new_role;
+}
+
+int WindowManager::loadOldRolesConfigFile()
+{
+ // Get afm application installed dir
+ char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
+ HMI_DEBUG("afm_app_install_dir:%s", afm_app_install_dir);
+
+ string file_name;
+ if (!afm_app_install_dir)
+ {
+ HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
+ }
+ else
+ {
+ file_name = string(afm_app_install_dir) + string(kPathOldRolesConfigFile);
+ }
+
+ // Load old_rolea config file
+ json_object* json_obj;
+ int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
+ if (0 > ret)
+ {
+ HMI_ERROR("Could not open %s, so use default old_roles information", kPathOldRolesConfigFile);
+ json_obj = json_tokener_parse(kDefaultOldRolesConfig);
+ }
+ HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
+
+ // Perse apps
+ json_object* json_cfg;
+ if (!json_object_object_get_ex(json_obj, "old_roles", &json_cfg))
+ {
+ HMI_ERROR("Parse Error!!");
+ return -1;
+ }
+
+ int len = json_object_array_length(json_cfg);
+ HMI_DEBUG("json_cfg len:%d", len);
+ HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
+
+ for (int i=0; i<len; i++)
+ {
+ json_object* json_tmp = json_object_array_get_idx(json_cfg, i);
+
+ const char* old_role = jh::getStringFromJson(json_tmp, "name");
+ if (nullptr == old_role)
+ {
+ HMI_ERROR("Parse Error!!");
+ return -1;
+ }
+
+ const char* new_role = jh::getStringFromJson(json_tmp, "new");
+ if (nullptr == new_role)
+ {
+ HMI_ERROR("Parse Error!!");
+ return -1;
+ }
+
+ this->roleold2new[old_role] = string(new_role);
+ }
+
+ // Check
+ for(auto itr = this->roleold2new.begin();
+ itr != this->roleold2new.end(); ++itr)
+ {
+ HMI_DEBUG(">>> role old:%s new:%s",
+ itr->first.c_str(), itr->second.c_str());
+ }
+
+ // Release json_object
+ json_object_put(json_obj);
+
+ return 0;
+}
+
+int WindowManager::saveLastModeData(unsigned req_num)
+{
+ bool found;
+ auto actions = g_app_list.getActions(req_num, &found);
+
+ HMI_DEBUG("Save LastMode data");
+
+ if (!found)
+ {
+ HMI_DEBUG("Not Found Entry");
+ return -1;
+ }
+
+ json_object *j_obj = json_object_new_object();
+ json_object *j_array = json_object_new_array();
+
+ for (const auto &act : actions)
+ {
+ if (act.visible == TaskVisible::VISIBLE)
+ {
+ unsigned layer = act.client->layerID();
+ unsigned surface = act.client->surfaceID();
+
+ t_ilm_bool visibility;
+
+ ilm_layerGetVisibility(layer, &visibility);
+
+ if (visibility == ILM_FALSE)
+ {
+ continue;
+ }
+
+ ilmSurfaceProperties sp;
+ ilm_getPropertiesOfSurface(surface, &sp);
+
+ json_object *j_array_obj = json_object_new_object();
+ json_object_object_add(j_array_obj, "role", json_object_new_string(act.role.c_str()));
+ json_object_object_add(j_array_obj, "visible",
+ json_object_new_string((visibility ? "true" : "false")));
+ json_object_object_add(j_array_obj, "area", json_object_new_string(act.area.c_str()));
+ json_object_object_add(j_array_obj, "destX", json_object_new_int(sp.destX));
+ json_object_object_add(j_array_obj, "destY", json_object_new_int(sp.destY));
+ json_object_object_add(j_array_obj, "destWidth", json_object_new_int(sp.destWidth));
+ json_object_object_add(j_array_obj, "destHeight", json_object_new_int(sp.destHeight));
+ json_object_object_add(j_array_obj, "sourceX", json_object_new_int(sp.sourceX));
+ json_object_object_add(j_array_obj, "sourceY", json_object_new_int(sp.sourceY));
+ json_object_object_add(j_array_obj, "sourceWidth", json_object_new_int(sp.sourceWidth));
+ json_object_object_add(j_array_obj, "sourceHeight", json_object_new_int(sp.sourceHeight));
+
+ json_object_array_add(j_array, j_array_obj);
+ }
+ }
+
+ json_object_object_add(j_obj, "LastModeData", j_array);
+
+ const char *buf = json_object_to_json_string(j_obj);
+
+ std::string root = getenv("AFM_APP_INSTALL_DIR");
+ std::string lastmode_path = root + WM_LASTMODE_PATH;
+
+ FILE *fp = fopen(lastmode_path.c_str(), "wb");
+ if (nullptr == fp)
+ {
+ HMI_ERROR("Could not open file");
+ return -1;
+ }
+
+ int len = strlen(buf);
+ fwrite(buf, len, 1, fp);
+
+ fclose(fp);
+
+ json_object_put(j_obj);
+
+ return 0;
+}
+
+Task WindowManager::convertCanSignalToCarStateTask(const char *signal_name)
+{
+ wm::LowCanClient *lcc = &(this->lcc);
+ Task task = Task::TASK_INVALID;
+
+ // If car info is updated, set car state change event
+ if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoParkingBrake]))
+ {
+ HMI_DEBUG("Parking Brake state is changed");
+
+ if (lcc->getCurrentParkingBrakeState())
+ {
+ task = wm::Task::TASK_PARKING_BRAKE_ON;
+ }
+ else
+ {
+ task = wm::Task::TASK_PARKING_BRAKE_OFF;
+ }
+ }
+ else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoAccelPedalPos]))
+ {
+ // Update accel pedal position
+ this->crr_car_info.accel_pedal_pos = lcc->getCurrentAccelPedalPosition();
+
+ if (lcc->isChangedAccelPedalState())
+ {
+ HMI_DEBUG("Accelerator Pedal state is changed");
+
+ if (lcc->getCurrentAccelPedalState())
+ {
+ task = wm::Task::TASK_ACCEL_PEDAL_ON;
+ }
+ else
+ {
+ task = wm::Task::TASK_ACCEL_PEDAL_OFF;
+ }
+ }
+ }
+ else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoHeadlame]))
+ {
+ HMI_DEBUG("Headlamp state is changed");
+
+ if (lcc->getCurrentHeadlampState())
+ {
+ task = wm::Task::TASK_HEDLAMP_ON;
+ }
+ else
+ {
+ task = wm::Task::TASK_HEDLAMP_OFF;
+ }
+ }
+ else if (strstr(signal_name, lcc->kSignalName[lcc->SignalNoLightstatusBrake]))
+ {
+ HMI_DEBUG("Lightstatus Brake state is changed");
+
+ if (lcc->getCurrentLightstatusBrakeState())
+ {
+ task = wm::Task::TASK_LIGHTSTATUS_BRAKE_ON;
+ }
+ else
+ {
+ task = wm::Task::TASK_LIGHTSTATUS_BRAKE_OFF;
+ }
+ }
+ return task;
+}
+
+void WindowManager::inputCarStateTask(Task task)
+{
+ unsigned req_num = 0;
+ WMError ret = WMError::UNKNOWN;
+
+ ret = this->setRequest(task, &req_num);
+
+ if(ret != WMError::SUCCESS)
+ {
+ HMI_ERROR(errorDescription(ret));
+ return;
+ }
+
+ if (req_num != g_app_list.currentRequestNumber())
+ {
+ // Add request, then invoked after the previous task is finished
+ HMI_SEQ_DEBUG(req_num, "request is accepted");
+ return;
+ }
+
+ /*
+ * Do allocate tasks
+ */
+ ret = this->checkPolicy(req_num);
+
+ if (ret != WMError::SUCCESS)
+ {
+ //this->emit_error()
+ HMI_SEQ_ERROR(req_num, errorDescription(ret));
+ g_app_list.removeRequest(req_num);
+ this->processNextRequest();
+ }
+}
+
+const char *WindowManager::check_surface_exist(const char *drawing_name)
+{
+ auto const &surface_id = this->id_alloc.lookup(string(drawing_name));
+ if (!surface_id)
+ {
+ return "Surface does not exist";
+ }
+
+ /* if (!this->controller->surface_exists(*surface_id))
+ {
+ return "Surface does not exist in controller!";
+ } */
+
+ /* auto layer_id = this->layers.get_layer_id(*surface_id);
+
+ if (!layer_id)
+ {
+ return "Surface is not on any layer!";
+ } */
+
+ HMI_DEBUG("surface %d is detected", *surface_id);
+ return nullptr;
+}
+
+const char* WindowManager::kDefaultOldRolesConfig = "{ \
+ \"old_roles\": [ \
+ { \
+ \"name\": \"HomeScreen\", \
+ \"new\": \"homescreen\" \
+ }, \
+ { \
+ \"name\": \"Music\", \
+ \"new\": \"music\" \
+ }, \
+ { \
+ \"name\": \"MediaPlayer\", \
+ \"new\": \"music\" \
+ }, \
+ { \
+ \"name\": \"Video\", \
+ \"new\": \"video\" \
+ }, \
+ { \
+ \"name\": \"VideoPlayer\", \
+ \"new\": \"video\" \
+ }, \
+ { \
+ \"name\": \"WebBrowser\", \
+ \"new\": \"browser\" \
+ }, \
+ { \
+ \"name\": \"Radio\", \
+ \"new\": \"radio\" \
+ }, \
+ { \
+ \"name\": \"Phone\", \
+ \"new\": \"phone\" \
+ }, \
+ { \
+ \"name\": \"Navigation\", \
+ \"new\": \"map\" \
+ }, \
+ { \
+ \"name\": \"HVAC\", \
+ \"new\": \"hvac\" \
+ }, \
+ { \
+ \"name\": \"Settings\", \
+ \"new\": \"settings\" \
+ }, \
+ { \
+ \"name\": \"Dashboard\", \
+ \"new\": \"dashboard\" \
+ }, \
+ { \
+ \"name\": \"POI\", \
+ \"new\": \"poi\" \
+ }, \
+ { \
+ \"name\": \"Mixer\", \
+ \"new\": \"mixer\" \
+ }, \
+ { \
+ \"name\": \"Restriction\", \
+ \"new\": \"restriction\" \
+ }, \
+ { \
+ \"name\": \"^OnScreen.*\", \
+ \"new\": \"on_screen\" \
+ } \
+ ] \
+}";
+
} // namespace wm
diff --git a/src/window_manager.hpp b/src/window_manager.hpp
index 4c2c49b..da6a267 100644
--- a/src/window_manager.hpp
+++ b/src/window_manager.hpp
@@ -27,6 +27,8 @@
#include "request.hpp"
#include "wm_error.hpp"
#include "wm_layer_control.hpp"
+#include "wm_connection.hpp"
+#include "low_can_client.hpp"
extern "C"
{
#include <afb/afb-binding.h>
@@ -131,7 +133,37 @@ struct id_allocator
struct TmpClient
{
std::string appid;
- unsigned layer;
+ unsigned pid;
+};
+
+struct TmpService
+{
+ std::string appid; // Used to search who create service surface
+ std::string dest; // Used to attach service to destination application
+ std::string service;// The name of service surface
+ std::string uuid; // uuid
+ TmpService(const std::string& app, const std::string& dst,
+ const std::string& svc, const std::string& uuid)
+ : appid(app), dest(dst), service(svc), uuid(uuid) {}
+};
+
+struct CarInfo
+{
+ CarInfo()
+ : parking_brake_stt(true),
+ accel_pedal_stt(false),
+ accel_pedal_pos(0.0),
+ running_stt(false),
+ headlamp_stt(false),
+ lightstatus_brake_stt(true)
+ {};
+
+ bool parking_brake_stt;
+ bool accel_pedal_stt;
+ double accel_pedal_pos;
+ bool running_stt;
+ bool headlamp_stt;
+ bool lightstatus_brake_stt;
};
class WindowManager
@@ -155,14 +187,33 @@ class WindowManager
Event_ScreenUpdated,
+ Event_Handshake,
+
+ Event_HeadlampOff,
+ Event_HeadlampOn,
+
+ Event_ParkingBrakeOff,
+ Event_ParkingBrakeOn,
+
+ Event_LightstatusBrakeOff,
+ Event_LightstatusBrakeOn,
+
+ Event_CarStop,
+ Event_CarRun,
+
Event_Error,
Event_Val_Max = Event_Error,
};
+ enum WM_Mode
+ {
+ Mode_Standalone = 0,
+ Mode_Connection,
+ };
+
explicit WindowManager();
~WindowManager() = default;
-
WindowManager(WindowManager const &) = delete;
WindowManager &operator=(WindowManager const &) = delete;
WindowManager(WindowManager &&) = delete;
@@ -172,33 +223,81 @@ class WindowManager
result<int> api_request_surface(char const *appid, char const *role);
char const *api_request_surface(char const *appid, char const *role, char const *ivi_id);
+ bool api_set_role(char const *appid, char const *role);
void api_activate_window(char const *appid, char const *role, char const *drawing_area, const reply_func &reply);
+ void api_activate_surface_for_slave(char const *appid, char const *drawing_name,
+ char const *drawing_area, const reply_func &reply);
+ void api_activate_surface_to_master(char const *appid, char const *drawing_name,
+ char const *drawing_area, const reply_func &reply);
void api_deactivate_window(char const *appid, char const *role, const reply_func &reply);
+ void api_deactivate_surface_for_slave(char const *appid, char const *drawing_name,
+ const reply_func &reply);
+ void api_deactivate_surface_to_master(char const *appid, char const *drawing_name,
+ const reply_func &reply);
void api_enddraw(char const *appid, char const *role);
+ int api_subscribe(afb_req req, int event_id);
+ void api_handshake();
+ void api_enddraw_for_remote(char const *appid, char const *drawing_name);
+ bool api_client_set_render_order(const char *appid, const std::vector<std::string> &render_order);
+ std::string api_client_attach_service_surface(const char* appid, const char* dest, const char* service_surface);
json_object* api_get_area_list();
void api_change_area_size(ChangeAreaReq &areas);
- bool api_subscribe(afb_req_t req, EventType event_id);
result<json_object *> api_get_display_info();
result<json_object *> api_get_area_info(char const *role);
+ result<json_object *> api_get_car_info(char const *label);
+ void send_event(const std::string& evname);
+ void send_event(const std::string& evname, const std::string& role);
+ void send_event(const std::string& evname, const std::string& role, const std::string& area, int x, int y, int w, int h);
// Events from the compositor we are interested in
- void surface_created(unsigned surface_id);
+ void surface_created(unsigned pid, unsigned surface_id);
void surface_removed(unsigned surface_id);
void removeClient(const std::string &appid);
void exceptionProcessForTransition();
+ const char* convertRoleOldToNew(char const *role);
+
+ void analyzeReceivedEvent(const char *event, struct json_object *object);
+
// Do not use this function
void timerHandler();
void startTransitionWrapper(std::vector<WMAction> &actions);
void processError(WMError error);
+ void processForRemoteRequest(json_object *data);
+ std::string searchApp(unsigned pid, unsigned ppid, unsigned surface, json_object* resp);
+ void storeSurface(const std::string& appid, unsigned ppid, unsigned surface);
+
+ WMConnection wmcon;
private:
- unsigned generateLayerForClient(const std::string &role);
+ // WM Events to clients
+ void emit_activated(const std::string& role);
+ void emit_deactivated(const std::string& role);
+ void emit_syncdraw(const std::string& role, char const *area, int x, int y, int w, int h);
+ void emit_syncdraw(const std::string &role, const std::string &area);
+ void emit_flushdraw(const std::string& role);
+ void emit_visible(const std::string& role, bool is_visible);
+ void emit_invisible(const std::string& role);
+ void emit_visible(const std::string& role);
+ void emitHeadlampOff();
+ void emitHeadlampOn();
+ void emitParkingBrakeOff();
+ void emitParkingBrakeOn();
+ void emitLightstatusBrakeOff();
+ void emitLightstatusBrakeOn();
+ void emitCarStop();
+ void emitCarRun();
+
WMError setRequest(const std::string &appid, const std::string &role, const std::string &area,
Task task, unsigned *req_num);
+ WMError setRequest(Task task, unsigned* req_num);
+ WMError setRequestForSlave(const std::string& appid, const std::string &role,
+ const std::string &area, Task task, unsigned* req_num);
WMError checkPolicy(unsigned req_num);
+ WMError checkPolicyForSlave(unsigned req_num);
WMError startTransition(unsigned req_num);
+ void transitionCarState(TaskCarState task);
WMError doEndDraw(unsigned req_num);
void emitScreenUpdated(unsigned req_num);
@@ -207,16 +306,34 @@ class WindowManager
void stopTimer();
void processNextRequest();
+ int loadOldRolesConfigFile();
+
+ int saveLastModeData(unsigned req_num);
+
+ Task convertCanSignalToCarStateTask(const char *signal_name);
+ void inputCarStateTask(Task task);
+
+ const char *check_surface_exist(const char *role);
+
private:
- std::map<std::string, afb_event_t> map_afb_event;
- std::unordered_map<std::string, struct rect> area2size;
+ std::map<std::string, struct afb_event> map_afb_event;
+ std::unordered_map<std::string, std::string> roleold2new;
+ std::unordered_map<std::string, std::string> rolenew2old;
std::shared_ptr<LayerControl> lc;
+
+ LowCanClient lcc;
+ CarInfo crr_car_info;
+
PMWrapper pmw;
rect_map area_info;
struct id_allocator id_alloc;
+ bool end_init;
+
// ID allocation and proxy methods for lookup
std::unordered_map<unsigned, struct TmpClient> tmp_surface2app;
+ std::vector<struct TmpService> tmp_services;
+ static const char* kDefaultOldRolesConfig;
};
} // namespace wm
diff --git a/src/wm_client.cpp b/src/wm_client.cpp
index 4bccb8c..3acf09e 100644
--- a/src/wm_client.cpp
+++ b/src/wm_client.cpp
@@ -16,7 +16,10 @@
#include <json-c/json.h>
#include "wm_client.hpp"
+#include "util.hpp"
#include <ilm/ilm_control.h>
+#include <uuid/uuid.h>
+
#define INVALID_SURFACE_ID 0
@@ -26,34 +29,19 @@ using std::vector;
namespace wm
{
-static const char kActive[] = "active";
-static const char kInactive[] = "inactive";
-static const char kVisible[] = "visible";
-static const char kInvisible[] = "invisible";
-static const char kSyncDraw[] = "syncDraw";
-static const char kFlushDraw[] = "flushDraw";
+static const vector<string> kWMEvents = {
+ // Private event for applications
+ "syncDraw", "flushDraw", "visible", "invisible", "active", "inactive", "error"};
+static const vector<string> kErrorDescription = {
+ "unknown-error"};
+
static const char kKeyDrawingName[] = "drawing_name";
-static const char kKeyDrawingArea[] = "drawing_area";
-static const char kKeyRole[] = "role";
-static const char kKeyArea[] = "area";
static const char kKeyrole[] = "role";
static const char kKeyError[] = "error";
-static const char kKeyErrorDesc[] = "errorDescription";
-static const char kKeyX[] = "x";
-static const char kKeyY[] = "y";
-static const char kKeyWidth[] = "width";
-static const char kKeyHeight[] = "height";
-static const char kKeyDrawingRect[] = "drawing-rect";
-
-static const vector<string> kWMEvents = {
- // Private event for applications
- kActive, kInactive,
- kVisible, kInvisible,
- kSyncDraw, kFlushDraw,
- kKeyError};
+static const char kKeyErrorDesc[] = "kErrorDescription";
WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const string &role)
- : id(appid), layer(layer), is_source_set(false),
+ : id(appid), layer(layer),
role2surface(0)
{
role2surface[role] = surface;
@@ -62,7 +50,7 @@ WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const
#if GTEST_ENABLED
string ev = x;
#else
- afb_event_t ev = afb_api_make_event(afbBindingV3root, x.c_str());
+ afb_event ev = afb_daemon_make_event(x.c_str());
#endif
evname2afb_event[x] = ev;
}
@@ -71,9 +59,6 @@ WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const
WMClient::WMClient(const string &appid, const string &role)
: id(appid),
layer(0),
- is_source_set(false),
- is_active(false),
- main_role(role),
role2surface(0),
evname2afb_event(0)
{
@@ -83,7 +68,7 @@ WMClient::WMClient(const string &appid, const string &role)
#if GTEST_ENABLED
string ev = x;
#else
- afb_event_t ev = afb_api_make_event(afbBindingV3root, x.c_str());
+ afb_event ev = afb_daemon_make_event(x.c_str());
#endif
evname2afb_event[x] = ev;
}
@@ -92,8 +77,6 @@ WMClient::WMClient(const string &appid, const string &role)
WMClient::WMClient(const string &appid, unsigned layer, const string &role)
: id(appid),
layer(layer),
- is_source_set(false),
- is_active(false),
main_role(role),
role2surface(0),
evname2afb_event(0)
@@ -104,7 +87,7 @@ WMClient::WMClient(const string &appid, unsigned layer, const string &role)
#if GTEST_ENABLED
string ev = x;
#else
- afb_event_t ev = afb_api_make_event(afbBindingV3root, x.c_str());
+ afb_event ev = afb_daemon_make_event(x.c_str());
#endif
evname2afb_event[x] = ev;
}
@@ -120,45 +103,16 @@ string WMClient::role() const
return this->main_role;
}
-void WMClient::setRole(const string& role)
-{
- this->main_role = role;
-}
-
unsigned WMClient::layerID() const
{
return this->layer;
}
-void WMClient::setLayerID(unsigned id)
-{
- this->layer = id;
-}
-
unsigned WMClient::surfaceID() const
{
return this->surface;
}
-void WMClient::registerSurface(unsigned surface)
-{
- this->surface = surface;
-}
-
-void WMClient::activate()
-{
- if(!this->isActive())
- this->emitActive(true); // emit when state is changed
- this->is_active = true;
-}
-
-void WMClient::deactivate()
-{
- if(this->isActive())
- this->emitActive(false); // emit when state is changed
- this->is_active = false;
-}
-
/**
* Add surface to the client
*
@@ -179,16 +133,6 @@ WMError WMClient::addSurface(unsigned surface)
return (err == ILM_SUCCESS) ? WMError::SUCCESS : WMError::FAIL;
}
-void WMClient::setSurfaceSizeCorrectly()
-{
- this->is_source_set = true;
-}
-
-bool WMClient::isSourceSizeSet()
-{
- return this->is_source_set;
-}
-
bool WMClient::removeSurfaceIfExist(unsigned surface)
{
bool ret = false;
@@ -197,152 +141,131 @@ bool WMClient::removeSurfaceIfExist(unsigned surface)
this->surface = INVALID_SURFACE_ID;
ret = true;
}
- return ret;
-}
-
-bool WMClient::subscribe(afb_req_t req, const string &evname)
-{
- int ret = afb_req_subscribe(req, this->evname2afb_event[evname]);
- if (ret)
+ else
{
- HMI_DEBUG("Failed to subscribe %s", evname.c_str());
- return false;
+ for(auto &x : this->service2surfaces)
+ {
+ if(x.second == surface)
+ {
+ ret = true;
+ string key = x.first;
+ this->service2surfaces.erase(key);
+ this->service2supplier.erase(key);
+ }
+ }
}
- return true;
+ return ret;
}
-void WMClient::emitVisible(bool visible)
+WMError WMClient::setRenderOrder(const vector<string> &order)
{
- // error check
- bool allow_send = false;
- if(visible)
+ WMError ret = WMError::SUCCESS;
+ this->surface_render_order.clear();
+ for(const auto& x : order)
{
- allow_send = afb_event_is_valid(this->evname2afb_event[kVisible]);
- }
- else
- {
- allow_send = afb_event_is_valid(this->evname2afb_event[kInvisible]);
- }
- if(allow_send)
- {
- json_object* j = json_object_new_object();
- json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str()));
- json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str()));
-
- if(visible)
+ unsigned s; // surface
+ if(x == this->role())
{
- afb_event_push(this->evname2afb_event[kVisible], j);
+ s = this->surfaceID();
+ }
+ else if(this->service2surfaces.count(x) != 0)
+ {
+ s = this->service2surfaces[x];
}
else
{
- afb_event_push(this->evname2afb_event[kInvisible], j);
+ ret = WMError::NOT_REGISTERED;
+ break;
}
+ this->surface_render_order.push_back(s);
}
- else
- {
- HMI_ERROR("Failed to send %s", __func__);
- }
-}
-
-void WMClient::emitActive(bool active)
-{
- // error check
- bool allow_send = false;
- if(active)
- {
- allow_send = afb_event_is_valid(this->evname2afb_event[kActive]);
- }
- else
+ if(ret == WMError::SUCCESS)
{
- allow_send = afb_event_is_valid(this->evname2afb_event[kInactive]);
- }
- if(allow_send)
- {
- json_object* j = json_object_new_object();
- json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str()));
- json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str()));
-
- if(active)
+ int count = 0;
+ t_ilm_layer* id_array = new t_ilm_surface[this->surface_render_order.size()];
+ if(id_array == nullptr)
{
- afb_event_push(this->evname2afb_event[kActive], j);
+ HMI_WARNING("short memory");
+ ret = WMError::FAIL;
}
else
{
- afb_event_push(this->evname2afb_event[kInactive], j);
+ for(const auto& i : this->surface_render_order)
+ {
+ id_array[count] = i;
+ ++count;
+ }
+ ilm_layerSetRenderOrder(this->layerID(),
+ id_array, this->surface_render_order.size());
+ delete id_array;
}
}
- else
- {
- HMI_ERROR("Failed to send %s", __func__);
- }
+ return ret;
}
-void WMClient::emitSyncDraw(const string& area, struct rect& r)
+string WMClient::attachTmpServiceSurface(const string& supplier, const string& service_surface)
{
- HMI_NOTICE("trace");
- if(afb_event_is_valid(this->evname2afb_event[kSyncDraw]))
- {
- json_object *j_rect = json_object_new_object();
- json_object_object_add(j_rect, kKeyX, json_object_new_int(r.x));
- json_object_object_add(j_rect, kKeyY, json_object_new_int(r.y));
- json_object_object_add(j_rect, kKeyWidth, json_object_new_int(r.w));
- json_object_object_add(j_rect, kKeyHeight, json_object_new_int(r.h));
-
- json_object* j = json_object_new_object();
- json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str()));
- json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str()));
- json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area.c_str()));
- json_object_object_add(j, kKeyArea, json_object_new_string(this->role().c_str()));
+ string uuid;
+ uuid_t u;
+ char out[37]; // uuid is 36 characters
+ uuid_generate_random(u);
+ uuid_unparse(u, out);
+ uuid = out;
+ this->service2supplier.emplace(service_surface, supplier);
+ return uuid;
+}
- json_object_object_add(j, kKeyDrawingRect, j_rect);
- afb_event_push(this->evname2afb_event[kSyncDraw], j);
- }
- else
+WMError WMClient::attachServiceSurface(const string& service_surface, unsigned surface)
+{
+ WMError ret = WMError::NOT_REGISTERED;
+ if(this->service2supplier.count(service_surface) != 0)
{
- HMI_ERROR("Failed to send %s", __func__);
+ this->service2surfaces.emplace(service_surface, surface);
+ ret = WMError::SUCCESS;
}
+ return ret;
}
-void WMClient::emitFlushDraw()
+#if GTEST_ENABLED
+bool WMClient::subscribe(afb_req req, const string &evname)
{
- if(afb_event_is_valid(this->evname2afb_event[kFlushDraw]))
- {
- json_object* j = json_object_new_object();
- json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str()));
- json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str()));
- afb_event_push(this->evname2afb_event[kFlushDraw], nullptr);
+ if(evname != kKeyError){
+ HMI_DEBUG("error is only enabeled for now");
+ return false;
}
- else
+ int ret = afb_req_subscribe(req, this->evname2afb_event[evname]);
+ if (ret)
{
- HMI_ERROR("Failed to send %s", __func__);
+ HMI_DEBUG("Failed to subscribe %s", evname.c_str());
+ return false;
}
+ return true;
}
-void WMClient::emitError(WMError error)
+void WMClient::emitError(WM_CLIENT_ERROR_EVENT ev)
{
if (!afb_event_is_valid(this->evname2afb_event[kKeyError])){
HMI_ERROR("event err is not valid");
return;
}
json_object *j = json_object_new_object();
- json_object_object_add(j, kKeyError, json_object_new_int(error));
- json_object_object_add(j, kKeyErrorDesc, json_object_new_string(errorDescription(error)));
- HMI_DEBUG("error: %d, description:%s", error, errorDescription(error));
+ json_object_object_add(j, kKeyError, json_object_new_int(ev));
+ json_object_object_add(j, kKeyErrorDesc, json_object_new_string(kErrorDescription[ev].c_str()));
+ HMI_DEBUG("error: %d, description:%s", ev, kErrorDescription[ev].c_str());
+
int ret = afb_event_push(this->evname2afb_event[kKeyError], j);
if (ret != 0)
{
HMI_DEBUG("afb_event_push failed: %m");
}
}
+#endif
void WMClient::dumpInfo()
{
DUMP("APPID : %s", id.c_str());
DUMP(" LAYER : %d", layer);
- for (const auto &x : this->role2surface)
- {
- DUMP(" ROLE : %s , SURFACE : %d", x.first.c_str(), x.second);
- }
+ DUMP(" ROLE : %s , SURFACE : %d", main_role.c_str(), surface);
}
} // namespace wm \ No newline at end of file
diff --git a/src/wm_client.hpp b/src/wm_client.hpp
index 7df4dea..fc171f4 100644
--- a/src/wm_client.hpp
+++ b/src/wm_client.hpp
@@ -20,17 +20,22 @@
#include <vector>
#include <string>
#include <unordered_map>
-#include "util.hpp"
#include "wm_error.hpp"
extern "C"
{
+#define AFB_BINDING_VERSION 2
#include <afb/afb-binding.h>
}
namespace wm
{
+enum WM_CLIENT_ERROR_EVENT
+{
+ UNKNOWN_ERROR
+};
+
class WMClient
{
public:
@@ -45,47 +50,43 @@ class WMClient
std::string appID() const;
std::string role() const;
- void setRole(const std::string& role);
unsigned layerID() const;
- void setLayerID(unsigned id);
unsigned surfaceID() const;
- void registerSurface(unsigned surface);
- void activate();
- void deactivate();
- std::string area() const {return this->app_area;};
- void setArea(const std::string area) {this->app_area = area;}
+ // void setRole(const std::string& role);
+ // void appendRole(const std::string& role);
WMError addSurface(unsigned surface);
- bool isSourceSizeSet();
- void setSurfaceSizeCorrectly();
- bool isActive() { return this->is_active;}
bool removeSurfaceIfExist(unsigned surface);
+ // bool removeRole(const std::string& role);
+ std::vector<unsigned> renderOrder() const;
+ WMError setRenderOrder(const std::vector<std::string>& order);
+ std::string attachTmpServiceSurface(const std::string& from, const std::string& service_surface);
+ WMError attachServiceSurface(const std::string& service_surface, unsigned surface);
- bool subscribe(afb_req_t req, const std::string &event_name);
- void emitActive(bool active);
- void emitVisible(bool visible);
- void emitSyncDraw(const std::string& area, struct rect& r);
- void emitFlushDraw();
- void emitError(WMError error);
+#if GTEST_ENABLED
+ bool subscribe(afb_req req, const std::string &event_name);
+ void emitError(WM_CLIENT_ERROR_EVENT ev);
+#endif
void dumpInfo();
private:
std::string id;
unsigned layer;
- bool is_source_set;
- bool is_active;
std::string main_role;
- std::string app_area;
+ std::string area;
unsigned surface; // currently, main application has only one surface.
//std::vector<std::string> role_list;
+ std::vector<unsigned> surface_render_order;
+ std::unordered_map<std::string, unsigned> service2surfaces;
std::unordered_map<std::string, unsigned> role2surface;
+ std::unordered_map<std::string, std::string> service2supplier;
#if GTEST_ENABLED
// This is for unit test. afb_make_event occurs sig11 if call not in afb-binding
std::unordered_map<std::string, std::string> evname2afb_event;
#else
- std::unordered_map<std::string, afb_event_t> evname2afb_event;
+ std::unordered_map<std::string, struct afb_event> evname2afb_event;
#endif
};
} // namespace wm
-#endif
+#endif \ No newline at end of file
diff --git a/src/wm_connection.cpp b/src/wm_connection.cpp
new file mode 100644
index 0000000..af970f5
--- /dev/null
+++ b/src/wm_connection.cpp
@@ -0,0 +1,845 @@
+/*
+ * Copyright (c) 2017 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 "wm_connection.hpp"
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "json_helper.hpp"
+#include "util.hpp"
+
+extern "C"
+{
+#include <afb/afb-binding.h>
+#include <systemd/sd-event.h>
+}
+
+
+/**
+ * namespace wm
+ */
+namespace wm
+{
+
+
+namespace
+{
+
+static const char kPathConnectionConfigFile[] = "/etc/hmi-config/connection.json";
+static const char kPathTimeoutConfigFile[] = "/etc/timeout.json";
+static const char kDefaultIpAddr[] = "192.168.10.10";
+static const int kDefaultPort = 4000;
+static const uint64_t kDefaultTimes = 60000;
+static const uint64_t kDefaultSleep = 50;
+static struct sd_event_source *g_limit_timer_src = nullptr;
+static struct sd_event_source *g_sleep_timer_src = nullptr;
+
+static int setTimer(sd_event_source **src, uint64_t usec, void* handler, void* data)
+{
+ int ret = sd_event_add_time(afb_daemon_get_event_loop(), src,
+ CLOCK_BOOTTIME, usec, 1, (sd_event_time_handler_t)handler, data);
+
+ if (ret < 0)
+ {
+ HMI_ERROR("Colud't set timer");
+ }
+
+ return ret;
+}
+
+static void updateTimer(sd_event_source *src, uint64_t usec)
+{
+ sd_event_source_set_time(src, usec);
+ sd_event_source_set_enabled(src, SD_EVENT_ONESHOT);
+}
+
+static void stopEvent(sd_event_source *src)
+{
+ int ret = sd_event_source_set_enabled(src, SD_EVENT_OFF);
+ if (ret < 0)
+ {
+ HMI_ERROR("Not set SD_EVENT_OFF (%s)", strerror(-ret));
+ }
+ sd_event_source_unref(src);
+}
+
+static int onIoEventReceive(sd_event_source *src, int fd, uint32_t revents, void * data)
+{
+ WMConnection *p_wmcon = (WMConnection*)data;
+
+ json_object *j_out[10];
+ int j_cnt;
+ int ret = p_wmcon->receive(j_out, &j_cnt, fd);
+ if (0 > ret)
+ {
+ return 0;
+ }
+
+ for(int i = 0; i < j_cnt; i++)
+ {
+ const char* rq = jh::getStringFromJson(j_out[i], "req");
+ const char* id = jh::getStringFromJson(j_out[i], "appid");
+ const char* dn = jh::getStringFromJson(j_out[i], "drawing_name");
+ const char* da = jh::getStringFromJson(j_out[i], "drawing_area");
+
+ HMI_DEBUG("req:%s appid:%s, drawing_name:%s, drawing_area:%s", rq, id, dn, da);
+
+ // Callback
+ p_wmcon->callOnReceivedHandler(j_out[i]);
+ }
+
+ return 0;
+}
+
+static int onIoEventAccept(sd_event_source *src, int fd, uint32_t revents, void * data)
+{
+ WMConnection *p_wmcon = (WMConnection*)data;
+
+ p_wmcon->serverAccept(fd);
+
+ return 0;
+}
+
+static int onIoEventConnected(sd_event_source *src, int fd, uint32_t revents, void * data)
+{
+ WMConnection *p_wmcon = (WMConnection*)data;
+
+ int ret = p_wmcon->connectedToServer(fd);
+
+ if (ret == 0)
+ {
+ stopEvent(src);
+
+ ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
+ fd, EPOLLIN, onIoEventReceive, p_wmcon);
+ }
+
+ return ret;
+}
+
+static int sleepTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
+{
+ WMConnection *p_wmcon = (WMConnection*)userdata;
+
+ int ret = p_wmcon->connectToEcu();
+
+ return ret;
+}
+
+static void limitTimerHandler(sd_event_source *s, uint64_t usec, void *userdata)
+{
+ WMConnection *p_wmcon = (WMConnection*)userdata;
+
+ p_wmcon->connectionTimeLimit();
+}
+
+} // namespace
+
+WMConnection::WMConnection()
+{
+ this->end_init = false;
+
+ //Load timeout config file
+ this->loadTimeoutConfigFile();
+
+ // Load connection config file
+ this->loadConnectionConfigFile();
+
+ // TODO: ECU name should be decide by config file
+ this->ecu_name = this->mode;
+}
+
+int WMConnection::initialize()
+{
+ int ret;
+ uint64_t sleepTime, limitTime;
+
+ // Initialize for Master/Slave
+ ret = this->initializeServer();
+
+ sleepTime = getNextTimerTime(this->sleep);
+
+ if (sleepTime <= 0)
+ {
+ HMI_ERROR("Cloud't get Next Timer");
+ goto connection_init_error;
+ }
+
+ ret = setTimer(&g_sleep_timer_src, sleepTime, (void *)sleepTimerHandler, this);
+ sd_event_source_set_enabled(g_sleep_timer_src, SD_EVENT_OFF);
+
+ limitTime = getNextTimerTime(this->times);
+
+ if (limitTime <= 0)
+ {
+ HMI_ERROR("Cloud't get Next Timer");
+ goto connection_init_error;
+ }
+
+ ret = setTimer(&g_limit_timer_src, limitTime, (void *)limitTimerHandler, this);
+
+ this->connectToEcu();
+
+ return ret;
+
+
+connection_init_error:
+ HMI_ERROR("Connection Initialize Failed");
+ return -1;
+}
+
+void WMConnection::registerCallback(ReceivedHandler on_received)
+{
+ this->onReceived = on_received;
+}
+
+int WMConnection::sendRequest(char const *req, char const *appid,
+ char const *drawing_name, char const *drawing_area)
+{
+ int ret;
+ json_object *j_obj = json_object_new_object();
+ json_object_object_add(j_obj, "req", json_object_new_string(req));
+ json_object_object_add(j_obj, "appid", json_object_new_string(appid));
+ json_object_object_add(j_obj, "drawing_name", json_object_new_string(drawing_name));
+ json_object_object_add(j_obj, "drawing_area", json_object_new_string(drawing_area));
+
+ std::string ecu_name = getAppIdToEcuName(appid);
+
+ HMI_DEBUG("send ecu_name %s", ecu_name.c_str());
+
+ ret = this->send(j_obj, ecu_name);
+
+ json_object_put(j_obj);
+
+ return ret;
+}
+
+int WMConnection::send(struct json_object* j_in, std::string ecu_name)
+{
+ SocketInfo *socketData = &this->wm_socket[ecu_name];
+
+ // Convert json_object to string to send
+ const char *buf = json_object_to_json_string(j_in);
+ if (nullptr == buf)
+ {
+ HMI_ERROR("Failed to convert json_object to string");
+ return -1;
+ }
+
+ int len = strlen(buf);
+
+ HMI_DEBUG("Send data(len:%d): %s", len, buf);
+
+ int n = write(socketData->connectedSocket(), buf, len);
+ if(0 > n)
+ {
+ HMI_ERROR("Failed to send data (%s)", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+bool WMConnection::isRemoteArea(const char* area)
+{
+ if (nullptr == area)
+ {
+ return false;
+ }
+
+ std::string str_area = std::string(area);
+ if ("" == str_area)
+ {
+ return false;
+ }
+
+ std::vector<std::string> elements;
+ elements = parseString(str_area, '.');
+
+ for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
+ {
+ if (itr->first == elements[0])
+ {
+ if (itr->first != this->ecu_name)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool WMConnection::isConnecting(std::string ecu_name)
+{
+ return (0 > this->wm_socket[ecu_name].connectedSocket()) ? false : true;
+}
+
+bool WMConnection::isConnectionMode()
+{
+ return (Mode_Connection == this->wm_mode) ? true : false;
+}
+
+std::string WMConnection::parseMasterArea(const char* area)
+{
+ std::string ret_area = "";
+ std::vector<std::string> elements;
+ elements = parseString(std::string(area), '.');
+
+ if ("master" != elements[0])
+ {
+ return std::string(area);
+ }
+
+ for (auto itr = (elements.begin() + 1); itr != elements.end(); ++itr)
+ {
+ ret_area += *itr;
+
+ if ((elements.end() - 1) != itr)
+ {
+ ret_area += ".";
+ }
+ }
+ return ret_area;
+}
+
+bool WMConnection::isSyncDrawingForRemote(const char* appid)
+{
+ if (std::string(appid) == this->syndDrawingAppId)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void WMConnection::startSyncDrawForRemote(const char* appid)
+{
+ this->syndDrawingAppId = std::string(appid);
+}
+
+void WMConnection::finishSyncDrawForRemote(const char* appid)
+{
+ if (std::string(appid) == this->syndDrawingAppId)
+ {
+ this->syndDrawingAppId = "";
+ }
+}
+
+std::string WMConnection::getAreaToEcuName(const char* area)
+{
+ std::string result;
+ std::string str_area = std::string(area);
+
+ if (str_area.find('.') != std::string::npos)
+ {
+ std::vector<std::string> elements;
+ elements = parseString(str_area, '.');
+ result = elements[0];
+ }
+ else
+ {
+ result = str_area;
+ }
+
+ return result;
+}
+
+std::string WMConnection::getSocketToEcuName(int socket)
+{
+ for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
+ {
+ if (socket == itr->second.connectedSocket())
+ {
+ return itr->first;
+ }
+ }
+
+ return "";
+}
+
+std::string WMConnection::getMySocketToEcuName(int socket)
+{
+ for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
+ {
+ if (socket == itr->second.mySocket())
+ {
+ return itr->first;
+ }
+ }
+
+ return "";
+}
+
+std::string WMConnection::getAppIdToEcuName(std::string appid)
+{
+ if (appid2ecuName.count(appid) == 1)
+ {
+ return this->appid2ecuName[appid];
+ }
+ else
+ {
+ return "";
+ }
+}
+
+std::string WMConnection::getIpToEcuName(std::string ip)
+{
+ for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
+ {
+ if (ip == itr->second.ip())
+ {
+ return itr->first;
+ }
+ }
+
+ return "";
+}
+
+void WMConnection::setAppIdToEcuName(std::string appid, std::string ecu_name)
+{
+ this->appid2ecuName[appid] = ecu_name;
+}
+
+void WMConnection::setAppIdToReceivedEcuName(std::string appid)
+{
+ this->appid2ecuName[appid] = received_ecu_name;
+}
+
+std::string WMConnection::getEcuName()
+{
+ return this->ecu_name;
+}
+
+bool WMConnection::getEndInit()
+{
+ return this->end_init;
+}
+
+void WMConnection::callOnReceivedHandler(json_object *j_out)
+{
+ this->onReceived(j_out);
+}
+
+int WMConnection::initializeServer()
+{
+ int ret = 0;
+ struct sockaddr_in addr;
+
+ SocketInfo *socketData = &this->wm_socket[this->ecu_name];
+
+ // Create socket
+ socketData->setMySocket(socket(AF_INET, SOCK_STREAM, 0));
+ if (0 > socketData->mySocket())
+ {
+ HMI_ERROR("Failed to create socket (%s)", strerror(errno));
+ return -1;
+ }
+
+ socketData->setConnectedSocket(socketData->mySocket());
+
+ // Bind socket
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(socketData->wmPort());
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ ret = bind(socketData->mySocket(), (struct sockaddr *)&addr, sizeof(addr));
+ if (0 > ret)
+ {
+ HMI_ERROR("Failed to bind socket (%s)", strerror(errno));
+ return -1;
+ }
+
+ // Listen connection
+ ret = listen(socketData->mySocket(), 1);
+ if (0 > ret)
+ {
+ HMI_ERROR("Failed to listen connection (%s)", strerror(errno));
+ return -1;
+ }
+
+ // Register callback to accept connection
+ ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
+ socketData->mySocket(), EPOLLIN,
+ onIoEventAccept, this);
+ if (0 > ret)
+ {
+ HMI_ERROR("Failed to add I/O event accept(%s)", strerror(-ret));
+ return -1;
+ }
+
+ return ret;
+}
+
+int WMConnection::initializeClient(std::string ecu_name)
+{
+ SocketInfo *socketData = &this->wm_socket[ecu_name];
+
+ if (socketData->mySocket() != -1)
+ {
+ close(socketData->mySocket());
+ }
+
+ // Create socket
+ int my_socket = socket(AF_INET, SOCK_STREAM, 0);
+ if (0 > my_socket)
+ {
+ HMI_ERROR("Failed to create socket (%s)", strerror(errno));
+ return -1;
+ }
+
+ socketData->setMySocket(my_socket);
+
+ return 0;
+}
+
+int WMConnection::connectToEcu()
+{
+ int cnt = 0;
+
+ HMI_DEBUG("Start Connection");
+
+ if (this->wm_socket.empty())
+ {
+ HMI_DEBUG("Connection destination is not written to connection.json");
+ stopEvent(g_limit_timer_src);
+ stopEvent(g_sleep_timer_src);
+
+ this->end_init = true;
+ this->wm_mode = Mode_Standalone;
+
+ return 0;
+ }
+
+ for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
+ {
+ std::string ecu_name = itr->first;
+ HMI_DEBUG("ECU Names %s", ecu_name.c_str());
+
+ if (itr->second.connectedSocket() != -1 || !itr->second.masterMode())
+ {
+ cnt++;
+ HMI_DEBUG("Already Connected");
+ continue;
+ }
+
+ if (itr->second.masterMode())
+ {
+ HMI_DEBUG("Try Connection");
+ connectToServer(ecu_name);
+ }
+ }
+
+ if (cnt == (int)this->wm_socket.size())
+ {
+ HMI_DEBUG("All Connected!!");
+
+ stopEvent(g_sleep_timer_src);
+ stopEvent(g_limit_timer_src);
+
+ this->end_init = true;
+ this->wm_mode = Mode_Connection;
+
+ return 0;
+ }
+
+ uint64_t sleepTime = getNextTimerTime(this->sleep);
+ updateTimer(g_sleep_timer_src, sleepTime);
+
+ return 0;
+}
+
+void WMConnection::connectionTimeLimit()
+{
+ HMI_DEBUG("Time Limit");
+
+ stopEvent(g_sleep_timer_src);
+ stopEvent(g_limit_timer_src);
+
+ this->wm_socket[this->ecu_name].setConnectedSocket(-1);
+ this->wm_mode = Mode_Standalone;
+
+ for (auto itr = this->wm_socket.begin(); itr != this->wm_socket.end(); ++itr)
+ {
+ if (itr->second.connectedSocket() != -1)
+ {
+ HMI_DEBUG("Connection Mode");
+ this->wm_mode = Mode_Connection;
+ }
+ else
+ {
+ close(itr->second.mySocket());
+ }
+ }
+
+ if (this->wm_mode == Mode_Standalone)
+ {
+ close(this->wm_socket[this->ecu_name].mySocket());
+ }
+
+ this->end_init = true;
+}
+
+int WMConnection::connectToServer(std::string ecu_name)
+{
+ int ret = 0;
+ struct sockaddr_in addr;
+
+ this->initializeClient(ecu_name);
+
+ SocketInfo *socketData = &wm_socket[ecu_name];
+
+ // Connect to master
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(socketData->wmPort());
+ addr.sin_addr.s_addr = inet_addr(socketData->ip().c_str());
+
+ connect(socketData->mySocket(), (struct sockaddr *)&addr, sizeof(addr));
+
+ ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
+ socketData->mySocket(), EPOLLOUT,
+ onIoEventConnected, this);
+
+ if (0 > ret)
+ {
+ HMI_ERROR("Failed to add I/O event receive(%s)", strerror(-ret));
+ return -1;
+ }
+
+ return ret;
+}
+
+int WMConnection::connectedToServer(int socket)
+{
+ int ret;
+
+ struct sockaddr_in addr;
+ socklen_t addr_len = sizeof(addr);
+
+ std::string ecu_name = getMySocketToEcuName(socket);
+
+ ret = getpeername(socket, (struct sockaddr*)&addr, &addr_len);
+
+ if (ret != 0)
+ {
+ HMI_DEBUG("Failed to connect %s (%s)", ecu_name.c_str(), strerror(errno));
+ return -1;
+ }
+
+ HMI_DEBUG("Connected to %s", ecu_name.c_str());
+
+ SocketInfo *socketData = &this->wm_socket[ecu_name];
+
+ // Store connected socket
+ socketData->setConnectedSocket(socket);
+
+ return 0;
+}
+
+int WMConnection::serverAccept(int socket)
+{
+ struct sockaddr_in addr;
+
+ // Accept connection
+ socklen_t len = sizeof(addr);
+ int my_socket = this->wm_socket[this->getEcuName()].mySocket();
+ int connected_socket = accept(my_socket, (struct sockaddr *)&addr, &len);
+ if (0 > connected_socket)
+ {
+ HMI_ERROR("Failed to accept connection (%s)", strerror(errno));
+ return -1;
+ }
+
+ std::string ip = inet_ntoa(addr.sin_addr);
+ std::string ecu_name = getIpToEcuName(ip);
+
+ SocketInfo *socketData = &this->wm_socket[ecu_name];
+
+ // Store connected socket
+ socketData->setConnectedSocket(connected_socket);
+
+ // Register callback to receive
+ int ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
+ connected_socket, EPOLLIN,
+ onIoEventReceive, this);
+ if (0 > ret)
+ {
+ HMI_ERROR("Failed to add I/O event receive(%s)", strerror(-ret));
+ return -1;
+ }
+
+ return 0;
+}
+
+int WMConnection::receive(json_object** j_out, int *j_cnt, int socket)
+{
+ char buf[1024] = {};
+ int n;
+
+ n = read(socket, buf, sizeof(buf));
+ if(0 > n)
+ {
+ HMI_ERROR("Failed to receive data (%s)", strerror(errno));
+ return -1;
+ }
+
+ HMI_DEBUG("Received data length: %d", n);
+ HMI_DEBUG("Received data: %s", buf);
+
+ // Parse received data
+ struct json_tokener *tokener = json_tokener_new();
+ int cnt = 0;
+
+ while (n >= tokener->char_offset)
+ {
+ j_out[cnt] = json_tokener_parse_ex(tokener, &buf[tokener->char_offset], n);
+
+ if (nullptr == j_out[cnt])
+ {
+ break;
+ }
+
+ cnt++;
+ }
+
+ *j_cnt = cnt;
+ json_tokener_free(tokener);
+
+ this->received_ecu_name = this->getSocketToEcuName(socket);
+ HMI_DEBUG("received ecu name %s", this->received_ecu_name.c_str());
+
+ return 0;
+}
+
+int WMConnection::loadTimeoutConfigFile()
+{
+ // Get afm application installed dir
+ char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
+ if (!afm_app_install_dir)
+ {
+ HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
+ }
+ std::string path = std::string(afm_app_install_dir) + std::string(kPathTimeoutConfigFile);
+
+ // Load connection config file
+ 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 timeout", path.c_str());
+ this->times = kDefaultTimes;
+ this->sleep = kDefaultSleep;
+ return 0;
+ }
+ HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
+
+ int times = jh::getIntFromJson(json_obj, "times");
+ this->times = (0 != times) ? times : kDefaultTimes;
+
+ int sleep = jh::getIntFromJson(json_obj, "sleep");
+ this->sleep = (0 != sleep) ? sleep : kDefaultSleep;
+
+ // Release json_object
+ json_object_put(json_obj);
+
+ return 0;
+}
+
+int WMConnection::loadConnectionConfigFile()
+{
+ std::string path = std::string(kPathConnectionConfigFile);
+
+ // Load connection config file
+ json_object *json_obj, *json_cfg;
+ int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
+ if (0 > ret)
+ {
+ HMI_ERROR("Could not open %s, so use default mode \"slave\"", kPathConnectionConfigFile);
+ this->wm_socket["slave"] = SocketInfo("slave", kDefaultIpAddr, kDefaultPort, false);
+ return 0;
+ }
+ HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
+
+ const char* screen_name = jh::getStringFromJson(json_obj, "screen_name");
+ this->mode = (nullptr != screen_name) ? screen_name : "slave";
+
+ int wm_port = jh::getIntFromJson(json_obj, "wm_port");
+
+ this->wm_socket[screen_name] = SocketInfo(screen_name, "", wm_port, true);
+
+ // Check
+ HMI_DEBUG("screen_name:%s wm_port:%d", screen_name, wm_port);
+
+ if (!json_object_object_get_ex(json_obj, "connections", &json_cfg))
+ {
+ HMI_ERROR("connection.json Parse Error!!");
+ return 0;
+ }
+
+ int len = json_object_array_length(json_cfg);
+
+ for (int i = 0; i < len; i++)
+ {
+ json_object *json_conn = json_object_array_get_idx(json_cfg, i);
+
+ std::string screen_name = jh::getStringFromJson(json_conn, "screen_name");
+ std::string ip = jh::getStringFromJson(json_conn, "ip");
+ int wm_port = jh::getIntFromJson(json_conn, "wm_port");
+ bool master_mode = jh::getBoolFromJson(json_conn, "master_mode");
+
+ this->wm_socket[screen_name] = SocketInfo(screen_name, ip, wm_port, master_mode);
+
+ HMI_DEBUG("screen_name:%s ip:%s port:%d server_mode:%s", screen_name.c_str(),
+ ip.c_str(), wm_port, (master_mode ? "true" : "false"));
+ }
+
+ // Release json_object
+ json_object_put(json_obj);
+
+ return 0;
+}
+
+uint64_t WMConnection::getNextTimerTime(uint64_t msec)
+{
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_BOOTTIME, &ts) != 0)
+ {
+ HMI_ERROR("Could't set time (clock_gettime() returns with error");
+ return -1;
+ }
+
+ uint64_t timer_nsec = ((ts.tv_sec * 1000000000ULL) + (ts.tv_nsec) + (msec * 1000000));
+
+ if (!timer_nsec)
+ {
+ HMI_ERROR("Second is 0");
+ return -1;
+ }
+
+ return timer_nsec / 1000;
+}
+
+} // namespace wm
diff --git a/src/wm_connection.hpp b/src/wm_connection.hpp
new file mode 100644
index 0000000..91f870e
--- /dev/null
+++ b/src/wm_connection.hpp
@@ -0,0 +1,117 @@
+/*
+ * Insert Copyright if needed.
+ */
+
+#ifndef WM_CONNECTION_HPP
+#define WM_CONNECTION_HPP
+
+#include <functional>
+#include <unordered_map>
+
+struct json_object;
+
+namespace wm
+{
+
+class SocketInfo
+{
+ public:
+ SocketInfo() {};
+ SocketInfo(std::string screen_name, std::string ip, int wm_port, bool master_mode) : _screen_name(screen_name),
+ _ip(ip), _wm_port(wm_port), _master_mode(master_mode){}
+ std::string screenName() const { return _screen_name; }
+ std::string ip() const { return _ip; }
+ int wmPort() const { return _wm_port; }
+ bool masterMode() const { return _master_mode; }
+ int mySocket() const { return _my_socket; }
+ int connectedSocket() const { return _connected_socket; }
+ void setMySocket(int socket) { this->_my_socket = socket; }
+ void setConnectedSocket(int socket) { this->_connected_socket = socket; }
+
+ private:
+ std::string _screen_name;
+ std::string _ip;
+ int _wm_port;
+ bool _master_mode;
+ int _my_socket = -1;
+ int _connected_socket = -1;
+};
+
+class WMConnection
+{
+ public:
+ WMConnection();
+ ~WMConnection() = default;
+
+ using ReceivedHandler = std::function<void(json_object* j_out)>;
+
+ enum ModeType
+ {
+ Mode_Standalone = 0,
+ Mode_Connection,
+ };
+
+ int initialize();
+ void registerCallback(ReceivedHandler on_received);
+ int sendRequest(char const *req, char const *appid,
+ char const *drawing_name, char const *drawing_area);
+ bool isRemoteArea(const char* area);
+ bool isConnecting(std::string ecu_name);
+ bool isConnectionMode();
+ std::string parseMasterArea(const char* area);
+ bool isSyncDrawingForRemote(const char* role);
+ void startSyncDrawForRemote(const char* role);
+ void finishSyncDrawForRemote(const char* role);
+ int getMySocket();
+ int getConnectedSocket();
+ void setConnectedSocket(int connected_socket);
+ std::string getAreaToEcuName(const char* area);
+ std::string getSocketToEcuName(int socket);
+ std::string getMySocketToEcuName(int socket);
+ std::string getAppIdToEcuName(std::string appid);
+ std::string getIpToEcuName(std::string ip);
+ std::string getEcuName();
+ bool getEndInit();
+ void setAppIdToEcuName(std::string appid, std::string ecu_name);
+ void setAppIdToReceivedEcuName(std::string appid);
+ void callOnReceivedHandler(json_object *j_out);
+ int connectToEcu();
+ int connectToServer(std::string ecu_name);
+ int connectedToServer(int socket);
+ void connectionTimeLimit();
+
+ int serverAccept(int socket);
+ int receive(json_object** j_out, int *j_cnt, int socket);
+
+ private:
+ std::string mode;
+ std::string received_ecu_name;
+ ReceivedHandler onReceived;
+ std::string syndDrawingAppId;
+
+ std::string ecu_name;
+ std::string received_ecu;
+
+ uint64_t times;
+ uint64_t sleep;
+
+ bool end_init;
+ ModeType wm_mode;
+
+ std::unordered_map<std::string, SocketInfo> wm_socket;
+ std::unordered_map<std::string, std::string> appid2ecuName;
+
+ int initializeServer();
+ int initializeClient(std::string ecu_name);
+ int loadTimeoutConfigFile();
+ int loadConnectionConfigFile();
+
+ int send(json_object* j_in, std::string ecu_name);
+
+ uint64_t getNextTimerTime(uint64_t msec);
+};
+
+} // namespace wm
+
+#endif // WM_CONNECTION_HPP
+
diff --git a/src/wm_layer.cpp b/src/wm_layer.cpp
index 4eceb43..e1454f8 100644
--- a/src/wm_layer.cpp
+++ b/src/wm_layer.cpp
@@ -66,6 +66,12 @@ void LayerState::removeLayer(unsigned layer)
this->render_order.erase(fwd_itr, this->render_order.end());
}
+bool LayerState::hasLayer(unsigned layer)
+{
+ auto itr = std::find(this->render_order.begin(), this->render_order.end(), layer);
+ return (itr != this->render_order.end()) ? true : false;
+}
+
void LayerState::attachAppToArea(const string& app, const string& area)
{
this->area2appid[area] = app;
@@ -96,6 +102,7 @@ WMLayer::WMLayer(json_object* j, unsigned wm_layer_id) : tmp_state(), state(), w
this->role_list = jh::getStringFromJson(j, "role");
this->id_begin = static_cast<unsigned>(jh::getIntFromJson(j, "id_range_begin"));
this->id_end = static_cast<unsigned>(jh::getIntFromJson(j, "id_range_end"));
+ this->screen = jh::getIntFromJson(j, "screen"); // screen is not defined in layers.json, screen is set to 0
if (name.empty())
{
@@ -183,6 +190,11 @@ void WMLayer::removeLayerFromState(unsigned layer)
this->tmp_state.removeLayer(layer);
}
+bool WMLayer::hasLayerFromState(unsigned layer)
+{
+ this->tmp_state.hasLayer(layer);
+}
+
void WMLayer::attachAppToArea(const string& app, const string& area)
{
this->tmp_state.attachAppToArea(app, area);
@@ -250,7 +262,7 @@ void WMLayer::undo()
void WMLayer::dump()
{
DUMP("===== wm layer status =====");
- DUMP("Layer :%s", this->name.c_str());
+ DUMP("Layer :%s on screen %d", this->name.c_str(), this->screen);
DUMP(" [Current]");
this->state.dump();
DUMP(" [To be]");
diff --git a/src/wm_layer.hpp b/src/wm_layer.hpp
index 97cf8a8..7da432c 100644
--- a/src/wm_layer.hpp
+++ b/src/wm_layer.hpp
@@ -38,6 +38,7 @@ class LayerState
const std::vector<unsigned> getIviIdList();
void addLayer(unsigned layer);
void removeLayer(unsigned layer);
+ bool hasLayer(unsigned layer);
void attachAppToArea(const std::string& app, const std::string& area);
// Debug
@@ -59,6 +60,7 @@ class WMLayer
unsigned idBegin() { return this->id_begin; }
unsigned idEnd() { return this->id_end; }
unsigned getWMLayerID() { return this->wm_layer_id; }
+ unsigned getScreenID() { return this->screen; }
const std::string& layerName();
void appendArea(const std::string& area);
LayerState& getLayerState() { return tmp_state; }
@@ -69,6 +71,7 @@ class WMLayer
// Manipulation
void addLayerToState(unsigned layer);
void removeLayerFromState(unsigned layer);
+ bool hasLayerFromState(unsigned layer);
void attachAppToArea(const std::string& app, const std::string& area);
std::string attachedApp(const std::string& area);
void update();
@@ -88,6 +91,7 @@ class WMLayer
std::string role_list;
std::vector<std::string> area_list;
std::vector<unsigned> id_list;
+ unsigned screen;
unsigned id_begin;
unsigned id_end;
};
diff --git a/src/wm_layer_control.cpp b/src/wm_layer_control.cpp
index c5c7913..8086fd3 100644
--- a/src/wm_layer_control.cpp
+++ b/src/wm_layer_control.cpp
@@ -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.
@@ -22,10 +21,22 @@
#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 REMOTE_LAYER "Remote"
+#define REMOTE_LAYER_RSE1 "RemoteRSE1"
+#define REMOTE_LAYER_RSE2 "RemoteRSE2"
+#define REMOTE_LAYER_HUD "RemoteHUD"
+#define REMOTE_LAYER_HUD_UL "RemoteHUDUpperLeft"
+#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 +68,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 +89,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 +130,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 +169,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 +192,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 +230,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 +248,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 +256,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)
{
- l->update();
+ this->undoUpdate();
+ return WMError::FAIL;
}
+ else
+ {
+ 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,9 +345,34 @@ 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.c_str());
+ HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path);
json_object *json_obj, *json_cfg;
int ret = jh::inputJsonFilie(path.c_str(), &json_obj);
@@ -310,9 +404,9 @@ WMError LayerControl::loadLayerSetting(const string &path)
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 +416,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;
}
- HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));
+ else
+ {
+ json_ecu = nullptr;
+ }
+ }
- 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 +535,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 +551,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 +592,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)
+ {
+ this->moveRemote(action.client->layerID(), action.area);
+ ret = this->makeVisible(action.client);
+ }
+ else if (action.visible == TaskVisible::REMOTE_INVISIBLE)
+ {
+ this->moveLocal(action.client->layerID());
+ ret = this->makeInvisible(action.client);
+ }
+ else // TaskVisible::REQ_REMOTE_VISIBLE || TaskVisible::REQ_REMOTE_INVISIBLE
+ {
+ // Visibility is not change
+ ret = WMError::SUCCESS;
+ }
+
return ret;
}
@@ -519,6 +687,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 +853,73 @@ 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;
+
+ if (area == AREA_NAME_RSE1)
+ remote_layer = REMOTE_LAYER_RSE1;
+ else if (area == AREA_NAME_RSE2)
+ remote_layer = REMOTE_LAYER_RSE2;
+ else if (area == AREA_NAME_HUD)
+ remote_layer = REMOTE_LAYER_HUD;
+ else if (area == AREA_NAME_HUD_UL)
+ remote_layer = REMOTE_LAYER_HUD_UL;
+ else
+ remote_layer = REMOTE_LAYER;
+
+ 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;
+ }
+ remote->addLayerToState(layer);
+ auto wm_layer = this->getWMLayer(layer);
+ wm_layer->removeLayerFromState(layer);
+ wm_layer->dump();
+ remote->dump();
+ ret = true;
+ }
+
+ return ret;
+}
+
+bool LayerControl::moveLocal(unsigned layer)
+{
+ bool ret = false;
+
+ 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;
+}
+
+bool LayerControl::hasRemoteLayer(unsigned layer)
+{
+ bool ret = false;
+
+ auto remote = this->getWMLayer(REMOTE_LAYER);
+ if(remote != nullptr)
+ {
+ ret = remote->hasLayerFromState(layer);
+ }
+
+ return ret;
+}
+
} // namespace wm
diff --git a/src/wm_layer_control.hpp b/src/wm_layer_control.hpp
index 68acd66..6eb7a76 100644
--- a/src/wm_layer_control.hpp
+++ b/src/wm_layer_control.hpp
@@ -27,14 +27,24 @@ namespace wm {
class Screen {
public:
- Screen(unsigned w, unsigned h) : _width(w), _height(h){}
- unsigned width() { return _width; }
- unsigned height() { return _height; }
+ Screen(unsigned id, unsigned w, unsigned h) : _screen_id(id), _width(w), _height(h){}
+ unsigned width() const { return _width; }
+ unsigned height() const { return _height; }
+ unsigned id() const { return _screen_id; }
+ unsigned scale() const { return _scale; }
+ int offsetX() const { return _offset_x; }
+ int offsetY() const { return _offset_y; }
+ void setScale(double scl) { this->_scale = scl; }
+ void setOffset(int x, int y) { this->_offset_x = x; this->_offset_y = y; }
private:
+ unsigned _screen_id;
unsigned _width;
unsigned _height;
unsigned _pysical_width = 0;
unsigned _pysical_height = 0;
+ int _offset_x = 0;
+ int _offset_y = 0;
+ double _scale = 1.0;
};
class LayerControlCallbacks {
@@ -60,18 +70,21 @@ class WMClient;
class LayerControl
{
public:
- explicit LayerControl(const std::string& root);
+ explicit LayerControl(const std::string& root, const std::string& ecu_name);
~LayerControl() = default;
WMError init(const LayerControlCallbacks& cb);
void createNewLayer(unsigned id);
- unsigned getNewLayerID(const std::string& role);
+ void createNewRemoteLayer(unsigned id);
+ unsigned getNewLayerID(const std::string& role, std::string* layer_name);
std::shared_ptr<WMLayer> getWMLayer(unsigned layer);
std::shared_ptr<WMLayer> getWMLayer(std::string layer_name);
struct rect getAreaSize(const std::string& area);
void setupArea(const rectangle& base_rct, double scaling);
Screen getScreenInfo();
double scale();
+ WMError updateLayer(LayerState& layer_state);
WMError renderLayers();
+ // WMError renderLayersRemote();
WMError setXDGSurfaceOriginSize(unsigned surface);
void undoUpdate();
WMError layoutChange(const WMAction& action);
@@ -87,23 +100,32 @@ class LayerControl
void dispatchSurfacePropChangeEvent(unsigned id, struct ilmSurfaceProperties*, t_ilm_notification_mask);
void dispatchLayerPropChangeEvent(unsigned id, struct ilmLayerProperties*, t_ilm_notification_mask);
+ bool hasRemoteLayer(unsigned layer);
+
private:
WMError makeVisible(const std::shared_ptr<WMClient> client);
WMError makeInvisible(const std::shared_ptr<WMClient> client);
bool moveForeGround(const std::shared_ptr<WMClient> client);
bool moveBackGround(const std::shared_ptr<WMClient> client);
+ bool moveRemote(unsigned layer, const std::string& area);
+ bool moveLocal(unsigned layer);
+ int loadWestonSetting(const std::string &path);
WMError loadLayerSetting(const std::string& path);
- WMError loadAreaDb(const std::string& path);
+ WMError loadAreasConfigFile(const std::string& path, const std::string& ecu_name);
std::vector<std::shared_ptr<WMLayer>> wm_layers;
+ std::vector<Screen> wm_screens;
std::unordered_map<unsigned, unsigned> lid2wmlid;
std::unordered_map<std::string, struct rect> area2size;
unsigned screenID;
- struct ilmScreenProperties screen_prop;
+
double scaling;
int offset_x;
int offset_y;
LayerControlCallbacks cb;
+
+ long times;
+ long sleep;
};
-} // namespace wm \ No newline at end of file
+} // namespace wm