[HAM] Added privilege checks in C++.
[platform/core/api/webapi-plugins.git] / src / humanactivitymonitor / humanactivitymonitor_manager.cc
1 /*
2  * Copyright (c) 2015 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/humanactivitymonitor_manager.h"
18
19 #include <gesture_recognition.h>
20
21 #include "common/logger.h"
22
23 namespace extension {
24 namespace humanactivitymonitor {
25
26 using common::PlatformResult;
27 using common::ErrorCode;
28
29 HumanActivityMonitorManager::HumanActivityMonitorManager()
30     : gesture_handle_(nullptr),
31       hrm_sensor_listener_(nullptr),
32       location_handle_(nullptr) {
33   LoggerD("Enter");
34 }
35
36 HumanActivityMonitorManager::~HumanActivityMonitorManager() {
37   LoggerD("Enter");
38   UnsetWristUpListener();
39   UnsetHrmListener();
40   UnsetGpsListener();
41 }
42
43 PlatformResult HumanActivityMonitorManager::Init() {
44   LoggerD("Enter");
45   return PlatformResult(ErrorCode::NO_ERROR);
46 }
47
48 PlatformResult HumanActivityMonitorManager::IsSupported(
49     const std::string& type) {
50
51   // check cache first
52   if (supported_.count(type)) {
53     return LogAndCreateResult(supported_[type]
54         ? ErrorCode::NO_ERROR
55         : ErrorCode::NOT_SUPPORTED_ERR);
56   }
57
58   int ret;
59   bool supported = false;
60   if (type == kActivityTypePedometer) {
61     // TODO(r.galka) no native api for pedometer
62     // so just pass it for not supported.
63   } else if (type == kActivityTypeWristUp) {
64     ret = gesture_is_supported(GESTURE_WRIST_UP, &supported);
65     if (ret != SENSOR_ERROR_NONE) {
66       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
67                             "WRIST_UP gesture check failed",
68                             ("gesture_is_supported(GESTURE_WRIST_UP), error: %d",ret));
69     }
70   } else if (type == kActivityTypeHrm) {
71     ret = sensor_is_supported(SENSOR_HRM, &supported);
72     if (ret != SENSOR_ERROR_NONE) {
73       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
74                             "HRM sensor check failed",
75                             ("sensor_is_supported(HRM), error: %d",ret));
76     }
77   } else if (type == kActivityTypeGps) {
78     supported = location_manager_is_supported_method(LOCATIONS_METHOD_GPS);
79   } else {
80     return LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR);
81   }
82
83   supported_[type] = supported;
84
85   return LogAndCreateResult(supported_[type]
86       ? ErrorCode::NO_ERROR
87       : ErrorCode::NOT_SUPPORTED_ERR);
88 }
89
90 PlatformResult HumanActivityMonitorManager::SetListener(
91     const std::string& type, JsonCallback callback) {
92
93   PlatformResult result = IsSupported(type);
94   if (!result) {
95     return result;
96   }
97
98   if (type == kActivityTypePedometer) {
99     // TODO(r.galka) Not Supported in current implementation.
100   }
101
102   if (type == kActivityTypeWristUp) {
103     return SetWristUpListener(callback);
104   }
105
106   if (type == kActivityTypeHrm) {
107     return SetHrmListener(callback);
108   }
109
110   if (type == kActivityTypeGps) {
111     return SetGpsListener(callback);
112   }
113
114   return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
115 }
116
117 PlatformResult HumanActivityMonitorManager::UnsetListener(
118     const std::string& type) {
119
120   PlatformResult result = IsSupported(type);
121   if (!result) {
122     return result;
123   }
124
125   if (type == kActivityTypePedometer) {
126     // TODO(r.galka) Not Supported in current implementation.
127   }
128
129   if (type == kActivityTypeWristUp) {
130     return UnsetWristUpListener();
131   }
132
133   if (type == kActivityTypeHrm) {
134     return UnsetHrmListener();
135   }
136
137   if (type == kActivityTypeGps) {
138     return UnsetGpsListener();
139   }
140
141   return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
142 }
143
144 PlatformResult HumanActivityMonitorManager::GetHumanActivityData(
145     const std::string& type,
146     picojson::value* data) {
147
148   LoggerD("Enter");
149   if (type == kActivityTypePedometer) {
150     // TODO(r.galka) Not Supported in current implementation.
151   }
152
153   if (type == kActivityTypeWristUp) {
154     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR);
155   }
156
157   if (type == kActivityTypeHrm) {
158     return GetHrmData(data);
159   }
160
161   if (type == kActivityTypeGps) {
162     return GetGpsData(data);
163   }
164
165   return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
166 }
167
168 // WRIST_UP
169 PlatformResult HumanActivityMonitorManager::SetWristUpListener(
170     JsonCallback callback) {
171   LoggerD("Enter");
172   int ret;
173
174   ret = gesture_create(&gesture_handle_);
175   if (ret != GESTURE_ERROR_NONE) {
176     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
177                           "Failed to create WRIST_UP listener",
178                           ("Failed to create WRIST_UP handle, error: %d",ret));
179   }
180
181   ret = gesture_start_recognition(gesture_handle_,
182                                   GESTURE_WRIST_UP,
183                                   GESTURE_OPTION_DEFAULT,
184                                   OnWristUpEvent,
185                                   this);
186   if (ret != GESTURE_ERROR_NONE) {
187     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
188                           "Failed to start WRIST_UP listener",
189                           ("Failed to start WRIST_UP listener, error: %d",ret));
190   }
191
192   wrist_up_event_callback_ = callback;
193
194   return PlatformResult(ErrorCode::NO_ERROR);
195 }
196
197 PlatformResult HumanActivityMonitorManager::UnsetWristUpListener() {
198   LoggerD("Enter");
199
200   if (gesture_handle_) {
201     int ret = gesture_stop_recognition(gesture_handle_);
202     if (ret != GESTURE_ERROR_NONE) {
203       LOGGER(ERROR) << "Failed to stop WRIST_UP detection, error: " << ret;
204     }
205
206     ret = gesture_release(gesture_handle_);
207     if (ret != GESTURE_ERROR_NONE) {
208       LOGGER(ERROR) << "Failed to release WRIST_UP handle, error: " << ret;
209     }
210   }
211
212   wrist_up_event_callback_ = nullptr;
213
214   return PlatformResult(ErrorCode::NO_ERROR);
215 }
216
217 void HumanActivityMonitorManager::OnWristUpEvent(gesture_type_e gesture,
218                                                  const gesture_data_h data,
219                                                  double timestamp,
220                                                  gesture_error_e error,
221                                                  void* user_data) {
222   LoggerD("Enter");
223   HumanActivityMonitorManager* manager =
224       static_cast<HumanActivityMonitorManager*>(user_data);
225
226   if (!manager->wrist_up_event_callback_) {
227     LOGGER(ERROR) << "No WRIST_UP event callback registered, skipping.";
228     return;
229   }
230
231   picojson::value v = picojson::value(); // null value
232   manager->wrist_up_event_callback_(&v);
233 }
234
235 // HRM
236 PlatformResult HumanActivityMonitorManager::SetHrmListener(
237     JsonCallback callback) {
238   LoggerD("Enter");
239   sensor_h hrm_sensor;
240   int ret;
241
242   ret = sensor_get_default_sensor(SENSOR_HRM, &hrm_sensor);
243   if (ret != SENSOR_ERROR_NONE) {
244     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
245                           "Failed to get HRM sensor",
246                           ("Failed to get HRM sensor, error: %d",ret));
247   }
248
249   ret = sensor_create_listener(hrm_sensor, &hrm_sensor_listener_);
250   if (ret != SENSOR_ERROR_NONE) {
251     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
252                           "Failed to create HRM sensor listener",
253                           ("Failed to create HRM sensor listener, error: %d",ret));
254   }
255
256   ret = sensor_listener_set_event_cb(hrm_sensor_listener_,
257                                      0,
258                                      OnHrmSensorEvent,
259                                      this);
260   if (ret != SENSOR_ERROR_NONE) {
261     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
262                           "Failed to set HRM sensor listener",
263                           ("Failed to set HRM sensor listener, error: %d",ret));
264   }
265
266   ret = sensor_listener_start(hrm_sensor_listener_);
267   if (ret != SENSOR_ERROR_NONE) {
268     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
269                           "Failed to start HRM sensor listener",
270                           ("Failed to start HRM sensor listener, error: %d",ret));
271   }
272
273   hrm_event_callback_ = callback;
274
275   return PlatformResult(ErrorCode::NO_ERROR);
276 }
277
278 PlatformResult HumanActivityMonitorManager::UnsetHrmListener() {
279   LoggerD("Enter");
280
281   if (hrm_sensor_listener_) {
282     int ret = sensor_listener_stop(hrm_sensor_listener_);
283     if (ret != SENSOR_ERROR_NONE) {
284       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
285                             "Failed to stop HRM sensor",
286                             ("Failed to stop HRM sensor, error: "%d,ret));
287     }
288
289     ret = sensor_listener_unset_event_cb(hrm_sensor_listener_);
290     if (ret != SENSOR_ERROR_NONE) {
291       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
292                             "Failed to unset HRM sensor listener",
293                             ("Failed to unset HRM sensor listener, error: %d",ret));
294     }
295
296     ret = sensor_destroy_listener(hrm_sensor_listener_);
297     if (ret != SENSOR_ERROR_NONE) {
298       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
299                             "Failed to destroy HRM sensor listener",
300                             ("Failed to destroy HRM sensor listener, error: %d",ret));
301     }
302   }
303
304   hrm_event_callback_ = nullptr;
305
306   return PlatformResult(ErrorCode::NO_ERROR);
307 }
308
309 static PlatformResult ConvertHrmEvent(sensor_event_s* event,
310                                       picojson::object* data) {
311   LOGGER(DEBUG) << "Sensor event:";
312   LOGGER(DEBUG) << "  |- accuracy: " << event->accuracy;
313   LOGGER(DEBUG) << "  |- timestamp: " << event->timestamp;
314   LOGGER(DEBUG) << "  |- value_count: " << event->value_count;
315
316   if (event->value_count < 2) {
317     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of HRM event");
318   }
319
320   LOGGER(DEBUG) << "  |- values[0]: " << event->values[0];
321   LOGGER(DEBUG) << "  |- values[1]: " << event->values[1];
322
323   float hr = floor( event->values[0] + 0.5); // heart beat rate 0 ~ 220 integer (bpm)
324
325   // there are no public native api for peak to peak interval.
326   // but RRI = (60 / HR) * 1000
327   // or unofficially values[1] is rri (0 ~ 5000 ms)
328   float rri = floor(event->values[1] + 0.5);
329
330
331   (*data)["heartRate"] = picojson::value(static_cast<double>(hr));
332   (*data)["rRInterval"] = picojson::value(static_cast<double>(rri));
333
334   return PlatformResult(ErrorCode::NO_ERROR);
335 }
336
337 void HumanActivityMonitorManager::OnHrmSensorEvent(
338     sensor_h /*sensor*/, sensor_event_s *event, void *user_data) {
339
340   LoggerD("Enter");
341   HumanActivityMonitorManager* manager =
342       static_cast<HumanActivityMonitorManager*>(user_data);
343
344   if (!manager->hrm_event_callback_) {
345     LOGGER(ERROR) << "No HRM event callback registered, skipping.";
346     return;
347   }
348
349   picojson::value hrm_data = picojson::value(picojson::object());
350   PlatformResult result = ConvertHrmEvent(event,
351                                           &hrm_data.get<picojson::object>());
352   if (!result) {
353     LOGGER(ERROR) << "Failed to convert HRM data: " << result.message();
354     return;
355   }
356
357   manager->hrm_event_callback_(&hrm_data);
358 }
359
360 PlatformResult HumanActivityMonitorManager::GetHrmData(picojson::value* data) {
361   LoggerD("Enter");
362   if (!hrm_sensor_listener_) {
363     return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
364   }
365
366   int ret;
367
368   sensor_event_s event;
369   ret = sensor_listener_read_data(hrm_sensor_listener_, &event);
370   if (ret != SENSOR_ERROR_NONE) {
371     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
372                           "Failed to get HRM sensor data",
373                           ("Failed to get HRM sensor data, error: %d",ret));
374   }
375
376   *data = picojson::value(picojson::object());
377   PlatformResult result = ConvertHrmEvent(&event,
378                                           &data->get<picojson::object>());
379   if (!result) {
380     return result;
381   }
382
383   return PlatformResult(ErrorCode::NO_ERROR);
384 }
385
386 // GPS
387 PlatformResult HumanActivityMonitorManager::SetGpsListener(
388     JsonCallback callback) {
389   LoggerD("Enter");
390   int ret;
391
392   ret = location_manager_create(LOCATIONS_METHOD_GPS, &location_handle_);
393   if (ret != LOCATIONS_ERROR_NONE) {
394     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
395                           "Failed to create location manager",
396                           ("Failed to create location manager, error: %d",ret));
397   }
398
399   ret = location_manager_set_location_batch_cb(location_handle_,
400                                                OnGpsEvent,
401                                                1, // batch_interval
402                                                120, // batch_period
403                                                this);
404   if (ret != LOCATIONS_ERROR_NONE) {
405     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
406                           "Failed to set location listener",
407                           ("Failed to set location listener, error: %d",ret));
408   }
409
410   ret = location_manager_start_batch(location_handle_);
411   if (ret != LOCATIONS_ERROR_NONE) {
412     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
413                           "Failed to start location manager",
414                           ("Failed to start location manager, error: %d",ret));
415   }
416
417   gps_event_callback_ = callback;
418
419   return PlatformResult(ErrorCode::NO_ERROR);
420 }
421
422 PlatformResult HumanActivityMonitorManager::UnsetGpsListener() {
423   LoggerD("Enter");
424
425   if (location_handle_) {
426     int ret = location_manager_stop_batch(location_handle_);
427     if (ret != LOCATIONS_ERROR_NONE) {
428       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
429                             "Failed to stop location manager",
430                             ("Failed to stop location manager, error: %d",ret));
431     }
432
433     ret = location_manager_unset_location_batch_cb(location_handle_);
434     if (ret != LOCATIONS_ERROR_NONE) {
435       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
436                             "Failed to unset location listener",
437                             ("Failed to unset location listener, error: %d",ret));
438     }
439
440     ret = location_manager_destroy(location_handle_);
441     if (ret != LOCATIONS_ERROR_NONE) {
442       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
443                             "Failed to destroy location manager",
444                             ("Failed to destroy location manager, error: %d",ret));
445     }
446   }
447
448   gps_event_callback_ = nullptr;
449
450   return PlatformResult(ErrorCode::NO_ERROR);
451 }
452
453 static bool ConvertGpsEvent(double latitude, double longitude, double altitude,
454                             double speed, double direction, double horizontal,
455                             double vertical, time_t timestamp,
456                             void* user_data) {
457   LoggerD("Enter");
458   picojson::array* gps_info_array = static_cast<picojson::array*>(user_data);
459
460   picojson::value gps_info = picojson::value(picojson::object());
461   picojson::object& gps_info_o = gps_info.get<picojson::object>();
462
463   gps_info_o["latitude"] = picojson::value(latitude);
464   gps_info_o["longitude"] = picojson::value(longitude);
465   gps_info_o["altitude"] = picojson::value(altitude);
466   gps_info_o["speed"] = picojson::value(speed);
467   // TODO(r.galka) errorRange not available in CAPI
468   gps_info_o["errorRange"] = picojson::value(static_cast<double>(0));
469   gps_info_o["timestamp"] = picojson::value(static_cast<double>(timestamp));
470
471   gps_info_array->push_back(gps_info);
472
473   return true;
474 }
475
476 void HumanActivityMonitorManager::OnGpsEvent(int num_of_location,
477                                              void *user_data) {
478   LoggerD("Enter");
479   HumanActivityMonitorManager* manager =
480       static_cast<HumanActivityMonitorManager*>(user_data);
481
482   if (!manager->gps_event_callback_) {
483     LOGGER(ERROR) << "No GPS event callback registered, skipping.";
484     return;
485   }
486
487   if (0 == num_of_location) {
488     LOGGER(ERROR) << "No GPS locations available, skipping.";
489     return;
490   }
491
492   picojson::value gps_info = picojson::value(picojson::array());
493   int ret = location_manager_foreach_location_batch(
494       manager->location_handle_,
495       ConvertGpsEvent,
496       &gps_info.get<picojson::array>());
497   if (ret != LOCATIONS_ERROR_NONE) {
498     LOGGER(ERROR) << "Failed to convert location, error: " << ret;
499     return;
500   }
501
502   manager->gps_event_callback_(&gps_info);
503 }
504
505 PlatformResult HumanActivityMonitorManager::GetGpsData(picojson::value* data) {
506   LoggerD("Enter");
507   if (!location_handle_) {
508     return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
509   }
510
511   int ret;
512   double altitude, latitude, longitude, climb,
513       direction, speed, horizontal, vertical;
514   location_accuracy_level_e level;
515   time_t timestamp;
516   ret = location_manager_get_location(location_handle_, &altitude, &latitude,
517                                       &longitude, &climb, &direction, &speed,
518                                       &level, &horizontal, &vertical,
519                                       &timestamp);
520   if (ret != LOCATIONS_ERROR_NONE) {
521     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to get location",
522                               ("Failed to get location, error: %d",ret));
523   }
524
525   *data = picojson::value(picojson::array());
526   ConvertGpsEvent(latitude, longitude, altitude, speed, direction, horizontal,
527                   vertical, timestamp, &data->get<picojson::array>());
528
529   return PlatformResult(ErrorCode::NO_ERROR);
530 }
531
532 }  // namespace humanactivitymonitor
533 }  // namespace extension