summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/hmi-debug.h47
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/app.hpp2
-rw-r--r--src/applist.cpp526
-rw-r--r--src/applist.hpp81
-rw-r--r--src/request.cpp44
-rw-r--r--src/request.hpp72
-rw-r--r--src/wm_client.cpp222
-rw-r--r--src/wm_client.hpp76
-rw-r--r--src/wm_error.cpp46
-rw-r--r--src/wm_error.hpp41
11 files changed, 1160 insertions, 3 deletions
diff --git a/include/hmi-debug.h b/include/hmi-debug.h
index a1d3079..697ac80 100644
--- a/include/hmi-debug.h
+++ b/include/hmi-debug.h
@@ -41,6 +41,14 @@ enum LOG_LEVEL{
#define HMI_INFO(prefix, args,...) _HMI_LOG(LOG_LEVEL_INFO, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__)
#define HMI_DEBUG(prefix, args,...) _HMI_LOG(LOG_LEVEL_DEBUG, __FILENAME__, __FUNCTION__,__LINE__, prefix, args,##__VA_ARGS__)
+#define HMI_SEQ_ERROR(seq_num, args,...) _HMI_SEQ_LOG(LOG_LEVEL_ERROR, __FILENAME__, __FUNCTION__, __LINE__, seq_num, args, ##__VA_ARGS__)
+#define HMI_SEQ_WARNING(seq_num, args,...) _HMI_SEQ_LOG(LOG_LEVEL_WARNING, __FILENAME__, __FUNCTION__, __LINE__, seq_num, args, ##__VA_ARGS__)
+#define HMI_SEQ_NOTICE(seq_num, args,...) _HMI_SEQ_LOG(LOG_LEVEL_NOTICE, __FILENAME__, __FUNCTION__, __LINE__, seq_num, args, ##__VA_ARGS__)
+#define HMI_SEQ_INFO(seq_num, args,...) _HMI_SEQ_LOG(LOG_LEVEL_INFO, __FILENAME__, __FUNCTION__, __LINE__, seq_num, args, ##__VA_ARGS__)
+#define HMI_SEQ_DEBUG(seq_num, args,...) _HMI_SEQ_LOG(LOG_LEVEL_DEBUG, __FILENAME__, __FUNCTION__, __LINE__, seq_num, args, ##__VA_ARGS__)
+
+#define DUMP(args, ...) _DUMP(LOG_LEVEL_DEBUG, args, ##__VA_ARGS__)
+
static char ERROR_FLAG[6][20] = {"NONE", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"};
static void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, const int line, const char* prefix, const char* log, ...)
@@ -67,4 +75,43 @@ static void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, c
free(message);
}
+static void _HMI_SEQ_LOG(enum LOG_LEVEL level, const char* file, const char* func, const int line, unsigned seq_num, const char* log, ...){
+ const int log_level = (getenv("USE_HMI_DEBUG") == NULL) ? LOG_LEVEL_ERROR:atoi(getenv("USE_HMI_DEBUG"));
+ if(log_level < level)
+ {
+ return;
+ }
+
+ char *message;
+ struct timespec tp;
+ unsigned int time;
+
+ clock_gettime(CLOCK_REALTIME, &tp);
+ time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
+
+ va_list args;
+ va_start(args, log);
+ if (log == NULL || vasprintf(&message, log, args) < 0)
+ message = NULL;
+ fprintf(stderr, "[%10.3f] [wm %s] [%s, %s(), Line:%d] >>> req %d: %s \n", time / 1000.0, ERROR_FLAG[level], file, func, line, seq_num, message);
+ va_end(args);
+ free(message);
+}
+
+static void _DUMP(enum LOG_LEVEL level, const char *log, ...)
+{
+ const int log_level = (getenv("USE_HMI_DEBUG") == NULL) ? LOG_LEVEL_ERROR : atoi(getenv("USE_HMI_DEBUG"));
+ if (log_level < level)
+ {
+ return;
+ }
+ char *message;
+ va_list args;
+ va_start(args, log);
+ if (log == NULL || vasprintf(&message, log, args) < 0)
+ message = NULL;
+ fprintf(stderr, "%s \n", message);
+ va_end(args);
+ free(message);
+}
#endif //__HMI_DEBUG_H__ \ No newline at end of file
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index f727500..db3f9cd 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -33,7 +33,11 @@ add_library(${TARGETS_WM} MODULE
${IVI_CON_PROTO}
json_helper.cpp
app.cpp
- layers.cpp)
+ layers.cpp
+ wm_client.cpp
+ wm_error.cpp
+ applist.cpp
+ request.cpp)
target_include_directories(${TARGETS_WM}
PRIVATE
diff --git a/src/app.hpp b/src/app.hpp
index ab4e809..4dce828 100644
--- a/src/app.hpp
+++ b/src/app.hpp
@@ -69,7 +69,6 @@ struct id_allocator
// Surfaces that where requested but not yet created
std::unordered_map<unsigned, std::string> id2name;
- // std::unordered_set<unsigned> pending_surfaces;
std::unordered_map<std::string, unsigned> name2id;
id_allocator(id_allocator const &) = delete;
@@ -82,7 +81,6 @@ struct id_allocator
{
unsigned sid = this->next++;
this->id2name[sid] = name;
- // this->pending_surfaces.insert({sid});
this->name2id[name] = sid;
HMI_DEBUG("wm", "allocated new id %u with name %s", sid, name.c_str());
return sid;
diff --git a/src/applist.cpp b/src/applist.cpp
new file mode 100644
index 0000000..a5ae9f0
--- /dev/null
+++ b/src/applist.cpp
@@ -0,0 +1,526 @@
+/*
+ * 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 <iostream>
+#include <algorithm>
+#include "applist.hpp"
+#include "../include/hmi-debug.h"
+
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+namespace wm
+{
+
+const static int kReserveClientSize = 100;
+const static int kReserveReqSize = 10;
+
+/**
+ * AppList Constructor.
+ *
+ * Reserve the container size to avoid re-allocating memory.
+ *
+ * @note Size should be changed according to the system.
+ * If the number of applications becomes over the size, re-allocating memory will happen.
+ */
+AppList::AppList()
+ : req_list(),
+ app2client(),
+ current_req(1)
+{
+ this->app2client.reserve(kReserveClientSize);
+ this->req_list.reserve(kReserveReqSize);
+}
+
+AppList::~AppList() {}
+
+// =================== Client Date container API ===================
+
+/**
+ * Add Client to the list
+ *
+ * Add Client to the list.
+ * The Client means application which has role, layer, surface
+ * This function should be called once for the app.
+ * Caller should take care not to be called more than once.
+ *
+ * @param string[in] Application id. This will be the key to withdraw the information.
+ * @param unsigned[in] Layer ID in which the application is
+ * @param unsigned[in] surface ID which the application has
+ * @param string[in] Role which means what behavior the application will do.
+ * @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 std::string &appid, unsigned layer, unsigned surface, const std::string &role)
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ shared_ptr<WMClient> client = std::make_shared<WMClient>(appid, layer, surface, role);
+ 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.
+ */
+void AppList::removeClient(const string &appid)
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ this->app2client.erase(appid);
+ HMI_INFO("wm", "Remove client %s", appid.c_str());
+}
+
+/**
+ * Check this class stores the appid.
+ *
+ * @param string[in] Application id. This will be the key to withdraw the information.
+ * @return true if the class has the requested key(appid)
+ */
+bool AppList::contains(const string &appid) const
+{
+ auto result = this->app2client.find(appid);
+ return (this->app2client.end() != result) ? true : false;
+}
+
+/**
+ * Remove surface from client
+ *
+ * @param unsigned[in] surface id.
+ * @return None
+ */
+void AppList::removeSurface(unsigned surface){
+ // This function may be very slow
+ std::lock_guard<std::mutex> lock(this->mtx);
+ bool ret = false;
+ for (auto &x : this->app2client)
+ {
+ ret = x.second->removeSurfaceIfExist(surface);
+ if(ret){
+ HMI_DEBUG("wm", "remove surface %d from Client %s finish",
+ surface, x.second->appID().c_str());
+ break;
+ }
+ }
+
+}
+
+/**
+ * Get WMClient object.
+ *
+ * After get the WMClient object, caller can call the client method.
+ * Before call this function, caller must call "contains"
+ * to check the key is contained, otherwise, you have to take care of std::out_of_range.
+ *
+ * @param string[in] application id(key)
+ * @return WMClient object
+ * @attention Must call cantains to check appid is stored before this function.
+ */
+shared_ptr<WMClient> AppList::lookUpClient(const string &appid)
+{
+ return this->app2client.at(appid);
+}
+
+/**
+ * Count Client.
+ *
+ * Returns the number of client stored in the list.
+ *
+ * @param None
+ * @return The number of client
+ */
+int AppList::countClient() const
+{
+ return this->app2client.size();
+}
+
+/**
+ * Get AppID with surface and role.
+ *
+ * Returns AppID if found.
+ *
+ * @param unsigned[in] surfaceID
+ * @param string[in] role
+ * @param bool[in,out] AppID is found or not
+ * @return AppID
+ * @attention If AppID is not found, param found will be false.
+ */
+string AppList::getAppID(unsigned surface, const string& role, bool* found) const
+{
+ *found = false;
+ for (const auto &x : this->app2client)
+ {
+ if(x.second->surfaceID(role) == surface){
+ *found = true;
+ return x.second->appID();
+ }
+ }
+ return string("");
+}
+
+// =================== Request Date container API ===================
+
+/**
+ * Get current request number
+ *
+ * Request number is the numeric ID to designate the request.
+ * But returned request number from this function doesn't mean the request exists.
+ * This number is used as key to withdraw the WMRequest object.
+ *
+ * @param None
+ * @return current request number.
+ * @note request number is more than 0.
+ */
+unsigned AppList::currentRequestNumber() const
+{
+ return this->current_req;
+}
+
+/**
+ * Get request number
+ *
+ * Request number is the numeric ID to designate the request.
+ * But returned request number from this function doesn't mean the request exists.
+ * This number is used as key to withdraw the WMRequest object.
+ *
+ * @param None
+ * @return request number.
+ * @attention If returned value is 0, no request exists.
+ */
+unsigned AppList::getRequestNumber(const string &appid) const
+{
+ for (const auto &x : this->req_list)
+ {
+ // Since app will not request twice and more, comparing appid is enough?
+ if ((x.trigger.appid == appid))
+ {
+ return x.req_num;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Add Request
+ *
+ * Request number is the numeric ID to designate the request.
+ * But returned request number from this function doesn't mean the request exists.
+ * This number is used as key to withdraw the WMRequest object.
+ *
+ * @param WMRequest[in] WMRequest object caller creates
+ * @return Request number
+ * @attention If the request number is different with curent request number,
+ * it means the previous request is not finished.
+ */
+unsigned AppList::addRequest(WMRequest req)
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ if (this->req_list.size() == 0)
+ {
+ req.req_num = current_req;
+ }
+ else
+ {
+ HMI_SEQ_INFO(this->current_req, "add: %d", this->req_list.back().req_num + 1);
+ req.req_num = this->req_list.back().req_num + 1;
+ }
+ this->req_list.push_back(req);
+ return req.req_num;
+}
+
+/**
+ * Get trigger which the application requests
+ *
+ * WMTrigger contains which application requests what role and where to put(area) and task.
+ * This is used for input event to Window Policy Manager(state machine).
+ *
+ * @param unsigned[in] request number
+ * @param bool[in,out] Check request number of the parameter is valid.
+ * @return WMTrigger which associates with the request number
+ * @attention If the request number is not valid, parameter "found" is false
+ * and return value will be meaningless value.
+ * Caller can check the request parameter is valid.
+ */
+struct WMTrigger AppList::getRequest(unsigned req_num, bool *found)
+{
+ *found = false;
+ for (const auto &x : this->req_list)
+ {
+ if (req_num == x.req_num)
+ {
+ *found = true;
+ return x.trigger;
+ }
+ }
+ HMI_SEQ_ERROR(req_num, "Couldn't get request : %d", req_num);
+ return WMTrigger{"", "", "", Task::TASK_INVALID};
+}
+
+/**
+ * Get actions which the application requests
+ *
+ * WMAciton contains the information of state transition.
+ * In other words, it contains actions of Window Manager,
+ * which role should be put to the area.
+ *
+ * @param unsigned[in] request number
+ * @param bool[in,out] Check request number of the parameter is valid.
+ * @return WMTrigger which associates with the request number
+ * @attention If the request number is not valid, parameter "found" is false
+ * and return value will be no reference pointer.
+ * Caller must check the request parameter is valid.
+ */
+const vector<struct WMAction> &AppList::getActions(unsigned req_num, bool* found)
+{
+ *found = false;
+ for (auto &x : this->req_list)
+ {
+ if (req_num == x.req_num)
+ {
+ *found = true;
+ return x.sync_draw_req;
+ }
+ }
+ HMI_SEQ_ERROR(req_num, "Couldn't get action with the request : %d", req_num);
+}
+
+/**
+ * Set actions to the request.
+ *
+ * Add actions to the request.
+ * This function can be called many times, and actions increase.
+ * This function is used for decision of actions of Window Manager
+ * according to the result of Window Policy Manager.
+ *
+ * @param unsigned[in] request number
+ * @param WMAction[in] Action of Window Manager.
+ * @return WMError If request number is not valid, FAIL will be returned.
+ */
+WMError AppList::setAction(unsigned req_num, const struct WMAction &action)
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ WMError result = WMError::FAIL;
+ for (auto &x : this->req_list)
+ {
+ if (req_num != x.req_num)
+ {
+ continue;
+ }
+ x.sync_draw_req.push_back(action);
+ result = WMError::SUCCESS;
+ break;
+ }
+ return result;
+}
+
+/**
+ * Note:
+ * @note This function set action with parameters.
+ * If visible is true, it means app should be visible, so enddraw_finished parameter should be false.
+ * otherwise (visible is false) app should be invisible. Then enddraw_finished param is set to true.
+ * This function doesn't support actions for focus yet.
+ */
+/**
+ * Set actions to the request.
+ *
+ * This function is overload function.
+ * The feature is same as other one.
+ *
+ * @param unsigned[in] request number
+ * @param string[in] application id
+ * @param string[in] role
+ * @param string[in] area
+ * @param Task[in] the role should be visible or not.
+ * @return WMError If request number is not valid, FAIL will be returned.
+ * @attention This function set action with parameters, then caller doesn't need to create WMAction object.
+ * If visible is true, it means app should be visible, so enddraw_finished parameter will be false.
+ * otherwise (visible is false) app should be invisible. Then enddraw_finished param is set to true.
+ * This function doesn't support actions for focus yet.
+ */
+WMError AppList::setAction(unsigned req_num, const string &appid, const string &role, const string &area, TaskVisible visible)
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ WMError result = WMError::FAIL;
+ for (auto &x : req_list)
+ {
+ if (req_num != x.req_num)
+ {
+ continue;
+ }
+ // If visible task is not invisible, redraw is required -> true
+ bool edraw_f = (visible != TaskVisible::INVISIBLE) ? false : true;
+ WMAction action{appid, role, area, visible, edraw_f};
+
+ x.sync_draw_req.push_back(action);
+ result = WMError::SUCCESS;
+ break;
+ }
+ return result;
+}
+
+/**
+ * Set end_draw_finished param is true
+ *
+ * This function checks
+ * - req_num is equal to current request number
+ * - appid and role are equeal to the appid and role stored in action list
+ * If it is valid, set the action is finished.
+ *
+ * @param unsigned[in] request number
+ * @param string[in] application id
+ * @param string[in] role
+ * @return If the parameters are not valid in action list, returns false
+ */
+bool AppList::setEndDrawFinished(unsigned req_num, const string &appid, const string &role)
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ bool result = false;
+ for (auto &x : req_list)
+ {
+ if (req_num < x.req_num)
+ {
+ break;
+ }
+ if (req_num == x.req_num)
+ {
+ for (auto &y : x.sync_draw_req)
+ {
+ if (y.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;
+ }
+ }
+ }
+ }
+ this->reqDump();
+ return result;
+}
+
+/**
+ * Check all actions of the requested sequence is finished
+ *
+ * @param unsigned[in] request_number
+ * @return true if all action is set.
+ */
+bool AppList::endDrawFullfilled(unsigned req_num)
+{
+ bool result = false;
+ for (const auto &x : req_list)
+ {
+ if (req_num < x.req_num)
+ {
+ break;
+ }
+ if (req_num == x.req_num)
+ {
+ result = true;
+ for (const auto &y : x.sync_draw_req)
+ {
+ result &= y.end_draw_finished;
+ if (!result)
+ {
+ break;
+ }
+ }
+ }
+ }
+ return result;
+}
+
+/**
+ * Finish the request, then remove it.
+ *
+ * @param unsigned[in] request_number
+ * @return None
+ * @note Please call next after this function to receive or process next request.
+ */
+void AppList::removeRequest(unsigned req_num)
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ this->req_list.erase(remove_if(this->req_list.begin(), this->req_list.end(),
+ [req_num](WMRequest x) {
+ return x.req_num == req_num;
+ }));
+}
+
+/**
+ * Move the current request to next
+ *
+ * @param None
+ * @return None
+ */
+void AppList::next()
+{
+ std::lock_guard<std::mutex> lock(this->mtx);
+ ++this->current_req;
+ if (0 == this->current_req)
+ {
+ this->current_req = 1;
+ }
+}
+
+/**
+ * Check the request exists is in request list
+ *
+ * @param None
+ * @return true if WMRequest exists in the request list
+ */
+bool AppList::haveRequest() const
+{
+ return !this->req_list.empty();
+}
+
+void AppList::clientDump()
+{
+ DUMP("======= client dump =====");
+ for (const auto &x : this->app2client)
+ {
+ const auto &y = x.second;
+ y->dumpInfo();
+ }
+ DUMP("======= client dump end=====");
+}
+
+void AppList::reqDump()
+{
+ DUMP("======= req dump =====");
+ DUMP("current request : %d", current_req);
+ for (const auto &x : req_list)
+ {
+ DUMP("requested : %d", x.req_num);
+ DUMP("Trigger : (APPID :%s, ROLE :%s, AREA :%s, TASK: %d)",
+ x.trigger.appid.c_str(),
+ x.trigger.role.c_str(),
+ x.trigger.area.c_str(),
+ x.trigger.task);
+
+ for (const auto &y : x.sync_draw_req)
+ {
+ DUMP(
+ "Action : (APPID :%s, ROLE :%s, AREA :%s, VISIBLE : %s, END_DRAW_FINISHED: %d)",
+ y.appid.c_str(),
+ y.role.c_str(),
+ y.area.c_str(),
+ (y.visible == TaskVisible::INVISIBLE) ? "invisible" : "visible",
+ y.end_draw_finished);
+ }
+ }
+ DUMP("======= req dump end =====");
+}
+} // namespace wm
diff --git a/src/applist.hpp b/src/applist.hpp
new file mode 100644
index 0000000..a794b53
--- /dev/null
+++ b/src/applist.hpp
@@ -0,0 +1,81 @@
+/*
+ * 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 ALLOCATE_LIST_HPP
+#define ALLOCATE_LIST_HPP
+#include <vector>
+#include <string>
+#include <map>
+#include <memory>
+#include <mutex>
+#include "wm_client.hpp"
+#include "request.hpp"
+#include "wm_error.hpp"
+
+namespace wm
+{
+
+/* using std::experimental::nullopt;
+using std::experimental::optional; */
+
+class AppList
+{
+ public:
+ AppList();
+ virtual ~AppList();
+ AppList(const AppList &obj) = delete;
+
+ // Client Database Interface
+ /* TODO: consider, which is better WMClient as parameter or not
+ If the WMClient should be more flexible, I think this param should be WMClient class
+ */
+ void addClient(const std::string &appid, unsigned layer,
+ unsigned surface,const std::string &role);
+ void removeClient(const std::string &appid);
+ bool contains(const std::string &appid) const;
+ int countClient() const;
+ std::shared_ptr<WMClient> lookUpClient(const std::string &appid);
+ void removeSurface(unsigned surface);
+ std::string getAppID(unsigned surface, const std::string &role, bool *found) const;
+
+ // Request Interface
+ unsigned currentRequestNumber() const;
+ unsigned getRequestNumber(const std::string &appid) const;
+ unsigned addRequest(WMRequest req);
+ WMError setAction(unsigned req_num, const struct WMAction &action);
+ WMError setAction(unsigned req_num, const std::string &appid,
+ const std::string &role, const std::string &area, TaskVisible visible);
+ bool setEndDrawFinished(unsigned req_num, const std::string &appid, const std::string &role);
+ bool endDrawFullfilled(unsigned req_num);
+ void removeRequest(unsigned req_num);
+ void next();
+ bool haveRequest() const;
+
+ struct WMTrigger getRequest(unsigned req_num, bool* found);
+ const std::vector<struct WMAction> &getActions(unsigned req_num, bool* found);
+
+ void clientDump();
+ void reqDump();
+
+ private:
+ std::vector<WMRequest> req_list;
+ std::unordered_map<std::string, std::shared_ptr<WMClient>> app2client;
+ unsigned current_req;
+ std::mutex mtx;
+};
+
+} // namespace wm
+#endif // ALLOCATE_LIST_HPP \ No newline at end of file
diff --git a/src/request.cpp b/src/request.cpp
new file mode 100644
index 0000000..069f8ff
--- /dev/null
+++ b/src/request.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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 "request.hpp"
+
+namespace wm
+{
+
+using std::string;
+
+WMRequest::WMRequest() {}
+
+WMRequest::WMRequest(string appid, string role, string area, Task task)
+ : req_num(0),
+ trigger{appid, role, area, task},
+ sync_draw_req(0)
+{
+}
+
+WMRequest::~WMRequest()
+{
+}
+
+WMRequest::WMRequest(const WMRequest &obj)
+{
+ this->req_num = obj.req_num;
+ this->trigger = obj.trigger;
+ this->sync_draw_req = obj.sync_draw_req;
+}
+
+} // namespace wm \ No newline at end of file
diff --git a/src/request.hpp b/src/request.hpp
new file mode 100644
index 0000000..6b2bda1
--- /dev/null
+++ b/src/request.hpp
@@ -0,0 +1,72 @@
+/*
+ * 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 WMREQUEST_HPP
+#define WMREQUEST_HPP
+
+#include <string>
+#include <vector>
+
+namespace wm
+{
+
+enum Task
+{
+ TASK_ALLOCATE,
+ TASK_RELEASE,
+ TASK_INVALID
+};
+
+enum TaskVisible
+{
+ VISIBLE,
+ INVISIBLE,
+ NO_CHANGE
+};
+
+struct WMTrigger
+{
+ std::string appid;
+ std::string role;
+ std::string area;
+ Task task;
+};
+
+struct WMAction
+{
+ std::string appid;
+ std::string role;
+ std::string area;
+ TaskVisible visible;
+ bool end_draw_finished;
+};
+
+struct WMRequest
+{
+ WMRequest();
+ explicit WMRequest(std::string appid, std::string role,
+ std::string area, Task task);
+ virtual ~WMRequest();
+ WMRequest(const WMRequest &obj);
+
+ unsigned req_num;
+ struct WMTrigger trigger;
+ std::vector<struct WMAction> sync_draw_req;
+};
+
+} // namespace wm
+
+#endif //WMREQUEST_HPP \ No newline at end of file
diff --git a/src/wm_client.cpp b/src/wm_client.cpp
new file mode 100644
index 0000000..a9ed547
--- /dev/null
+++ b/src/wm_client.cpp
@@ -0,0 +1,222 @@
+/*
+ * 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 <json-c/json.h>
+#include "wm_client.hpp"
+#include "hmi-debug.h"
+
+#define INVALID_SURFACE_ID 0
+
+using std::string;
+using std::vector;
+
+namespace wm
+{
+
+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 kKeyrole[] = "role";
+static const char kKeyError[] = "error";
+static const char kKeyErrorDesc[] = "kErrorDescription";
+
+WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const string &role)
+ : id(appid), layer(layer),
+ role2surface(0)
+{
+ role2surface[role] = surface;
+ for (auto x : kWMEvents)
+ {
+#if GTEST_ENABLED
+ string ev = x;
+#else
+ afb_event ev = afb_daemon_make_event(x.c_str());
+#endif
+ event2list[x] = ev;
+ }
+}
+
+WMClient::WMClient(const string &appid, const string &role)
+ : id(appid),
+ layer(0),
+ role2surface(0),
+ event2list(0)
+{
+ role2surface[role] = INVALID_SURFACE_ID;
+ for (auto x : kWMEvents)
+ {
+#if GTEST_ENABLED
+ string ev = x;
+#else
+ afb_event ev = afb_daemon_make_event(x.c_str());
+#endif
+ event2list[x] = ev;
+ }
+}
+
+WMClient::~WMClient()
+{
+}
+
+string WMClient::appID() const
+{
+ return this->id;
+}
+
+unsigned WMClient::surfaceID(const string &role) const
+{
+ if (0 == this->role2surface.count(role))
+ {
+ return INVALID_SURFACE_ID;
+ }
+ return this->role2surface.at(role);
+}
+
+std::string WMClient::role(unsigned surface) const
+{
+ for(const auto& x : this->role2surface)
+ {
+ if(x.second == surface)
+ {
+ return x.first;
+ }
+ }
+ return std::string("");
+}
+
+unsigned WMClient::layerID() const
+{
+ return this->layer;
+}
+
+/**
+ * Set layerID the client belongs to
+ *
+ * This function set layerID the client belongs to.
+ * But this function may not used because the layer should be fixed at constructor.
+ * So this function will be used to change layer by some reasons.
+ *
+ * @param unsigned[in] layerID
+ * @return None
+ * @attention WMClient can't have multiple layer
+ */
+void WMClient::registerLayer(unsigned layer)
+{
+ this->layer = layer;
+}
+
+/**
+ * Add the pair of role and surface to the client
+ *
+ * This function set the pair of role and surface to the client.
+ * This function is used for the client which has multi surfaces.
+ * If the model and relationship for role and surface(layer)
+ * is changed, this function will be changed
+ * Current Window Manager doesn't use this function.
+ *
+ * @param string[in] role
+ * @param unsigned[in] surface
+ * @return true
+ */
+bool WMClient::addSurface(const string &role, unsigned surface)
+{
+ HMI_DEBUG("wm", "Add role %s with surface %d", role.c_str(), surface);
+ if (0 != this->role2surface.count(role))
+ {
+ HMI_NOTICE("wm", "override surfaceID %d with %d", this->role2surface[role], surface);
+ }
+ this->role2surface[role] = surface;
+ return true;
+}
+
+bool WMClient::removeSurfaceIfExist(unsigned surface)
+{
+ bool ret = false;
+ for (auto &x : this->role2surface)
+ {
+ if (surface == x.second)
+ {
+ HMI_INFO("wm", "Remove surface from client %s: role %s, surface: %d",
+ this->id.c_str(), x.first.c_str(), x.second);
+ this->role2surface.erase(x.first);
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+bool WMClient::removeRole(const string &role)
+{
+ bool ret = false;
+ if (this->role2surface.count(role) != 0)
+ {
+ this->role2surface.erase(role);
+ ret = true;
+ }
+ return ret;
+}
+
+#ifndef GTEST_ENABLED
+bool WMClient::subscribe(afb_req req, const string &evname)
+{
+ if(evname != kKeyError){
+ HMI_DEBUG("wm", "error is only enabeled for now");
+ return false;
+ }
+ int ret = afb_req_subscribe(req, this->event2list[evname]);
+ if (ret)
+ {
+ HMI_DEBUG("wm", "Failed to subscribe %s", evname.c_str());
+ return false;
+ }
+ return true;
+}
+
+void WMClient::emitError(WM_CLIENT_ERROR_EVENT ev)
+{
+ if (!afb_event_is_valid(this->event2list[kKeyError])){
+ HMI_ERROR("wm", "event err is not valid");
+ return;
+ }
+ json_object *j = json_object_new_object();
+ 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("wm", "error: %d, description:%s", ev, kErrorDescription[ev].c_str());
+
+ int ret = afb_event_push(this->event2list[kKeyError], j);
+ if (ret != 0)
+ {
+ HMI_DEBUG("wm", "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);
+ }
+}
+
+} // namespace wm \ No newline at end of file
diff --git a/src/wm_client.hpp b/src/wm_client.hpp
new file mode 100644
index 0000000..0d6faeb
--- /dev/null
+++ b/src/wm_client.hpp
@@ -0,0 +1,76 @@
+/*
+ * 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 WINDOWMANAGER_CLIENT_HPP
+#define WINDOWMANAGER_CLIENT_HPP
+
+#include <vector>
+#include <string>
+#include <unordered_map>
+
+extern "C"
+{
+#define AFB_BINDING_VERSION 2
+#include <afb/afb-binding.h>
+}
+
+namespace wm
+{
+
+enum WM_CLIENT_ERROR_EVENT
+{
+ UNKNOWN_ERROR
+};
+
+class WMClient
+{
+ public:
+ WMClient();
+ WMClient(const std::string &appid, unsigned layer,
+ unsigned surface, const std::string &role);
+ WMClient(const std::string &appid, const std::string &role);
+ virtual ~WMClient();
+
+ std::string appID() const;
+ unsigned surfaceID(const std::string &role) const;
+ unsigned layerID() const;
+ std::string role(unsigned surface) const;
+ void registerLayer(unsigned layer);
+ bool addSurface(const std::string& role, unsigned surface);
+ bool removeSurfaceIfExist(unsigned surface);
+ bool removeRole(const std::string& role);
+
+#ifndef 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;
+ std::unordered_map<std::string, unsigned> role2surface;
+#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> event2list;
+#else
+ std::unordered_map<std::string, struct afb_event> event2list;
+#endif
+};
+} // namespace wm
+
+#endif \ No newline at end of file
diff --git a/src/wm_error.cpp b/src/wm_error.cpp
new file mode 100644
index 0000000..694a7d0
--- /dev/null
+++ b/src/wm_error.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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_error.hpp"
+
+namespace wm {
+
+const char *errorDescription(WMError enum_error_number)
+{
+ switch (enum_error_number){
+ case SUCCESS:
+ return "Success";
+ case FAIL:
+ return "Request failed";
+ case REQ_REJECTED:
+ return "Request is rejected, due to the policy rejection of the request.";
+ case REQ_DROPPED:
+ return "Request is dropped, because the high priority request is done";
+ case NOT_REGISTERED:
+ return "Not registered";
+ case TIMEOUT_EXPIRED:
+ return "Request is dropped, due to time out expiring";
+ case LAYOUT_CHANGE_FAIL:
+ return "Layout change fails, due to some reasons";
+ case NO_ENTRY:
+ return "No element";
+ case NO_LAYOUT_CHANGE:
+ return "No layout change(deactivate only)";
+ default:
+ return "Unknown error number. Window manager bug.";
+ }
+}
+
+} \ No newline at end of file
diff --git a/src/wm_error.hpp b/src/wm_error.hpp
new file mode 100644
index 0000000..c4c61b4
--- /dev/null
+++ b/src/wm_error.hpp
@@ -0,0 +1,41 @@
+/*
+ * 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 WINDOW_MANAGER_ERROR
+#define WINDOW_MANAGER_ERROR
+
+namespace wm {
+
+typedef enum WINDOWMANAGER_ERROR
+{
+ SUCCESS = 0,
+ FAIL,
+ REQ_REJECTED,
+ REQ_DROPPED,
+ TIMEOUT_EXPIRED,
+ NOT_REGISTERED,
+ LAYOUT_CHANGE_FAIL,
+ NO_ENTRY,
+ NO_LAYOUT_CHANGE,
+ UNKNOWN,
+ ERR_MAX = UNKNOWN
+}
+WMError;
+
+const char *errorDescription(WMError enum_error_number);
+
+}
+#endif // WINDOW_MANAGER_ERROR \ No newline at end of file