1168f4bc3d8c6a979d9a7b6e6322e2cadcf42031
[platform/core/api/webapi-plugins.git] / src / humanactivitymonitor / gesture_manager.cc
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 #include "humanactivitymonitor/gesture_manager.h"
18
19 #include <gesture_recognition.h>
20
21 #include "common/extension.h"
22 #include "common/logger.h"
23 #include "common/optional.h"
24 #include "common/picojson.h"
25 #include "common/scope_exit.h"
26 #include "common/tools.h"
27
28 namespace extension {
29 namespace humanactivitymonitor {
30
31 using common::PlatformResult;
32 using common::ErrorCode;
33 using common::tools::ReportError;
34 using common::tools::ReportSuccess;
35
36 namespace {
37
38 const std::string kListenerId = "listenerId";
39 const std::string kListener = "GestureRecognitionListener";
40 const std::string kType = "type";
41 const std::string kTimestamp = "timestamp";
42 const std::string kAlwayOn = "alwaysOn";
43 const std::string kAction = "action";
44 const std::string kEvent = "event";
45 const std::string kError = "error";
46 const std::string kOnError = "onerror";
47 const std::string kOnDetect = "ondetect";
48
49 ErrorCode getErrorCode(int error) {
50   switch (error) {
51     case GESTURE_ERROR_NONE:
52       return ErrorCode::NO_ERROR;
53     case GESTURE_ERROR_INVALID_PARAMETER:
54       return ErrorCode::INVALID_VALUES_ERR;
55     case GESTURE_ERROR_OPERATION_FAILED:
56       return ErrorCode::IO_ERR;
57     case GESTURE_ERROR_NOT_SUPPORTED:
58       return ErrorCode::NOT_SUPPORTED_ERR;
59     case GESTURE_ERROR_INVALID_OPERATION:
60     case GESTURE_ERROR_OUT_OF_MEMORY:
61     case GESTURE_ERROR_PERMISSION_DENIED:
62     case GESTURE_ERROR_ALREADY_STARTED:
63     case GESTURE_ERROR_NOT_STARTED:
64     default:
65       return ErrorCode::ABORT_ERR;
66   }
67 }
68
69 PlatformResult StrToGestureType(const std::string& type, gesture_type_e* type_e) {
70   if ("GESTURE_DOUBLE_TAP" == type) {
71     *type_e = GESTURE_DOUBLE_TAP;
72   } else if ("GESTURE_MOVE_TO_EAR" == type) {
73     *type_e = GESTURE_MOVE_TO_EAR;
74   } else if ("GESTURE_NO_MOVE" == type) {
75     *type_e = GESTURE_NO_MOVE;
76   } else if ("GESTURE_PICK_UP" == type) {
77     *type_e = GESTURE_PICK_UP;
78   } else if ("GESTURE_SHAKE" == type) {
79     *type_e = GESTURE_SHAKE;
80   } else if ("GESTURE_SNAP" == type) {
81     *type_e = GESTURE_SNAP;
82   } else if ("GESTURE_TILT" == type) {
83     *type_e = GESTURE_TILT;
84   } else if ("GESTURE_TURN_FACE_DOWN" == type) {
85     *type_e = GESTURE_TURN_FACE_DOWN;
86   } else if ("GESTURE_WRIST_UP" == type) {
87     *type_e = GESTURE_WRIST_UP;
88   } else {
89     return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unknown gesture type");
90   }
91
92   return PlatformResult(ErrorCode::NO_ERROR);
93 }
94
95 std::string GestureTypeToStr(gesture_type_e type) {
96   switch (type) {
97     case GESTURE_DOUBLE_TAP:
98       return "GESTURE_DOUBLE_TAP";
99     case GESTURE_MOVE_TO_EAR:
100       return "GESTURE_MOVE_TO_EAR";
101     case GESTURE_NO_MOVE:
102       return "GESTURE_NO_MOVE";
103     case GESTURE_PICK_UP:
104       return "GESTURE_PICK_UP";
105     case GESTURE_SHAKE:
106       return "GESTURE_SHAKE";
107     case GESTURE_SNAP:
108       return "GESTURE_SNAP";
109     case GESTURE_TILT:
110       return "GESTURE_TILT";
111     case GESTURE_TURN_FACE_DOWN:
112       return "GESTURE_TURN_FACE_DOWN";
113     case GESTURE_WRIST_UP:
114       return "GESTURE_WRIST_UP";
115     default:
116       return "GESTURE_UNKNOWN_TYPE";
117   }
118 }
119 std::string GestureEventToStr(gesture_event_e event, gesture_type_e gesture) {
120   switch (event) {
121     // GESTURE_EVENT_DETECTED == GESTURE_SHAKE_DETECTED == GESTURE_SNAP_X_NEGATIVE == 1
122     case GESTURE_EVENT_DETECTED:
123       if (GESTURE_SHAKE == gesture) {
124         return "GESTURE_SHAKE_DETECTED";
125       } else if (GESTURE_SNAP == gesture) {
126         return "GESTURE_SNAP_X_NEGATIVE";
127       } else {
128         return "GESTURE_EVENT_DETECTED";
129       }
130     // GESTURE_SHAKE_FINISHED == GESTURE_SNAP_X_POSITIVE == 2
131     case GESTURE_SHAKE_FINISHED:
132       if (GESTURE_SHAKE == gesture) {
133         return "GESTURE_SHAKE_FINISHED";
134       } else {
135         return "GESTURE_SNAP_X_POSITIVE";
136       }
137     case GESTURE_SNAP_Y_NEGATIVE:
138       return "GESTURE_SNAP_Y_NEGATIVE";
139     case GESTURE_SNAP_Y_POSITIVE:
140       return "GESTURE_SNAP_Y_POSITIVE";
141     case GESTURE_SNAP_Z_NEGATIVE:
142       return "GESTURE_SNAP_Z_NEGATIVE";
143     case GESTURE_SNAP_Z_POSITIVE:
144       return "GESTURE_SNAP_Z_POSITIVE";
145     default:
146       return "GESTURE_EVENT_NONE";
147   }
148 }
149
150 void GestureRecognitionDefaultCb(gesture_type_e gesture, const gesture_data_h data,
151                                  double timestamp, gesture_error_e error, void* user_data) {
152   ScopeLogger();
153
154   GestureManager* manager = static_cast<GestureManager*>(user_data);
155   if (!manager) {
156     LoggerW("User data is null");
157     return;
158   }
159
160   manager->CompleteGestureListenerCb(gesture, data, timestamp, error, false);
161 }
162
163 void GestureRecognitionAlwaysOnCb(gesture_type_e gesture, const gesture_data_h data,
164                                   double timestamp, gesture_error_e error, void* user_data) {
165   ScopeLogger();
166   GestureManager* manager = static_cast<GestureManager*>(user_data);
167
168   if (!manager) {
169     LoggerW("User data is null");
170     return;
171   }
172
173   manager->CompleteGestureListenerCb(gesture, data, timestamp, error, true);
174 }
175
176 }  // namespace
177
178 GestureManager::GestureManager()
179     : m_callback(nullptr), m_recognition_default_map(), m_recognition_always_on_map() {
180   ScopeLogger();
181 }
182
183 GestureManager::~GestureManager() {
184   ScopeLogger();
185
186   int ret = GESTURE_ERROR_NONE;
187
188   for (auto& it : m_recognition_default_map) {
189     ret = gesture_stop_recognition(it.second);
190     if (GESTURE_ERROR_NONE != ret) {
191       LoggerE("gesture_stop_recognition() failed");
192     }
193
194     ret = gesture_release(it.second);
195     if (GESTURE_ERROR_NONE != ret) {
196       LoggerE("gesture_release() failed");
197     }
198   }
199
200   for (auto& it : m_recognition_always_on_map) {
201     ret = gesture_stop_recognition(it.second);
202     if (GESTURE_ERROR_NONE != ret) {
203       LoggerE("gesture_stop_recognition() failed");
204     }
205
206     ret = gesture_release(it.second);
207     if (GESTURE_ERROR_NONE != ret) {
208       LoggerE("gesture_release() failed");
209     }
210   }
211
212   m_recognition_default_map.clear();
213   m_recognition_always_on_map.clear();
214 }
215
216 PlatformResult GestureManager::IsSupported(const std::string& type, bool* is_supported) {
217   ScopeLogger();
218
219   gesture_type_e type_e = GESTURE_DOUBLE_TAP;
220   PlatformResult result = StrToGestureType(type, &type_e);
221   if (!result) {
222     return result;
223   }
224
225   int ret = gesture_is_supported(type_e, is_supported);
226   if (GESTURE_ERROR_NONE != ret) {
227     return LogAndCreateResult(
228         getErrorCode(ret), "Checking gesture failed",
229         ("Checking gesture failed, error: %d (%s)", ret, get_error_message(ret)));
230   }
231
232   return PlatformResult(ErrorCode::NO_ERROR);
233 }
234
235 gesture_event_e GestureManager::GetGestureEvent(const gesture_data_h data) {
236   ScopeLogger();
237
238   gesture_event_e event = GESTURE_EVENT_NONE;
239   int ret = gesture_get_event(data, &event);
240   if (GESTURE_ERROR_NONE != ret) {
241     LoggerE("gesture_get_event() failed, error %d (%s)", ret, get_error_message(ret));
242   }
243
244   return event;
245 }
246
247 void GestureManager::FillTiltData(const gesture_data_h data, picojson::object* obj) {
248   ScopeLogger();
249
250   int x = 0;
251   int y = 0;
252
253   int ret = gesture_get_tilt(data, &x, &y);
254   if (GESTURE_ERROR_NONE != ret) {
255     LoggerE("gesture_get_tilt() failed, error %d (%s)", ret, get_error_message(ret));
256   }
257
258   obj->insert(std::make_pair("x", picojson::value(static_cast<double>(x))));
259   obj->insert(std::make_pair("y", picojson::value(static_cast<double>(y))));
260 }
261
262 void GestureManager::CompleteGestureListenerCb(gesture_type_e gesture, const gesture_data_h data,
263                                                double timestamp, gesture_error_e error,
264                                                bool always_on) {
265   ScopeLogger();
266
267   picojson::value response = picojson::value(picojson::object());
268   auto& obj = response.get<picojson::object>();
269
270   obj.insert(std::make_pair(kAlwayOn, picojson::value(always_on)));
271   obj.insert(std::make_pair(kListenerId, picojson::value(kListener)));
272
273   if (GESTURE_ERROR_NONE != error) {
274     obj.insert(std::make_pair(kAction, picojson::value(kOnError)));
275
276     PlatformResult result =
277         LogAndCreateResult(getErrorCode(error), "Error occurred during recognition");
278     ReportError(result, &obj);
279   } else {
280     gesture_event_e event = GetGestureEvent(data);
281     if (GESTURE_EVENT_NONE == event) {
282       LoggerD("Gesture event none detected.");
283       return;
284     }
285
286     std::string gesture_str = GestureTypeToStr(gesture);
287     if ("GESTURE_UNKNOWN_TYPE" == gesture_str) {
288       LoggerE("Unknown gesture type");
289       return;
290     }
291
292     obj.insert(std::make_pair(kAction, picojson::value(kOnDetect)));
293
294     picojson::value result = picojson::value(picojson::object());
295     auto& result_obj = result.get<picojson::object>();
296
297     result_obj.insert(std::make_pair(kEvent, picojson::value(GestureEventToStr(event, gesture))));
298     result_obj.insert(std::make_pair(kTimestamp, picojson::value(timestamp)));
299     result_obj.insert(std::make_pair(kType, picojson::value(gesture_str)));
300
301     if (GESTURE_TILT == gesture) {
302       FillTiltData(data, &result_obj);
303     }
304
305     ReportSuccess(result, obj);
306   }
307
308   if (!m_callback) {
309     LoggerE("Callback is not defined");
310   } else {
311     m_callback(&response);
312   }
313 }
314
315 PlatformResult GestureManager::AddListener(gesture_type_e type, gesture_option_e option,
316                                            RecognitionMap& gesture_map,
317                                            gesture_recognition_cb callback) {
318   ScopeLogger();
319
320   gesture_h handle = nullptr;
321
322   int ret = gesture_create(&handle);
323   if (GESTURE_ERROR_NONE != ret) {
324     return LogAndCreateResult(
325         getErrorCode(ret), "Creating handle failed",
326         ("Creating handle failed, error: %d (%s)", ret, get_error_message(ret)));
327   }
328
329   ret = gesture_start_recognition(handle, type, option, callback, this);
330   if (GESTURE_ERROR_NONE != ret) {
331     gesture_release(handle);
332     return LogAndCreateResult(
333         getErrorCode(ret), "Starting recognition failed",
334         ("Starting recognition failed, error: %d (%s)", ret, get_error_message(ret)));
335   }
336
337   gesture_map[type] = handle;
338
339   return PlatformResult(ErrorCode::NO_ERROR);
340 }
341
342 PlatformResult GestureManager::AddGestureRecognitionListener(const std::string& type,
343                                                              bool always_on, JsonCallback cb) {
344   ScopeLogger();
345
346   gesture_type_e type_e = GESTURE_DOUBLE_TAP;
347   PlatformResult result = StrToGestureType(type, &type_e);
348   if (!result) {
349     return result;
350   }
351
352   gesture_option_e option = GESTURE_OPTION_DEFAULT;
353   gesture_recognition_cb callback = GestureRecognitionDefaultCb;
354   RecognitionMap* gesture_map = &m_recognition_default_map;
355
356   if (!m_callback) {
357     m_callback = cb;
358   }
359
360   if (always_on) {
361     option = GESTURE_OPTION_ALWAYS_ON;
362     callback = GestureRecognitionAlwaysOnCb;
363     gesture_map = &m_recognition_always_on_map;
364   }
365
366   return AddListener(type_e, option, *gesture_map, callback);
367 }
368
369 PlatformResult GestureManager::RemoveGestureRecognitionListener(const std::string& type,
370                                                                 bool always_on) {
371   ScopeLogger();
372
373   auto& recognition_map = always_on ? m_recognition_always_on_map : m_recognition_default_map;
374   gesture_type_e type_e = GESTURE_DOUBLE_TAP;
375   PlatformResult result = StrToGestureType(type, &type_e);
376   if (!result) {
377     LoggerD("Unknown gesture type.");
378     return PlatformResult(ErrorCode::NO_ERROR);
379   }
380
381   gesture_h handle = nullptr;
382   RecognitionMap::iterator it = recognition_map.find(type_e);
383
384   if (recognition_map.end() != it) {
385     handle = it->second;
386   }
387
388   if (handle) {
389     int ret = gesture_stop_recognition(handle);
390     if (GESTURE_ERROR_NONE != ret) {
391       return LogAndCreateResult(
392           getErrorCode(ret), "Stoping recognition failed",
393           ("Stoping recognition failed, error: %d (%s)", ret, get_error_message(ret)));
394     }
395
396     ret = gesture_release(handle);
397     if (GESTURE_ERROR_NONE != ret) {
398       LoggerE("gesture_release() failed");
399     }
400
401     recognition_map.erase(it);
402   }
403
404   return PlatformResult(ErrorCode::NO_ERROR);
405 }
406
407 }  // namespace humanactivitymonitor
408 }  // namespace extension