Merge branch 'tizen_3.0' into tizen_4.0 65/152965/1 accepted/tizen/4.0/unified/20170929.075732 submit/tizen_4.0/20170927.114247
authorPiotr Kosko <p.kosko@samsung.com>
Wed, 27 Sep 2017 11:26:28 +0000 (13:26 +0200)
committerPiotr Kosko <p.kosko@samsung.com>
Wed, 27 Sep 2017 11:26:28 +0000 (13:26 +0200)
Conflicts:
packaging/webapi-plugins.spec

Change-Id: I4396c1ca3a1415cfbe4cd9ca0edc9351b5053615

63 files changed:
packaging/webapi-plugins.spec
src/alarm/alarm.gyp
src/alarm/alarm_api.js
src/alarm/alarm_instance.cc
src/alarm/alarm_manager.cc
src/alarm/alarm_manager.h
src/alarm/alarm_utils.cc
src/alarm/alarm_utils.h
src/application/application.gyp
src/application/application_api.js
src/application/application_instance.cc
src/application/application_instance.h
src/application/application_manager.cc
src/application/application_manager.h
src/archive/filesystem_node.cc
src/bluetooth/bluetooth.gyp
src/common/GDBus/auto_gen_interface.c
src/common/GDBus/auto_gen_interface.h
src/common/GDBus/gdbus_powerwrapper.cc
src/common/common.gyp
src/datacontrol/datacontrol_api.js
src/datacontrol/datacontrol_instance.cc
src/datacontrol/datacontrol_instance.h
src/download/download_instance.cc
src/filesystem/filesystem_manager.cc
src/filesystem/filesystem_stat.cc
src/humanactivitymonitor/gesture_manager.cc [new file with mode: 0644]
src/humanactivitymonitor/gesture_manager.h [new file with mode: 0644]
src/humanactivitymonitor/humanactivitymonitor.gyp
src/humanactivitymonitor/humanactivitymonitor_api.js
src/humanactivitymonitor/humanactivitymonitor_instance.cc
src/humanactivitymonitor/humanactivitymonitor_instance.h
src/nfc/nfc.gyp
src/nfc/nfc_adapter.cc
src/nfc/nfc_adapter.h
src/nfc/nfc_api.js
src/nfc/nfc_instance.cc
src/nfc/nfc_instance.h
src/nfc/nfc_util.cc
src/nfc/nfc_util.h
src/notification/common_notification.cc [new file with mode: 0644]
src/notification/common_notification.h [new file with mode: 0644]
src/notification/notification.gyp
src/notification/notification_api.js
src/notification/notification_extension.cc
src/notification/notification_instance.cc
src/notification/notification_instance.h
src/notification/notification_manager.cc
src/notification/notification_manager.h
src/notification/status_notification.cc
src/notification/status_notification.h
src/notification/user_notification.cc [new file with mode: 0644]
src/notification/user_notification.h [new file with mode: 0644]
src/power/power.gyp
src/preference/preference.gyp
src/push/push.gyp
src/sensor/sensor_api.js
src/sensor/sensor_service.cc
src/systeminfo/systeminfo.gyp
src/systeminfo/systeminfo_api.js
src/systeminfo/systeminfo_device_capability.cc
src/systeminfo/systeminfo_properties_manager.cc
src/utils/utils_api.js

index 21b2d7f..ea2275c 100644 (file)
@@ -1,7 +1,5 @@
 %bcond_with wayland
 
-%{!?profile:%define profile tv}
-
 %define _manifestdir %{TZ_SYS_RW_PACKAGES}
 %define _desktop_icondir %{TZ_SYS_SHARE}/icons/default/small
 
@@ -17,354 +15,339 @@ Group:      Development/Libraries
 Summary:    Tizen Web APIs implemented
 Source0:    %{name}-%{version}.tar.gz
 
-%ifarch %{arm} aarch64
-# ARM
-%define tizen_is_emulator           0
-%else
-# I586
-%define tizen_is_emulator           1
-%endif
-
-%if "%{_repository}" == "arm64-wayland"
-# 64bit
-%define tizen_is_arm64           1
-%else
-# 32bit
-%define tizen_is_arm64           0
-%endif
-
 ####################################################################
 #       Common Profile : artik                                     #
 ####################################################################
-%if "%{?profile}" == "common"
-
-%define tizen_privilege_engine                        CYNARA
-
-%define tizen_feature_account_support                 0
-%define tizen_feature_alarm_support                   1
-%define tizen_feature_app_control_settings_support    1
-%define tizen_feature_application_support             1
-%define tizen_feature_archive_support                 0
-%define tizen_feature_badge_support                   0
-%define tizen_feature_bluetooth_support               1
-%define tizen_feature_bookmark_support                0
-%define tizen_feature_calendar_support                0
-%define tizen_feature_contact_support                 0
-%define tizen_feature_content_support                 1
-%define tizen_feature_datacontrol_support             0
-%define tizen_feature_datasync_support                0
-%define tizen_feature_download_support                1
-%define tizen_feature_exif_support                    1
-%define tizen_feature_feedback_support                0
-%define tizen_feature_filesystem_support              1
-%define tizen_feature_fm_radio_support                0
-%define tizen_feature_ham_support                     0
-%define tizen_feature_iotcon_support                  0
-%define tizen_feature_location_batch                  0
-%define tizen_feature_key_manager_support             0
-%define tizen_feature_media_controller_support        0
-%define tizen_feature_media_key_support               0
-%define tizen_feature_message_port_support            1
-%define tizen_feature_messaging_support               0
-%define tizen_feature_nfc_emulation_support           0
-%define tizen_feature_nfc_support                     0
-%define tizen_feature_notification_support            0
-%define tizen_feature_package_support                 1
-%define tizen_feature_player_util_support             0
-%define tizen_feature_power_support                   0
-%define tizen_feature_preference_support              0
-%define tizen_feature_push_support                    0
-%define tizen_feature_se_support                      0
-%define tizen_feature_sensor_support                  0
-%define tizen_feature_sound_support                   1
-%define tizen_feature_system_info_support             1
-%define tizen_feature_system_setting_support          0
-%define tizen_feature_telephony_support               0
-%define tizen_feature_time_support                    1
-%define tizen_feature_web_setting_support             0
-%define tizen_feature_widget_service_support          0
-%define tizen_feature_wi_fi_support                   1
-%define tizen_feature_inputdevice_support             0
-%define tizen_feature_callhistory_support             0
-%define tizen_feature_nbs_support                     0
-%define tizen_feature_tvinputdevice_support           0
-
-%endif # tizen_profile_common
+
+%define tizen_common_privilege_engine                        CYNARA
+
+%define tizen_common_feature_account_support                 0
+%define tizen_common_feature_alarm_support                   1
+%define tizen_common_feature_app_control_settings_support    1
+%define tizen_common_feature_application_support             1
+%define tizen_common_feature_archive_support                 0
+%define tizen_common_feature_badge_support                   0
+%define tizen_common_feature_bluetooth_support               1
+%define tizen_common_feature_bookmark_support                0
+%define tizen_common_feature_calendar_support                0
+%define tizen_common_feature_contact_support                 0
+%define tizen_common_feature_content_support                 1
+%define tizen_common_feature_datacontrol_support             0
+%define tizen_common_feature_datasync_support                0
+%define tizen_common_feature_download_support                1
+%define tizen_common_feature_exif_support                    1
+%define tizen_common_feature_feedback_support                0
+%define tizen_common_feature_filesystem_support              1
+%define tizen_common_feature_fm_radio_support                0
+%define tizen_common_feature_ham_support                     0
+%define tizen_common_feature_iotcon_support                  0
+%define tizen_common_feature_location_batch                  0
+%define tizen_common_feature_key_manager_support             0
+%define tizen_common_feature_media_controller_support        0
+%define tizen_common_feature_media_key_support               0
+%define tizen_common_feature_message_port_support            1
+%define tizen_common_feature_messaging_support               0
+%define tizen_common_feature_nfc_emulation_support           0
+%define tizen_common_feature_nfc_support                     0
+%define tizen_common_feature_notification_support            0
+%define tizen_common_feature_package_support                 1
+%define tizen_common_feature_player_util_support             0
+%define tizen_common_feature_power_support                   0
+%define tizen_common_feature_preference_support              0
+%define tizen_common_feature_push_support                    0
+%define tizen_common_feature_se_support                      0
+%define tizen_common_feature_sensor_support                  0
+%define tizen_common_feature_sound_support                   1
+%define tizen_common_feature_system_info_support             1
+%define tizen_common_feature_system_setting_support          0
+%define tizen_common_feature_telephony_support               0
+%define tizen_common_feature_time_support                    1
+%define tizen_common_feature_web_setting_support             0
+%define tizen_common_feature_widget_service_support          0
+%define tizen_common_feature_wi_fi_support                   1
+%define tizen_common_feature_inputdevice_support             0
+%define tizen_common_feature_callhistory_support             0
+%define tizen_common_feature_nbs_support                     0
+%define tizen_common_feature_tvinputdevice_support           0
+
 
 ####################################################################
 #       Mobile Profile :  TM1(32bit), Redwood(SM-Z910F), KIRAN(Z130H)          #
 #                         TM2(64bit)
 ####################################################################
-%if "%{?profile}" == "mobile"
-
-%define tizen_privilege_engine                        CYNARA
-
-%define tizen_feature_account_support                 1
-%define tizen_feature_alarm_support                   1
-%define tizen_feature_app_control_settings_support    1
-%define tizen_feature_application_support             1
-%define tizen_feature_archive_support                 1
-%define tizen_feature_badge_support                   1
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_bluetooth_support               0
-%else
-%define tizen_feature_bluetooth_support               1
-%endif
-%define tizen_feature_bookmark_support                1
-%define tizen_feature_calendar_support                1
-%define tizen_feature_contact_support                 1
-%define tizen_feature_content_support                 1
-%define tizen_feature_datacontrol_support             1
-%define tizen_feature_datasync_support                0
-%define tizen_feature_download_support                1
-%define tizen_feature_exif_support                    1
-%define tizen_feature_feedback_support                1
-%define tizen_feature_filesystem_support              1
 
-# FM radio feature
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_fm_radio_support                1
-%else
-%if 0%{?tizen_is_arm64}
-%define tizen_feature_fm_radio_support                0
+%define tizen_mobile_privilege_engine                        CYNARA
+
+%define tizen_mobile_feature_account_support                 1
+%define tizen_mobile_feature_alarm_support                   1
+%define tizen_mobile_feature_app_control_settings_support    1
+%define tizen_mobile_feature_application_support             1
+%define tizen_mobile_feature_archive_support                 1
+%define tizen_mobile_feature_badge_support                   1
+%define tizen_mobile_feature_bluetooth_support               1
+%define tizen_mobile_feature_bookmark_support                1
+%define tizen_mobile_feature_calendar_support                1
+%define tizen_mobile_feature_contact_support                 1
+%define tizen_mobile_feature_content_support                 1
+%define tizen_mobile_feature_datacontrol_support             1
+%define tizen_mobile_feature_datasync_support                0
+%define tizen_mobile_feature_download_support                1
+%define tizen_mobile_feature_exif_support                    1
+%define tizen_mobile_feature_feedback_support                1
+%define tizen_mobile_feature_filesystem_support              1
+
+%ifarch aarch64
+%define tizen_mobile_feature_fm_radio_support                0
 %else
-%define tizen_feature_fm_radio_support                1
-%endif
+%define tizen_mobile_feature_fm_radio_support                1
 %endif
 
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_ham_support                     1
-%else
-%define tizen_feature_ham_support                     0
-%endif
-%define tizen_feature_iotcon_support                  1
-%define tizen_feature_location_batch                  0
-%define tizen_feature_key_manager_support             1
-%define tizen_feature_media_controller_support        1
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_media_key_support               0
-%else
-%define tizen_feature_media_key_support               1
-%endif
-%define tizen_feature_message_port_support            1
-%define tizen_feature_messaging_support               1
+%define tizen_mobile_feature_ham_support                     0
 
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_nfc_emulation_support           0
-%define tizen_feature_nfc_support                     1
-%else
-%define tizen_feature_nfc_emulation_support           0
-%define tizen_feature_nfc_support                     0
-%endif
-%define tizen_feature_notification_support            1
-%define tizen_feature_package_support                 1
-%define tizen_feature_player_util_support             1
-%define tizen_feature_power_support                   1
-%define tizen_feature_preference_support              1
-%define tizen_feature_push_support                    1
+%define tizen_mobile_feature_iotcon_support                  1
+%define tizen_mobile_feature_location_batch                  0
+%define tizen_mobile_feature_key_manager_support             1
+%define tizen_mobile_feature_media_controller_support        1
+
+%define tizen_mobile_feature_media_key_support               1
+
+%define tizen_mobile_feature_message_port_support            1
+%define tizen_mobile_feature_messaging_support               1
+
+%define tizen_mobile_feature_nfc_emulation_support           0
+%define tizen_mobile_feature_nfc_support                     0
+
+%define tizen_mobile_feature_notification_support            1
+%define tizen_mobile_feature_package_support                 1
+%define tizen_mobile_feature_player_util_support             1
+%define tizen_mobile_feature_power_support                   1
+%define tizen_mobile_feature_preference_support              1
+%define tizen_mobile_feature_push_support                    1
 
 # secure element feature
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_se_support                      0
-%else
-%if 0%{?tizen_is_arm64}
-%define tizen_feature_se_support                      0
+%ifarch aarch64
+%define tizen_mobile_feature_se_support                      0
 %else
-%define tizen_feature_se_support                      1
-%endif
+%define tizen_mobile_feature_se_support                      1
 %endif
 
-%define tizen_feature_sensor_support                  1
-%define tizen_feature_sound_support                   1
-%define tizen_feature_system_info_support             1
-%define tizen_feature_system_setting_support          1
+%define tizen_mobile_feature_sensor_support                  1
+%define tizen_mobile_feature_sound_support                   1
+%define tizen_mobile_feature_system_info_support             1
+%define tizen_mobile_feature_system_setting_support          1
 
 # telephony feature
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_telephony_support               1
+%ifarch aarch64
+%define tizen_mobile_feature_telephony_support               0
+%define tizen_mobile_feature_callhistory_support             0
+%define tizen_mobile_feature_nbs_support                     0
 %else
-%if 0%{?tizen_is_arm64}
-%define tizen_feature_telephony_support               0
-%else
-%define tizen_feature_telephony_support               1
-%endif
+%define tizen_mobile_feature_telephony_support               1
+%define tizen_mobile_feature_callhistory_support             1
+%define tizen_mobile_feature_nbs_support                     1
 %endif
 
-%define tizen_feature_time_support                    1
-%define tizen_feature_web_setting_support             1
-%define tizen_feature_widget_service_support          1
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_wi_fi_support                   0
-%else
-%define tizen_feature_wi_fi_support                   1
-%endif
-%define tizen_feature_inputdevice_support             1
+%define tizen_mobile_feature_time_support                    1
+%define tizen_mobile_feature_web_setting_support             1
+%define tizen_mobile_feature_widget_service_support          1
 
-%if 0%{?tizen_feature_telephony_support}
-%define tizen_feature_callhistory_support             1
-%define tizen_feature_nbs_support                     1
-%else
-%define tizen_feature_callhistory_support             0
-%define tizen_feature_nbs_support                     0
-%endif
+%define tizen_mobile_feature_wi_fi_support                   1
 
-%define tizen_feature_tvinputdevice_support           0
+%define tizen_mobile_feature_inputdevice_support             1
+
+%define tizen_mobile_feature_tvinputdevice_support           0
 
-%endif # tizen_profile_mobile
 
 ####################################################################
-#       Wearable Profile :  B2 / TW1                      #
+#       Wearable Profile :  B2 / TW2                      #
 ####################################################################
-%if "%{?profile}" == "wearable"
 
-%define tizen_privilege_engine                        CYNARA
+%define tizen_wearable_privilege_engine                        CYNARA
 
 # Account API is optional in Tizen Wearable Profile.
-%define tizen_feature_account_support                 0
+%define tizen_wearable_feature_account_support                 1
 
-%define tizen_feature_alarm_support                   1
-%define tizen_feature_app_control_settings_support    1
-%define tizen_feature_application_support             1
+%define tizen_wearable_feature_alarm_support                   1
+%define tizen_wearable_feature_app_control_settings_support    1
+%define tizen_wearable_feature_application_support             1
 
 # Archive API is optional in Tizen Wearable Profile.
-%define tizen_feature_archive_support                 1
+%define tizen_wearable_feature_archive_support                 1
 
 # Badge API is mandatory in Tizen Wearable Profile.
-%define tizen_feature_badge_support                   1
+%define tizen_wearable_feature_badge_support                   1
 
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_bluetooth_support               0
-%else
-%define tizen_feature_bluetooth_support               1
-%endif
+%define tizen_wearable_feature_bluetooth_support               1
 
 # Bookmark API is optional in Tizen Wearable Profile.
-%define tizen_feature_bookmark_support                0
+%define tizen_wearable_feature_bookmark_support                0
 
 # Calendar API is mandatory in Tizen Wearable Profile.
-%define tizen_feature_calendar_support                0
-%define tizen_feature_contact_support                 0
-%define tizen_feature_content_support                 1
-%define tizen_feature_datacontrol_support             1
-%define tizen_feature_datasync_support                0
-%define tizen_feature_download_support                1
-%define tizen_feature_exif_support                    1
-%define tizen_feature_feedback_support                1
-%define tizen_feature_filesystem_support              1
-%define tizen_feature_fm_radio_support                0
-%define tizen_feature_ham_support                     1
-%define tizen_feature_iotcon_support                  1
-%define tizen_feature_location_batch                  0
-%define tizen_feature_media_controller_support        1
+%define tizen_wearable_feature_calendar_support                1
+%define tizen_wearable_feature_contact_support                 1
+%define tizen_wearable_feature_content_support                 1
+%define tizen_wearable_feature_datacontrol_support             1
+%define tizen_wearable_feature_datasync_support                0
+%define tizen_wearable_feature_download_support                1
+%define tizen_wearable_feature_exif_support                    1
+%define tizen_wearable_feature_feedback_support                1
+%define tizen_wearable_feature_filesystem_support              1
+%define tizen_wearable_feature_fm_radio_support                0
+%define tizen_wearable_feature_ham_support                     1
+%define tizen_wearable_feature_iotcon_support                  1
+%define tizen_wearable_feature_location_batch                  0
+%define tizen_wearable_feature_media_controller_support        1
 
 # MediayKey API is optional in Tizen Wearable Profile.
 # tizen.org/feature/network.bluetooth.audio.media is required for MediayKey API
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_media_key_support               0
-%else
-%define tizen_feature_media_key_support               1
-%endif
-%define tizen_feature_key_manager_support             1
-%define tizen_feature_message_port_support            1
-%define tizen_feature_messaging_support               0
-%define tizen_feature_nfc_emulation_support           0
-%define tizen_feature_nfc_support                     1
-%define tizen_feature_notification_support            1
-%define tizen_feature_package_support                 1
-%define tizen_feature_player_util_support             1
-%define tizen_feature_power_support                   1
-%define tizen_feature_preference_support              1
-%define tizen_feature_push_support                    1
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_se_support                      0
-%else
-%define tizen_feature_se_support                      1
-%endif
-%define tizen_feature_sensor_support                  1
-%define tizen_feature_sound_support                   1
-%define tizen_feature_system_info_support             1
-%define tizen_feature_system_setting_support          1
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_telephony_support               1
-%else
-%define tizen_feature_telephony_support               0
-%endif
-%define tizen_feature_time_support                    1
-%define tizen_feature_web_setting_support             0
-%define tizen_feature_widget_service_support          1
-%define tizen_feature_wi_fi_support                   1
-%define tizen_feature_inputdevice_support             1
-%define tizen_feature_tvinputdevice_support           0
+%define tizen_wearable_feature_media_key_support               1
+%define tizen_wearable_feature_key_manager_support             1
+%define tizen_wearable_feature_message_port_support            1
+%define tizen_wearable_feature_messaging_support               0
+%define tizen_wearable_feature_nfc_emulation_support           0
+%define tizen_wearable_feature_nfc_support                     1
+%define tizen_wearable_feature_notification_support            1
+%define tizen_wearable_feature_package_support                 1
+%define tizen_wearable_feature_player_util_support             1
+%define tizen_wearable_feature_power_support                   1
+%define tizen_wearable_feature_preference_support              1
+%define tizen_wearable_feature_push_support                    1
+%define tizen_wearable_feature_se_support                      1
+# sensor module is not supported in TW2 devices
+%define tizen_wearable_feature_sensor_support                  0
+%define tizen_wearable_feature_sound_support                   1
+%define tizen_wearable_feature_system_info_support             1
+%define tizen_wearable_feature_system_setting_support          1
 
 #- telephony related APIs
 # CallHistory API is optional in Tizen Wearable Profile.
 # NetworkBearerSelection API is optional in Tizen Wearable Profile.
-%if 0%{?tizen_feature_telephony_support}
-%define    tizen_feature_callhistory_support          1
-%define    tizen_feature_nbs_support                  1
-%else
-%define    tizen_feature_callhistory_support          0
-%define    tizen_feature_nbs_support                  0
-%endif
+%define tizen_wearable_feature_telephony_support               0
+%define tizen_wearable_feature_callhistory_support             0
+%define tizen_wearable_feature_nbs_support                     0
+
+%define tizen_wearable_feature_time_support                    1
+%define tizen_wearable_feature_web_setting_support             0
+%define tizen_wearable_feature_widget_service_support          1
+%define tizen_wearable_feature_wi_fi_support                   1
+%define tizen_wearable_feature_inputdevice_support             1
+%define tizen_wearable_feature_tvinputdevice_support           0
 
-%endif # tizen_profile_wearable
 
 ####################################################################
 #       TV Profile                                                 #
 ####################################################################
-%if "%{?profile}" == "tv"
-
-%define tizen_privilege_engine                        CYNARA
-
-%define tizen_feature_account_support                 0
-%define tizen_feature_alarm_support                   1
-%define tizen_feature_app_control_settings_support    0
-%define tizen_feature_application_support             1
-%define tizen_feature_archive_support                 1
-%define tizen_feature_badge_support                   0
-%define tizen_feature_bluetooth_support               0
-%define tizen_feature_bookmark_support                0
-%define tizen_feature_calendar_support                0
-%define tizen_feature_callhistory_support             0
-%define tizen_feature_contact_support                 0
-%define tizen_feature_content_support                 1
-%define tizen_feature_datacontrol_support             1
-%define tizen_feature_datasync_support                0
-%define tizen_feature_download_support                1
-%define tizen_feature_exif_support                    1
-%define tizen_feature_feedback_support                0
-%define tizen_feature_filesystem_support              1
-%define tizen_feature_fm_radio_support                0
-%define tizen_feature_ham_support                     0
-%define tizen_feature_iotcon_support                  1
-%define tizen_feature_key_manager_support             1
-%define tizen_feature_media_controller_support        0
-%define tizen_feature_media_key_support               1
-%define tizen_feature_message_port_support            1
-%define tizen_feature_messaging_support               0
-%define tizen_feature_nbs_support                     0
-%define tizen_feature_nfc_emulation_support           0
-%define tizen_feature_nfc_support                     0
-%define tizen_feature_notification_support            0
-%define tizen_feature_package_support                 1
-%define tizen_feature_player_util_support             0
-%define tizen_feature_power_support                   0
-%define tizen_feature_preference_support              0
-%define tizen_feature_push_support                    1
-%define tizen_feature_se_support                      0
-%define tizen_feature_sensor_support                  0
-%define tizen_feature_sound_support                   0
-%define tizen_feature_system_info_support             1
-%define tizen_feature_system_setting_support          0
-%define tizen_feature_telephony_support               0
-%define tizen_feature_time_support                    1
-%define tizen_feature_web_setting_support             1
-%define tizen_feature_widget_service_support          0
-%define tizen_feature_wi_fi_support                   1
-%define tizen_feature_inputdevice_support             0
-%define tizen_feature_tvinputdevice_support           1
-
-%endif # tizen_profile_tv
+
+%define tizen_tv_privilege_engine                        CYNARA
+
+%define tizen_tv_feature_account_support                 0
+%define tizen_tv_feature_alarm_support                   1
+%define tizen_tv_feature_app_control_settings_support    0
+%define tizen_tv_feature_application_support             1
+%define tizen_tv_feature_archive_support                 1
+%define tizen_tv_feature_badge_support                   0
+%define tizen_tv_feature_bluetooth_support               0
+%define tizen_tv_feature_bookmark_support                0
+%define tizen_tv_feature_calendar_support                0
+%define tizen_tv_feature_callhistory_support             0
+%define tizen_tv_feature_contact_support                 0
+%define tizen_tv_feature_content_support                 1
+%define tizen_tv_feature_datacontrol_support             1
+%define tizen_tv_feature_datasync_support                0
+%define tizen_tv_feature_download_support                1
+%define tizen_tv_feature_exif_support                    1
+%define tizen_tv_feature_feedback_support                0
+%define tizen_tv_feature_filesystem_support              1
+%define tizen_tv_feature_fm_radio_support                0
+%define tizen_tv_feature_ham_support                     0
+%define tizen_tv_feature_iotcon_support                  1
+%define tizen_tv_feature_key_manager_support             1
+%define tizen_tv_feature_media_controller_support        0
+%define tizen_tv_feature_media_key_support               0
+%define tizen_tv_feature_message_port_support            1
+%define tizen_tv_feature_messaging_support               0
+%define tizen_tv_feature_nbs_support                     0
+%define tizen_tv_feature_nfc_emulation_support           0
+%define tizen_tv_feature_nfc_support                     0
+%define tizen_tv_feature_notification_support            0
+%define tizen_tv_feature_package_support                 1
+%define tizen_tv_feature_player_util_support             0
+%define tizen_tv_feature_power_support                   0
+%define tizen_tv_feature_preference_support              0
+%define tizen_tv_feature_push_support                    1
+%define tizen_tv_feature_se_support                      0
+%define tizen_tv_feature_sensor_support                  0
+%define tizen_tv_feature_sound_support                   0
+%define tizen_tv_feature_system_info_support             1
+%define tizen_tv_feature_system_setting_support          0
+%define tizen_tv_feature_telephony_support               0
+%define tizen_tv_feature_time_support                    1
+%define tizen_tv_feature_web_setting_support             1
+%define tizen_tv_feature_widget_service_support          0
+%define tizen_tv_feature_wi_fi_support                   1
+%define tizen_tv_feature_inputdevice_support             0
+%define tizen_tv_feature_tvinputdevice_support           1
+
+# common, or "unified (undefined)"
+%define unified_build   1
+# GBM Product Build Optimization. Not for 4.0 Public Unified Build.
+%if "%{?profile}" == "tv" || "%{?profile}" == "mobile" || "%{?profile}" == "wearable" || "%{?profile}" == "ivi"
+%define unified_build  0
+%endif
+
+# GBM Product Build Optimization. Not for 4.0 Public Unified Build.
+%if "%{?profile}" == "tv" || "%{?profile}" == "mobile" || "%{?profile}" == "wearable" || "%{?profile}" == "common"
+%define tizen_privilege_engine                        %{expand:%tizen_%{?profile}_privilege_engine}
+
+%define tizen_feature_account_support                 %{expand:%tizen_%{?profile}_feature_account_support}
+%define tizen_feature_alarm_support                   %{expand:%tizen_%{?profile}_feature_alarm_support}
+%define tizen_feature_app_control_settings_support    %{expand:%tizen_%{?profile}_feature_app_control_settings_support}
+%define tizen_feature_application_support             %{expand:%tizen_%{?profile}_feature_application_support}
+%define tizen_feature_archive_support                 %{expand:%tizen_%{?profile}_feature_archive_support}
+%define tizen_feature_badge_support                   %{expand:%tizen_%{?profile}_feature_badge_support}
+%define tizen_feature_bluetooth_support               %{expand:%tizen_%{?profile}_feature_bluetooth_support}
+%define tizen_feature_bookmark_support                %{expand:%tizen_%{?profile}_feature_bookmark_support}
+%define tizen_feature_calendar_support                %{expand:%tizen_%{?profile}_feature_calendar_support}
+%define tizen_feature_contact_support                 %{expand:%tizen_%{?profile}_feature_contact_support}
+%define tizen_feature_content_support                 %{expand:%tizen_%{?profile}_feature_content_support}
+%define tizen_feature_datacontrol_support             %{expand:%tizen_%{?profile}_feature_datacontrol_support}
+%define tizen_feature_datasync_support                %{expand:%tizen_%{?profile}_feature_datasync_support}
+%define tizen_feature_download_support                %{expand:%tizen_%{?profile}_feature_download_support}
+%define tizen_feature_exif_support                    %{expand:%tizen_%{?profile}_feature_exif_support}
+%define tizen_feature_feedback_support                %{expand:%tizen_%{?profile}_feature_feedback_support}
+%define tizen_feature_filesystem_support              %{expand:%tizen_%{?profile}_feature_filesystem_support}
+%define tizen_feature_fm_radio_support                %{expand:%tizen_%{?profile}_feature_fm_radio_support}
+%define tizen_feature_ham_support                     %{expand:%tizen_%{?profile}_feature_ham_support}
+%define tizen_feature_iotcon_support                  %{expand:%tizen_%{?profile}_feature_iotcon_support}
+%define tizen_feature_location_batch                  %{expand:%tizen_%{?profile}_feature_location_batch}
+%define tizen_feature_key_manager_support             %{expand:%tizen_%{?profile}_feature_key_manager_support}
+%define tizen_feature_media_controller_support        %{expand:%tizen_%{?profile}_feature_media_controller_support}
+%define tizen_feature_media_key_support               %{expand:%tizen_%{?profile}_feature_media_key_support}
+%define tizen_feature_message_port_support            %{expand:%tizen_%{?profile}_feature_message_port_support}
+%define tizen_feature_messaging_support               %{expand:%tizen_%{?profile}_feature_messaging_support}
+%define tizen_feature_nfc_emulation_support           %{expand:%tizen_%{?profile}_feature_nfc_emulation_support}
+%define tizen_feature_nfc_support                     %{expand:%tizen_%{?profile}_feature_nfc_support}
+%define tizen_feature_notification_support            %{expand:%tizen_%{?profile}_feature_notification_support}
+%define tizen_feature_package_support                 %{expand:%tizen_%{?profile}_feature_package_support}
+%define tizen_feature_player_util_support             %{expand:%tizen_%{?profile}_feature_player_util_support}
+%define tizen_feature_power_support                   %{expand:%tizen_%{?profile}_feature_power_support}
+%define tizen_feature_preference_support              %{expand:%tizen_%{?profile}_feature_preference_support}
+%define tizen_feature_push_support                    %{expand:%tizen_%{?profile}_feature_push_support}
+%define tizen_feature_se_support                      %{expand:%tizen_%{?profile}_feature_se_support}
+%define tizen_feature_sensor_support                  %{expand:%tizen_%{?profile}_feature_sensor_support}
+%define tizen_feature_sound_support                   %{expand:%tizen_%{?profile}_feature_sound_support}
+%define tizen_feature_system_info_support             %{expand:%tizen_%{?profile}_feature_system_info_support}
+%define tizen_feature_system_setting_support          %{expand:%tizen_%{?profile}_feature_system_setting_support}
+%define tizen_feature_telephony_support               %{expand:%tizen_%{?profile}_feature_telephony_support}
+%define tizen_feature_time_support                    %{expand:%tizen_%{?profile}_feature_time_support}
+%define tizen_feature_web_setting_support             %{expand:%tizen_%{?profile}_feature_web_setting_support}
+%define tizen_feature_widget_service_support          %{expand:%tizen_%{?profile}_feature_widget_service_support}
+%define tizen_feature_wi_fi_support                   %{expand:%tizen_%{?profile}_feature_wi_fi_support}
+%define tizen_feature_inputdevice_support             %{expand:%tizen_%{?profile}_feature_inputdevice_support}
+%define tizen_feature_callhistory_support             %{expand:%tizen_%{?profile}_feature_callhistory_support}
+%define tizen_feature_nbs_support                     %{expand:%tizen_%{?profile}_feature_nbs_support}
+%define tizen_feature_tvinputdevice_support           %{expand:%tizen_%{?profile}_feature_tvinputdevice_support}
+%endif
 
 BuildRequires: pkgconfig(security-privilege-manager)
 BuildRequires: ninja
@@ -396,7 +379,7 @@ BuildRequires: pkgconfig(capi-network-bluetooth)
 BuildRequires: pkgconfig(capi-network-wifi-manager)
 BuildRequires: pkgconfig(tapi)
 BuildRequires: pkgconfig(libpcrecpp)
-BuildRequires: pkgconfig(capi-appfw-application)
+BuildRequires: pkgconfig(capi-appfw-app-common)
 BuildRequires: pkgconfig(capi-appfw-app-manager)
 BuildRequires: pkgconfig(capi-appfw-package-manager)
 BuildRequires: pkgconfig(capi-content-media-content)
@@ -417,138 +400,228 @@ BuildRequires: pkgconfig(wayland-client)
 BuildRequires: pkgconfig(security-privilege-checker)
 %endif
 
-%if "%{?tizen_privilege_engine}" == "CYNARA"
+%if "%{?tizen_privilege_engine}" == "CYNARA" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(cynara-client)
 BuildRequires: pkgconfig(libsmack)
 %endif
 
-%if 0%{?tizen_feature_account_support}
+%if "%{?tizen_feature_account_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(accounts-svc)
 %endif
 
-%if 0%{?tizen_feature_alarm_support}
+%if "%{?tizen_feature_alarm_support}" == "1" || "%{?unified_build}" == "1"
+BuildRequires: pkgconfig(capi-appfw-app-control)
+BuildRequires: pkgconfig(capi-appfw-application)
 BuildRequires: pkgconfig(capi-appfw-alarm)
 BuildRequires: pkgconfig(alarm-service)
 %endif
 
-%if 0%{?tizen_feature_bookmark_support}
+%if "%{?tizen_feature_application_support}" == "1" || "%{?unified_build}" == "1"
+BuildRequires: pkgconfig(capi-appfw-app-control)
+BuildRequires: pkgconfig(capi-appfw-event)
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "mobile"
+BuildRequires: pkgconfig(capi-context)
+%endif
+
+%endif
+
+%if "%{?tizen_feature_bluetooth_support}" == "1" || "%{?unified_build}" == "1"
+BuildRequires: pkgconfig(capi-appfw-app-control)
+%endif
+
+%if "%{?tizen_feature_bookmark_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-web-bookmark)
 BuildRequires: pkgconfig(bookmark-adaptor)
 %endif
 
-%if 0%{?tizen_feature_datacontrol_support}
+%if "%{?tizen_feature_datacontrol_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-data-control)
 %endif
 
-%if 0%{?tizen_feature_download_support}
+%if "%{?tizen_feature_download_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-web-url-download)
 %endif
 
-%if 0%{?tizen_feature_ham_support}
+%if "%{?tizen_feature_ham_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(motion)
 BuildRequires: pkgconfig(capi-system-sensor)
 BuildRequires: pkgconfig(capi-location-manager)
 BuildRequires: pkgconfig(sensor)
 %endif
 
-%if 0%{?tizen_feature_iotcon_support}
+%if "%{?tizen_feature_iotcon_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(iotcon)
 %endif
 
-%if 0%{?tizen_feature_player_util_support}
+%if "%{?tizen_feature_player_util_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(chromium-efl)
 %endif
 
-%if 0%{?tizen_feature_power_support}
-BuildRequires: pkgconfig(deviced)
-%endif
-
-%if 0%{?tizen_feature_power_support}
+%if "%{?tizen_feature_power_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-appfw-application)
 %endif
 
-%if 0%{?tizen_feature_push_support}
+%if "%{?tizen_feature_push_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(push)
+BuildRequires: pkgconfig(capi-appfw-app-control)
 %endif
 
-%if 0%{?tizen_feature_key_manager_support}
+%if "%{?tizen_feature_key_manager_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(key-manager)
 %endif
 
-%if 0%{?tizen_feature_media_controller_support}
+%if "%{?tizen_feature_media_controller_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-media-controller)
 %endif
 
-%if 0%{?tizen_feature_messaging_support}
+%if "%{?tizen_feature_messaging_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(ecore-file)
 BuildRequires:  pkgconfig(email-service)
 BuildRequires:  pkgconfig(msg-service)
 BuildRequires:  pkgconfig(db-util)
 %endif
 
-%if 0%{?tizen_feature_badge_support}
+%if "%{?tizen_feature_badge_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(badge)
 %endif
 
-%if 0%{?tizen_feature_calendar_support}
+%if "%{?tizen_feature_calendar_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(calendar-service2)
 %endif
 
-%if 0%{?tizen_feature_contact_support}
+%if "%{?tizen_feature_contact_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(contacts-service2)
 %endif
 
-%if 0%{?tizen_feature_callhistory_support}
+%if "%{?tizen_feature_callhistory_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(contacts-service2)
 %endif
 
-%if 0%{?tizen_feature_exif_support}
+%if "%{?tizen_feature_exif_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(libexif)
 %endif
 
-%if 0%{?tizen_feature_nfc_support}
+%if "%{?tizen_feature_nfc_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(capi-network-nfc)
+BuildRequires:  pkgconfig(capi-appfw-app-control)
 %endif
 
-%if 0%{?tizen_feature_fm_radio_support}
+%if "%{?tizen_feature_fm_radio_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-media-radio)
 %endif
 
-%if 0%{?tizen_feature_feedback_support}
+%if "%{?tizen_feature_feedback_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(feedback)
 %endif
 
-%if 0%{?tizen_feature_se_support}
+%if "%{?tizen_feature_se_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(capi-network-smartcard)
 %endif
 
-%if 0%{?tizen_feature_message_port_support}
+%if "%{?tizen_feature_message_port_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-message-port)
 %endif
 
-%if 0%{?tizen_feature_notification_support}
+%if "%{?tizen_feature_notification_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(notification)
+BuildRequires: pkgconfig(capi-appfw-app-control)
+%endif
+
+%if "%{?tizen_feature_preference_support}" == "1" || "%{?unified_build}" == "1"
+BuildRequires: pkgconfig(capi-appfw-preference)
 %endif
 
-%if 0%{?tizen_feature_sound_support}
+%if "%{?tizen_feature_sound_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(capi-media-sound-manager)
 %endif
 
-%if 0%{?tizen_feature_sensor_support}
+%if "%{?tizen_feature_sensor_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(capi-system-sensor)
 %endif
 
-%if 0%{?tizen_feature_media_key_support}
+%if "%{?tizen_feature_media_key_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires:  pkgconfig(capi-system-media-key)
 %endif
 
-%if 0%{?tizen_feature_widget_service_support}
+%if "%{?tizen_feature_widget_service_support}" == "1" || "%{?unified_build}" == "1"
 BuildRequires: pkgconfig(widget_service)
 %endif
 
+Requires:      %{name}-compat = %{version}-%{release}
+%if "%{?unified_build}" == "1"
+Recommends:    %{name}-profile_common = %{version}-%{release}
+%endif
+
 %description
 Tizen Web APIs implemented.
 
+%package profile_common
+Summary:       webapi-plugin binaries for common profile
+Provides:      %{name}-compat = %{version}-%{release}
+Conflicts:     %{name}-profile_mobile
+Conflicts:     %{name}-profile_wearable
+Conflicts:     %{name}-profile_tv
+Conflicts:     %{name}-profile_ivi
+%description profile_common
+Tizen Web API implementation binaries for Tizen common profile.
+
+%package profile_mobile
+Summary:       webapi-plugin binaries for mobile profile
+Provides:      %{name}-compat = %{version}-%{release}
+Conflicts:     %{name}-profile_common
+Conflicts:     %{name}-profile_wearable
+Conflicts:     %{name}-profile_tv
+Conflicts:     %{name}-profile_ivi
+%description profile_mobile
+Tizen Web API implementation binaries for Tizen mobile profile.
+
+%ifarch %{ix86} x86_64
+%package mobile-extension-emulator
+Summary:       webapi-plugin binaries for mobile emulator
+Requires:      %{name}-profile_mobile = %{version}-%{release}
+%description mobile-extension-emulator
+Tizen Web API implementation binaries for Tizen mobile emulator.
+%endif
+
+%package profile_wearable
+Summary:       webapi-plugin binaries for wearable profile
+Provides:      %{name}-compat = %{version}-%{release}
+Conflicts:     %{name}-profile_mobile
+Conflicts:     %{name}-profile_common
+Conflicts:     %{name}-profile_tv
+Conflicts:     %{name}-profile_ivi
+%description profile_wearable
+Tizen Web API implementation binaries for Tizen wearable profile.
+
+%ifarch %{ix86} x86_64
+%package wearable-extension-emulator
+Summary:       webapi-plugin binaries for wearable emulator
+Requires:      %{name}-profile_wearable = %{version}-%{release}
+%description wearable-extension-emulator
+Tizen Web API implementation binaries for Tizen wearable emulator.
+%endif
+
+%package profile_tv
+Summary:       webapi-plugin binaries for tv profile
+Provides:      %{name}-compat = %{version}-%{release}
+Conflicts:     %{name}-profile_mobile
+Conflicts:     %{name}-profile_wearable
+Conflicts:     %{name}-profile_common
+Conflicts:     %{name}-profile_ivi
+%description profile_tv
+Tizen Web API implementation binaries for Tizen tv profile.
+
+%package profile_ivi
+Summary:       webapi-plugin binaries for ivi profile
+Provides:      %{name}-compat = %{version}-%{release}
+Conflicts:     %{name}-profile_mobile
+Conflicts:     %{name}-profile_wearable
+Conflicts:     %{name}-profile_tv
+Conflicts:     %{name}-profile_common
+%description profile_ivi
+Tizen Web API implementation binaries for Tizen ivi profile.
+
 %package devel
 Summary:    webapi-plugins development headers
 Group:      Development/Libraries
@@ -563,75 +636,541 @@ webapi-plugins development headers
 %build
 
 export GYP_GENERATORS='ninja'
+
+%if "%{?unified_build}" == "1"
+# Build All Profiles
+
+# Mobile
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=mobile -Dprivilege_engine=%{tizen_mobile_privilege_engine}"
+GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
+GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
+
+# feature flags
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_mobile_feature_account_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_mobile_feature_alarm_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_mobile_feature_app_control_settings_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_mobile_feature_application_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_mobile_feature_archive_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_mobile_feature_badge_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_mobile_feature_bluetooth_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_mobile_feature_bookmark_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_mobile_feature_calendar_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_mobile_feature_callhistory_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_mobile_feature_contact_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_mobile_feature_content_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_mobile_feature_datacontrol_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_mobile_feature_datasync_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_mobile_feature_download_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_mobile_feature_exif_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_feedback_support=%{?tizen_mobile_feature_feedback_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_mobile_feature_filesystem_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_mobile_feature_fm_radio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_mobile_feature_ham_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_iotcon_support=%{?tizen_mobile_feature_iotcon_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_mobile_feature_location_batch}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_mobile_feature_key_manager_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_mobile_feature_media_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_mobile_feature_media_key_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_mobile_feature_message_port_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_mobile_feature_messaging_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_mobile_feature_nbs_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_mobile_feature_nfc_emulation_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_mobile_feature_nfc_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_mobile_feature_notification_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_mobile_feature_package_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_player_util_support=%{?tizen_mobile_feature_player_util_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_mobile_feature_power_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_preference_support=%{?tizen_mobile_feature_preference_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_mobile_feature_push_support}"
+#GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_mobile_feature_sap_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_mobile_feature_sensor_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_mobile_feature_se_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_mobile_feature_sound_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_mobile_feature_system_info_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_mobile_feature_system_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_mobile_feature_telephony_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{?tizen_mobile_feature_time_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_mobile_feature_inputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_mobile_feature_web_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_mobile_feature_widget_service_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_mobile_feature_wi_fi_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_mobile_feature_tvinputdevice_support}"
+
+./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+pushd out
+mv Default bin_mobile
+popd
+
+# mobile-extension-emulator
+%ifarch %{ix86} x86_64
+
+%define tizen_mobile_feature_bluetooth_support               0
+
+# FM radio feature
+%define tizen_mobile_feature_fm_radio_support                1
+
+%define tizen_mobile_feature_ham_support                     1
+%define tizen_mobile_feature_media_key_support               0
+%define tizen_mobile_feature_nfc_emulation_support           0
+%define tizen_mobile_feature_nfc_support                     1
+
+# secure element feature
+%define tizen_mobile_feature_se_support                      0
+
+# telephony feature
+%define tizen_mobile_feature_telephony_support               1
+%define tizen_mobile_feature_callhistory_support             1
+%define tizen_mobile_feature_nbs_support                     1
+
+%define tizen_mobile_feature_wi_fi_support                   0
+
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=mobile -Dprivilege_engine=%{tizen_mobile_privilege_engine}"
+GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
+GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
+
+# feature flags
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_mobile_feature_account_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_mobile_feature_alarm_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_mobile_feature_app_control_settings_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_mobile_feature_application_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_mobile_feature_archive_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_mobile_feature_badge_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_mobile_feature_bluetooth_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_mobile_feature_bookmark_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_mobile_feature_calendar_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_mobile_feature_callhistory_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_mobile_feature_contact_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_mobile_feature_content_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_mobile_feature_datacontrol_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_mobile_feature_datasync_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_mobile_feature_download_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_mobile_feature_exif_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_feedback_support=%{?tizen_mobile_feature_feedback_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_mobile_feature_filesystem_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_mobile_feature_fm_radio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_mobile_feature_ham_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_iotcon_support=%{?tizen_mobile_feature_iotcon_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_mobile_feature_location_batch}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_mobile_feature_key_manager_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_mobile_feature_media_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_mobile_feature_media_key_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_mobile_feature_message_port_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_mobile_feature_messaging_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_mobile_feature_nbs_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_mobile_feature_nfc_emulation_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_mobile_feature_nfc_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_mobile_feature_notification_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_mobile_feature_package_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_player_util_support=%{?tizen_mobile_feature_player_util_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_mobile_feature_power_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_preference_support=%{?tizen_mobile_feature_preference_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_mobile_feature_push_support}"
+#GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_mobile_feature_sap_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_mobile_feature_sensor_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_mobile_feature_se_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_mobile_feature_sound_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_mobile_feature_system_info_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_mobile_feature_system_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_mobile_feature_telephony_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{?tizen_mobile_feature_time_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_mobile_feature_inputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_mobile_feature_web_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_mobile_feature_widget_service_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_mobile_feature_wi_fi_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_mobile_feature_tvinputdevice_support}"
+
+./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+pushd out
+mv Default bin_mobile_emulator
+popd
+%endif
+
+# WEARABLE
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=wearable -Dprivilege_engine=%{tizen_wearable_privilege_engine}"
+GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
+GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
+
+# feature flags
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_wearable_feature_account_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_wearable_feature_alarm_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_wearable_feature_app_control_settings_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_wearable_feature_application_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_wearable_feature_archive_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_wearable_feature_badge_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_wearable_feature_bluetooth_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_wearable_feature_bookmark_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_wearable_feature_calendar_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_wearable_feature_callhistory_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_wearable_feature_contact_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_wearable_feature_content_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_wearable_feature_datacontrol_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_wearable_feature_datasync_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_wearable_feature_download_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_wearable_feature_exif_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_feedback_support=%{?tizen_wearable_feature_feedback_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_wearable_feature_filesystem_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_wearable_feature_fm_radio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_wearable_feature_ham_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_iotcon_support=%{?tizen_wearable_feature_iotcon_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_wearable_feature_location_batch}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_wearable_feature_key_manager_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_wearable_feature_media_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_wearable_feature_media_key_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_wearable_feature_message_port_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_wearable_feature_messaging_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_wearable_feature_nbs_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_wearable_feature_nfc_emulation_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_wearable_feature_nfc_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_wearable_feature_notification_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_wearable_feature_package_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_player_util_support=%{?tizen_wearable_feature_player_util_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_wearable_feature_power_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_preference_support=%{?tizen_wearable_feature_preference_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_wearable_feature_push_support}"
+#GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_wearable_feature_sap_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_wearable_feature_sensor_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_wearable_feature_se_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_wearable_feature_sound_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_wearable_feature_system_info_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_wearable_feature_system_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_wearable_feature_telephony_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{?tizen_wearable_feature_time_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_wearable_feature_inputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_wearable_feature_web_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_wearable_feature_widget_service_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_wearable_feature_wi_fi_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_wearable_feature_tvinputdevice_support}"
+
+./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+pushd out
+mv Default bin_wearable
+popd
+
+# wearable-extension-emulator
+%ifarch %{ix86} x86_64
+
+%define tizen_wearable_feature_bluetooth_support             0
+
+# MediayKey API is optional in Tizen Wearable Profile.
+# tizen.org/feature/network.bluetooth.audio.media is required for MediayKey API
+%define tizen_wearable_feature_media_key_support             0
+
+#- telephony related APIs
+# CallHistory API is optional in Tizen Wearable Profile.
+# NetworkBearerSelection API is optional in Tizen Wearable Profile.
+%define tizen_wearable_feature_se_support                    0
+%define tizen_wearable_feature_telephony_support             1
+%define tizen_wearable_feature_callhistory_support           1
+%define tizen_wearable_feature_nbs_support                   1
+%define tizen_wearable_feature_sensor_support                1
+
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=wearable -Dprivilege_engine=%{tizen_wearable_privilege_engine}"
+GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
+GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
+
+# feature flags
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_wearable_feature_account_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_wearable_feature_alarm_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_wearable_feature_app_control_settings_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_wearable_feature_application_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_wearable_feature_archive_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_wearable_feature_badge_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_wearable_feature_bluetooth_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_wearable_feature_bookmark_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_wearable_feature_calendar_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_wearable_feature_callhistory_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_wearable_feature_contact_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_wearable_feature_content_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_wearable_feature_datacontrol_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_wearable_feature_datasync_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_wearable_feature_download_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_wearable_feature_exif_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_feedback_support=%{?tizen_wearable_feature_feedback_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_wearable_feature_filesystem_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_wearable_feature_fm_radio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_wearable_feature_ham_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_iotcon_support=%{?tizen_wearable_feature_iotcon_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_wearable_feature_location_batch}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_wearable_feature_key_manager_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_wearable_feature_media_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_wearable_feature_media_key_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_wearable_feature_message_port_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_wearable_feature_messaging_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_wearable_feature_nbs_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_wearable_feature_nfc_emulation_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_wearable_feature_nfc_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_wearable_feature_notification_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_wearable_feature_package_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_player_util_support=%{?tizen_wearable_feature_player_util_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_wearable_feature_power_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_preference_support=%{?tizen_wearable_feature_preference_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_wearable_feature_push_support}"
+#GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_wearable_feature_sap_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_wearable_feature_sensor_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_wearable_feature_se_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_wearable_feature_sound_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_wearable_feature_system_info_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_wearable_feature_system_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_wearable_feature_telephony_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{?tizen_wearable_feature_time_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_wearable_feature_inputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_wearable_feature_web_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_wearable_feature_widget_service_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_wearable_feature_wi_fi_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_wearable_feature_tvinputdevice_support}"
+
+./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+pushd out
+mv Default bin_wearable_emulator
+popd
+%endif
+
+# TV
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=tv -Dprivilege_engine=%{tizen_tv_privilege_engine}"
+GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
+GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
+
+# feature flags
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_tv_feature_account_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_tv_feature_alarm_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_tv_feature_app_control_settings_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_tv_feature_application_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_tv_feature_archive_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_tv_feature_badge_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_tv_feature_bluetooth_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_tv_feature_bookmark_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_tv_feature_calendar_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_tv_feature_callhistory_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_tv_feature_contact_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_tv_feature_content_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_tv_feature_datacontrol_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_tv_feature_datasync_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_tv_feature_download_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_tv_feature_exif_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_feedback_support=%{?tizen_tv_feature_feedback_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_tv_feature_filesystem_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_tv_feature_fm_radio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_tv_feature_ham_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_iotcon_support=%{?tizen_tv_feature_iotcon_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_tv_feature_location_batch}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_tv_feature_key_manager_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_tv_feature_media_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_tv_feature_media_key_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_tv_feature_message_port_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_tv_feature_messaging_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_tv_feature_nbs_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_tv_feature_nfc_emulation_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_tv_feature_nfc_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_tv_feature_notification_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_tv_feature_package_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_player_util_support=%{?tizen_tv_feature_player_util_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_tv_feature_power_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_preference_support=%{?tizen_tv_feature_preference_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_tv_feature_push_support}"
+#GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_tv_feature_sap_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_tv_feature_sensor_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_tv_feature_se_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_tv_feature_sound_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_tv_feature_system_info_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_tv_feature_system_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_tv_feature_telephony_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{?tizen_tv_feature_time_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_tv_feature_inputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_tv_feature_web_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_tv_feature_widget_service_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_tv_feature_wi_fi_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_tv_feature_tvinputdevice_support}"
+
+./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+pushd out
+mv Default bin_tv
+popd
+
+%endif
+
+# Unified: common/ Others: its own profile
+%if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "wearable" && "%{?profile}" != "ivi"
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=common -Dprivilege_engine=%{tizen_privilege_engine}"
+%else
 GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=%{profile} -Dprivilege_engine=%{tizen_privilege_engine}"
+%endif
 GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=%{display_type}"
 GYP_OPTIONS="$GYP_OPTIONS -Dcrosswalk_extensions_path=%{crosswalk_extensions_path}"
 
 # feature flags
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_is_emulator=%{?tizen_is_emulator}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_feature_account_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_feature_alarm_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_feature_app_control_settings_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_feature_application_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_feature_archive_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_feature_badge_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_feature_bluetooth_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_feature_bookmark_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_feature_calendar_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_feature_callhistory_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_feature_contact_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_feature_content_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_feature_datacontrol_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_feature_datasync_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_feature_download_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_feature_exif_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_feedback_support=%{?tizen_feature_feedback_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_feature_filesystem_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_feature_fm_radio_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_feature_ham_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_iotcon_support=%{?tizen_feature_iotcon_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_feature_location_batch}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_feature_key_manager_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_feature_media_controller_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_feature_media_key_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_feature_message_port_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_feature_messaging_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_feature_nbs_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_feature_nfc_emulation_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_feature_nfc_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_feature_notification_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_feature_package_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_player_util_support=%{?tizen_feature_player_util_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_feature_power_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_preference_support=%{?tizen_feature_preference_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_feature_push_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_feature_sap_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_feature_sensor_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_feature_se_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_feature_sound_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_feature_system_info_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_feature_system_setting_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_feature_telephony_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{?tizen_feature_time_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_feature_inputdevice_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_feature_web_setting_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_feature_widget_service_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_feature_wi_fi_support}"
-GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_feature_tvinputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_common_feature_account_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_common_feature_alarm_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_common_feature_app_control_settings_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_common_feature_application_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_common_feature_archive_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_common_feature_badge_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_common_feature_bluetooth_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_common_feature_bookmark_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_common_feature_calendar_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_common_feature_callhistory_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_common_feature_contact_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_common_feature_content_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_common_feature_datacontrol_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_common_feature_datasync_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_common_feature_download_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_common_feature_exif_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_feedback_support=%{?tizen_common_feature_feedback_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_common_feature_filesystem_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_common_feature_fm_radio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_common_feature_ham_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_iotcon_support=%{?tizen_common_feature_iotcon_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_common_feature_location_batch}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_common_feature_key_manager_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_common_feature_media_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_common_feature_media_key_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_common_feature_message_port_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_common_feature_messaging_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_common_feature_nbs_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_common_feature_nfc_emulation_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_common_feature_nfc_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_common_feature_notification_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_common_feature_package_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_player_util_support=%{?tizen_common_feature_player_util_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_common_feature_power_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_preference_support=%{?tizen_common_feature_preference_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_common_feature_push_support}"
+#GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_common_feature_sap_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_common_feature_sensor_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_common_feature_se_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_common_feature_sound_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_common_feature_system_info_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_common_feature_system_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_common_feature_telephony_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{?tizen_common_feature_time_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_common_feature_inputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_common_feature_web_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_common_feature_widget_service_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_common_feature_wi_fi_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_common_feature_tvinputdevice_support}"
 
 ./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
 
+%if "%{?profile}" != "mobile" && "%{?profile}" != "tv" && "%{?profile}" != "wearable" && "%{?profile}" != "ivi"
 ninja -C out/Default %{?_smp_mflags}
+pushd out
+mv Default bin_common
+ln -sf bin_common Default
+
+# IVI does not have independent configurations, yet.
+# Copying the whole result in order to support ivi subpacakge
+cp -R bin_common bin_ivi
+
+popd
+%else
+ninja -C out/Default %{?_smp_mflags}
+pushd out
+mv Default bin_%{?profile}
+ln -sf bin_%{?profile} Default
+popd
+%endif
 
 %install
-mkdir -p %{buildroot}/usr/share/license
-cp LICENSE %{buildroot}/usr/share/license/%{name}
-cat LICENSE.BSD-3-Clause >> %{buildroot}/usr/share/license/%{name}
-cat LICENSE.MIT >> %{buildroot}/usr/share/license/%{name}
 
 # Extensions.
 mkdir -p %{buildroot}%{crosswalk_extensions_path}
-install -p -m 644 out/Default/libtizen*.so %{buildroot}%{crosswalk_extensions_path}
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "common"
+mkdir -p %{buildroot}%{crosswalk_extensions_path}/common
+install -p -m 644 out/bin_common/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/common
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/common out/Default/desc_gentool \
+       %{crosswalk_extensions_path}/common \
+       %{buildroot}%{crosswalk_extensions_path}/common > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/common/plugins.json
+%endif
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "mobile"
+mkdir -p %{buildroot}%{crosswalk_extensions_path}/mobile
+install -p -m 644 out/bin_mobile/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/mobile
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/mobile out/Default/desc_gentool \
+       %{crosswalk_extensions_path}/mobile \
+       %{buildroot}%{crosswalk_extensions_path}/mobile > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/mobile/plugins.json
+
+# mobile-extension-emulator
+%ifarch %{ix86} x86_64
+mkdir -p %{buildroot}%{crosswalk_extensions_path}/mobile_emulator
+install -p -m 644 out/bin_mobile_emulator/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/mobile_emulator
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/mobile_emulator out/Default/desc_gentool \
+       %{crosswalk_extensions_path}/mobile_emulator \
+       %{buildroot}%{crosswalk_extensions_path}/mobile_emulator > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/mobile_emulator/plugins.json
+%endif // mobile-extension-emulator
+
+%endif // mobile
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "wearable"
+mkdir -p %{buildroot}%{crosswalk_extensions_path}/wearable
+install -p -m 644 out/bin_wearable/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/wearable
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/wearable out/Default/desc_gentool \
+       %{crosswalk_extensions_path}/wearable \
+       %{buildroot}%{crosswalk_extensions_path}/wearable > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/wearable/plugins.json
+
+# wearable-extension-emulator
+%ifarch %{ix86} x86_64
+mkdir -p %{buildroot}%{crosswalk_extensions_path}/wearable_emulator
+install -p -m 644 out/bin_wearable_emulator/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/wearable_emulator
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/mobile_emulator out/Default/desc_gentool \
+       %{crosswalk_extensions_path}/wearable_emulator \
+       %{buildroot}%{crosswalk_extensions_path}/wearable_emulator > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/wearable_emulator/plugins.json
+%endif // wearable-extension-emulator
+
+%endif // wearable
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "tv"
+mkdir -p %{buildroot}%{crosswalk_extensions_path}/tv
+install -p -m 644 out/bin_tv/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/tv
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/tv out/Default/desc_gentool \
+       %{crosswalk_extensions_path}/tv \
+       %{buildroot}%{crosswalk_extensions_path}/tv > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/tv/plugins.json
+%endif
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "ivi"
+mkdir -p %{buildroot}%{crosswalk_extensions_path}/ivi
+install -p -m 644 out/bin_ivi/libtizen*.so %{buildroot}%{crosswalk_extensions_path}/ivi
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path}/ivi out/Default/desc_gentool \
+       %{crosswalk_extensions_path}/ivi \
+       %{buildroot}%{crosswalk_extensions_path}/ivi > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/ivi/plugins.json
+%endif
 
 # devel files
 mkdir -p %{buildroot}%{_libdir}/pkgconfig
@@ -652,20 +1191,123 @@ cp -a tools/gyp %{buildroot}%{_includedir}/%{name}/tools/gyp
 cp -a tools/slimit %{buildroot}%{_includedir}/%{name}/tools/slimit
 cp -a out/Default/desc_gentool %{buildroot}%{_includedir}/%{name}/tools/desc_gentool
 
-# execute desc_gentool
-LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{crosswalk_extensions_path} out/Default/desc_gentool \
-       %{crosswalk_extensions_path} \
-       %{buildroot}%{crosswalk_extensions_path} > plugins.json
+%files
+%manifest webapi-plugins.manifest
+%license LICENSE
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "common"
+%post profile_common
+ln -sf %{crosswalk_extensions_path}/common/* %{crosswalk_extensions_path}
+%preun profile_common
+# This is an un-installation.
+if [ "$1" == "0" ]; then
+  rm %{crosswalk_extensions_path}/libtizen*.so
+  rm %{crosswalk_extensions_path}/plugins.json
+fi
+%files profile_common
+%dir %{crosswalk_extensions_path}/common/
+%{crosswalk_extensions_path}/common/libtizen*.so
+%{crosswalk_extensions_path}/common/plugins.json
+%manifest webapi-plugins.manifest
+%endif
 
-# temporary plugins description for lazy loading
-install -p -m 644 plugins.json %{buildroot}%{crosswalk_extensions_path}/plugins.json
+%if "%{?unified_build}" == "1" || "%{?profile}" == "mobile"
+%post profile_mobile
+ln -sf %{crosswalk_extensions_path}/mobile/* %{crosswalk_extensions_path}
+%preun profile_mobile
+# This is an un-installation.
+if [ "$1" == "0" ]; then
+  rm %{crosswalk_extensions_path}/libtizen*.so
+  rm %{crosswalk_extensions_path}/plugins.json
+fi
+%files profile_mobile
+%dir %{crosswalk_extensions_path}/mobile/
+%{crosswalk_extensions_path}/mobile/libtizen*.so
+%{crosswalk_extensions_path}/mobile/plugins.json
+%manifest webapi-plugins.manifest
 
+# mobile-extension-emulator
+%ifarch %{ix86} x86_64
+%post mobile-extension-emulator
+ln -sf %{crosswalk_extensions_path}/mobile_emulator/* %{crosswalk_extensions_path}
+%preun mobile-extension-emulator
+# This is an un-installation.
+if [ "$1" == "0" ]; then
+  rm %{crosswalk_extensions_path}/libtizen*.so
+  rm %{crosswalk_extensions_path}/plugins.json
+fi
+%files mobile-extension-emulator
+%dir %{crosswalk_extensions_path}/mobile_emulator/
+%{crosswalk_extensions_path}/mobile_emulator/libtizen*.so
+%{crosswalk_extensions_path}/mobile_emulator/plugins.json
+%manifest webapi-plugins.manifest
+%endif // mobile-extension-emulator
+%endif // mobile
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "wearable"
+%post profile_wearable
+ln -sf %{crosswalk_extensions_path}/wearable/* %{crosswalk_extensions_path}
+%preun profile_wearable
+# This is an un-installation.
+if [ "$1" == "0" ]; then
+  rm %{crosswalk_extensions_path}/libtizen*.so
+  rm %{crosswalk_extensions_path}/plugins.json
+fi
+%files profile_wearable
+%dir %{crosswalk_extensions_path}/wearable/
+%{crosswalk_extensions_path}/wearable/libtizen*.so
+%{crosswalk_extensions_path}/wearable/plugins.json
+%manifest webapi-plugins.manifest
 
-%files
-%{crosswalk_extensions_path}/libtizen*.so
-%{crosswalk_extensions_path}/plugins.json
-%{_datadir}/license/%{name}
+# wearable-extension-emulator
+%ifarch %{ix86} x86_64
+%post wearable-extension-emulator
+ln -sf %{crosswalk_extensions_path}/wearable_emulator/* %{crosswalk_extensions_path}
+%preun wearable-extension-emulator
+# This is an un-installation.
+if [ "$1" == "0" ]; then
+  rm %{crosswalk_extensions_path}/libtizen*.so
+  rm %{crosswalk_extensions_path}/plugins.json
+fi
+%files wearable-extension-emulator
+%dir %{crosswalk_extensions_path}/wearable_emulator/
+%{crosswalk_extensions_path}/wearable_emulator/libtizen*.so
+%{crosswalk_extensions_path}/wearable_emulator/plugins.json
 %manifest webapi-plugins.manifest
+%endif // wearable-extension-emulator
+%endif // wearable
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "tv"
+%post profile_tv
+ln -sf %{crosswalk_extensions_path}/tv/* %{crosswalk_extensions_path}
+%preun profile_tv
+# This is an un-installation.
+if [ "$1" == "0" ]; then
+  rm %{crosswalk_extensions_path}/libtizen*.so
+  rm %{crosswalk_extensions_path}/plugins.json
+fi
+%files profile_tv
+%dir %{crosswalk_extensions_path}/tv/
+%{crosswalk_extensions_path}/tv/libtizen*.so
+%{crosswalk_extensions_path}/tv/plugins.json
+%manifest webapi-plugins.manifest
+%endif
+
+%if "%{?unified_build}" == "1" || "%{?profile}" == "ivi"
+%post profile_ivi
+ln -sf %{crosswalk_extensions_path}/ivi/* %{crosswalk_extensions_path}
+%preun profile_ivi
+# This is an un-installation.
+if [ "$1" == "0" ]; then
+  rm %{crosswalk_extensions_path}/libtizen*.so
+  rm %{crosswalk_extensions_path}/plugins.json
+fi
+%files profile_ivi
+%dir %{crosswalk_extensions_path}/ivi/
+%{crosswalk_extensions_path}/ivi/libtizen*.so
+%{crosswalk_extensions_path}/ivi/plugins.json
+%manifest webapi-plugins.manifest
+%endif
 
 %files devel
 %{_includedir}/*
index dc1135a..5d212ec 100644 (file)
@@ -8,6 +8,7 @@
       'type': 'loadable_module',
       'dependencies': [
         '../common/common.gyp:tizen_common',
+        '../notification/notification.gyp:tizen_notification',
       ],
       'sources': [
         'alarm_api.js',
@@ -25,6 +26,8 @@
           'variables': {
             'packages': [
               'capi-appfw-alarm',
+              'capi-appfw-app-control',
+              'capi-appfw-application',
             ]
           },
         }],
index 47725dc..cfa5f98 100755 (executable)
@@ -66,6 +66,20 @@ function UpdateInternalData_(internal, data) {
     }
 }
 
+var LogManager = function() {
+    this.enableLog = true;
+};
+
+LogManager.prototype.allow = function() {
+    this.enableLog = true;
+};
+
+LogManager.prototype.disallow = function() {
+    this.enableLog = false;
+};
+
+var _warningLogs = new LogManager();
+
 //class AlarmManager ////////////////////////////////////////////////////
 AlarmManager.prototype.add = function () {
     var args = AV.validateMethod(arguments, [
@@ -116,6 +130,47 @@ AlarmManager.prototype.add = function () {
     }
 };
 
+AlarmManager.prototype.addAlarmNotification = function() {
+    var args = AV.validateMethod(arguments, [
+    {
+        name: 'alarm',
+        type: AV.Types.PLATFORM_OBJECT,
+        values: [tizen.AlarmRelative, tizen.AlarmAbsolute]
+    }, {
+        name: 'notification',
+        type: AV.Types.PLATFORM_OBJECT,
+        values: [tizen.StatusNotification, tizen.UserNotification]
+    }]);
+
+    var type = null, milliseconds = 0;
+    if (args.alarm instanceof tizen.AlarmRelative) {
+        type = 'AlarmRelative';
+    } else if (args.alarm instanceof tizen.AlarmAbsolute) {
+        type = 'AlarmAbsolute';
+        milliseconds = args.alarm.date.getTime();
+    }
+
+    var callArgs = {};
+    callArgs.alarm = args.alarm;
+    callArgs.type = type;
+    callArgs.notification = args.notification;
+    callArgs.milliseconds = Converter.toString(milliseconds);
+    callArgs.isPeriodSet = !T.isNullOrUndefined(args.alarm.period);
+
+    //add marker for UserNotification implementation
+    callArgs.newImpl = (callArgs.notification instanceof tizen.UserNotification);
+
+    var result = native.callSync('AlarmManager_addAlarmNotification', callArgs);
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    }
+    else {
+        _edit.allow();
+        UpdateInternalData_(args.alarm, native.getResultObject(result));
+        _edit.disallow();
+    }
+};
+
 AlarmManager.prototype.remove = function () {
     var args = AV.validateMethod(arguments, [
         {
@@ -153,14 +208,71 @@ AlarmManager.prototype.get = function () {
         throw native.getErrorObject(result);
     } else {
         result = native.getResultObject(result);
+
+        var alarm;
+        _warningLogs.disallow();
         if ('AlarmRelative' === result.type) {
-            return new tizen.AlarmRelative(result.delay, result.period, InternalData_(result));
+            alarm = new tizen.AlarmRelative(result.delay, result.period, InternalData_(result));
         } else {
             var date = new Date(result.year, result.month, result.day,
                     result.hour, result.min, result.sec);
 
-            return new tizen.AlarmAbsolute(date, result.second, InternalData_(result));
+            alarm = new tizen.AlarmAbsolute(date, result.second, InternalData_(result));
+        }
+        _warningLogs.allow();
+        return alarm;
+    }
+};
+
+function _prepareAppControl(noti) {
+  if (!noti || !noti.actions || !noti.actions.appControl) {
+    privUtils_.log("Do nothing - appControl is NOT present");
+    return;
+  }
+  if (!T.isNullOrUndefined(noti.actions.appControl.operation)) {
+    noti.actions.appControl = new tizen.ApplicationControl(
+        noti.actions.appControl.operation,
+        noti.actions.appControl.uri,
+        noti.actions.appControl.mime,
+        noti.actions.appControl.category,
+        noti.actions.appControl.data,
+        noti.actions.appControl.launchMode);
+  }
+}
+
+function _prepareDetailInfo(noti) {
+  if (!noti || !noti.textContents || !noti.textContents.detailInfo) {
+    console.log("Do nothing - detailInfo is NOT present");
+    return;
+  }
+  var detailInfo = noti.textContents.detailInfo;
+  if (T.isArray(detailInfo)) {
+    var _d = [];
+    for (var i = 0; i < detailInfo.length; ++i) {
+      _d.push(new tizen.NotificationDetailInfo(detailInfo[i].mainText,
+          detailInfo[i].subText || null));
+    }
+    noti.textContents.detailInfo = _d;
+  }
+}
+
+AlarmManager.prototype.getAlarmNotification = function () {
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'id',
+            type : AV.Types.STRING,
         }
+    ]);
+
+    var result = native.callSync('AlarmManager_getAlarmNotification', {id: Number(args.id)});
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        var noti = native.getResultObject(result);
+        _prepareAppControl(noti);
+        _prepareDetailInfo(noti);
+        return new tizen.UserNotification(noti.userType, noti.title, noti);
     }
 };
 
@@ -172,6 +284,7 @@ AlarmManager.prototype.getAll = function () {
     } else {
         var data = native.getResultObject(result);
         var md = [];
+        _warningLogs.disallow();
         data.forEach(function (i) {
             if ('AlarmRelative'=== i.type) {
                 md.push(new tizen.AlarmRelative(i.delay, i.period, InternalData_(i)));
@@ -181,6 +294,7 @@ AlarmManager.prototype.getAll = function () {
                 md.push(new tizen.AlarmAbsolute(date, i.second, InternalData_(i)));
             }
         });
+        _warningLogs.allow();
         return md;
     }
 };
@@ -302,6 +416,10 @@ tizen.AlarmAbsolute = function(date, second, internal) {
             } else {
                 if(!T.isNullOrUndefined(second)){
                     m_period = Converter.toLong(second);
+                    if(_warningLogs.enableLog){
+                        privUtils_.warn("This Constructor is deprecated since Tizen 4.0." +
+                        " Please consider using other constructors or other type of an alarm.");
+                    }
                 }
             }
         }
index f246c30..e1b4008 100644 (file)
@@ -29,10 +29,14 @@ AlarmInstance::AlarmInstance() {
   using namespace std::placeholders;
 
   RegisterSyncHandler("AlarmManager_add", std::bind(&AlarmManager::Add, &manager_, _1, _2));
+  RegisterSyncHandler("AlarmManager_addAlarmNotification",
+                      std::bind(&AlarmManager::AddAlarmNotification, &manager_, _1, _2));
   RegisterSyncHandler("AlarmManager_remove", std::bind(&AlarmManager::Remove, &manager_, _1, _2));
   RegisterSyncHandler("AlarmManager_removeAll",
                       std::bind(&AlarmManager::RemoveAll, &manager_, _1, _2));
   RegisterSyncHandler("AlarmManager_get", std::bind(&AlarmManager::Get, &manager_, _1, _2));
+  RegisterSyncHandler("AlarmManager_getAlarmNotification",
+                      std::bind(&AlarmManager::GetAlarmNotification, &manager_, _1, _2));
   RegisterSyncHandler("AlarmManager_getAll", std::bind(&AlarmManager::GetAll, &manager_, _1, _2));
   // AlarmRelative
   RegisterSyncHandler("AlarmRelative_getRemainingSeconds",
index 9921a27..e8d2087 100644 (file)
@@ -20,6 +20,7 @@
 #include <app.h>
 #include <app_alarm.h>
 #include <app_control_internal.h>
+#include <notification_internal.h>
 
 #include "common/converter.h"
 #include "common/logger.h"
 #include "alarm_instance.h"
 #include "alarm_utils.h"
 
+#include "notification/common_notification.h"
+#include "notification/status_notification.h"
+#include "notification/user_notification.h"
+
 using namespace common;
 using namespace common::tools;
 
@@ -38,6 +43,7 @@ namespace alarm {
 namespace {
 const int kDateSize = 22;  //"yyy mm dd hh mm ss dd" e.g 115 11 28 11 25 50 -1
 const std::string kPrivilegeAlarm = "http://tizen.org/privilege/alarm";
+const std::string kPrivilegeNotification = "http://tizen.org/privilege/notification";
 
 const std::string kAlarmRelative = "AlarmRelative";
 const std::string kAlarmAbsolute = "AlarmAbsolute";
@@ -54,14 +60,6 @@ const char* kAlarmTypeValueAbsolute = "ABSOLUTE";
 const char* kAlarmTypeValueRelative = "RELATIVE";
 
 const char* kAlarmRelativeDelayKey = "RELATIVE_DELAY";
-
-const char* kSundayShort = "SU";
-const char* kMondayShort = "MO";
-const char* kTuesdayShort = "TU";
-const char* kWednesdayShort = "WE";
-const char* kThuesdayShort = "TH";
-const char* kFridayShort = "FR";
-const char* kSaturdayShort = "SA";
 }
 
 AlarmManager::AlarmManager() {
@@ -218,30 +216,12 @@ void AlarmManager::Add(const picojson::value& args, picojson::object& out) {
                !(it_daysOfTheWeek->second.get<picojson::array>()).empty()) {
       app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
                                  kAlarmAbsoluteReccurrenceTypeByDayValue);
-      picojson::array days_of_the_week = it_daysOfTheWeek->second.get<picojson::array>();
+      const picojson::array& days_of_the_week = it_daysOfTheWeek->second.get<picojson::array>();
       int repeat_value = 0;
-      for (auto iter = days_of_the_week.begin(); iter != days_of_the_week.end(); ++iter) {
-        auto day = (*iter).get<std::string>();
-        if (kSundayShort == day) {
-          repeat_value |= ALARM_WEEK_FLAG_SUNDAY;
-        } else if (kMondayShort == day) {
-          repeat_value |= ALARM_WEEK_FLAG_MONDAY;
-        } else if (kTuesdayShort == day) {
-          repeat_value |= ALARM_WEEK_FLAG_TUESDAY;
-        } else if (kWednesdayShort == day) {
-          repeat_value |= ALARM_WEEK_FLAG_WEDNESDAY;
-        } else if (kThuesdayShort == day) {
-          repeat_value |= ALARM_WEEK_FLAG_THURSDAY;
-        } else if (kFridayShort == day) {
-          repeat_value |= ALARM_WEEK_FLAG_FRIDAY;
-        } else if (kSaturdayShort == day) {
-          repeat_value |= ALARM_WEEK_FLAG_SATURDAY;
-        } else {
-          LogAndReportError(
-              PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Invalid days of the week value."),
-              &out);
-          return;
-        }
+      PlatformResult result = util::ArrayDaysToMask(days_of_the_week, &repeat_value);
+      if (!result) {
+        LogAndReportError(PlatformResult(result.error_code(), result.message()), &out);
+        return;
       }
       ret = alarm_schedule_with_recurrence_week_flag(app_control, &start_date, repeat_value,
                                                      &alarm_id);
@@ -263,6 +243,228 @@ void AlarmManager::Add(const picojson::value& args, picojson::object& out) {
   ReportSuccess(result, out);
 }
 
+void AlarmManager::AddAlarmNotification(const picojson::value& args, picojson::object& out) {
+  using namespace extension::notification;
+  LoggerD("Entered");
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeAlarm, &out);
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeNotification, &out);
+
+  if (!args.contains("alarm") || !args.contains("notification")) {
+    LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
+                      &out);
+    return;
+  }
+
+  const picojson::object& alarm = args.get("alarm").get<picojson::object>();
+
+  std::string alarm_type;
+  if (args.contains("type")) {
+    alarm_type = args.get("type").get<std::string>();
+  }
+
+  notification_h notification_handle = nullptr;
+  app_control_h app_control = nullptr;
+
+  SCOPE_EXIT {
+    notification_free(notification_handle);
+    app_control_destroy(app_control);
+  };
+
+  using namespace std::placeholders;
+  GetHandleFromJsonFun impl{};
+  if (args.contains("newImpl") && args.get("newImpl").is<bool>() &&
+      args.get("newImpl").get<bool>()) {
+    LoggerD("New implementation");
+    impl = std::bind(&UserNotification::GetNotiHandleFromJson, _1, _2, _3);
+  } else {
+    LoggerW("Deprecated object used");
+    impl = std::bind(&StatusNotification::GetNotiHandleFromJson, _1, _2, _3);
+  }
+
+  PlatformResult platform_result = impl(args.get("notification"), false, &notification_handle);
+  if (!platform_result) {
+    LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, platform_result.message().c_str()),
+                      &out);
+  }
+  platform_result = CommonNotification::GetAppControl(notification_handle, &app_control);
+
+  if (!platform_result) {
+    LogAndReportError(
+        PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
+  }
+
+  int alarm_id = 0;
+  int ret = 0;
+
+  if (kAlarmRelative == alarm_type) {
+    ret = app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueRelative);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LogAndReportError(
+          PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
+          ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
+      return;
+    }
+
+    const auto it_period = alarm.find("period");
+    const auto it_delay = alarm.find("delay");
+
+    if (alarm.end() == it_delay || alarm.end() == it_period || !it_delay->second.is<double>()) {
+      LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
+                        &out);
+      return;
+    }
+
+    int delay = static_cast<int>(it_delay->second.get<double>());
+
+    std::string delay_str = std::to_string(delay);
+    ret = app_control_add_extra_data(app_control, kAlarmRelativeDelayKey, delay_str.c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LogAndReportError(
+          PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
+          ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
+      return;
+    }
+
+    platform_result = CommonNotification::SetAppControl(notification_handle, app_control);
+
+    if (!platform_result) {
+      LogAndReportError(
+          PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
+    }
+
+    int period = 0;
+    if (it_period->second.is<double>()) {
+      period = static_cast<int>(it_period->second.get<double>());
+    }
+
+    bool isPeriodSet = false;
+    if (args.contains("isPeriodSet")) {
+      isPeriodSet = args.get("isPeriodSet").get<bool>();
+    }
+
+    if (!isPeriodSet) {
+      ret = alarm_schedule_noti_once_after_delay(notification_handle, delay, &alarm_id);
+    } else {
+      ret = alarm_schedule_noti_after_delay(notification_handle, delay, period, &alarm_id);
+    }
+  } else {
+    if (alarm.find("period")->second.is<double>()) {
+      LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                                       "AlarmAbsolute constructed by deprecated constructor."),
+                        &out);
+      return;
+    }
+
+    ret = app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueAbsolute);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LogAndReportError(
+          PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
+          ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
+      return;
+    }
+
+    const auto it_daysOfTheWeek = alarm.find("daysOfTheWeek");
+    long long int milliseconds = 0;
+
+    if (args.contains("milliseconds")) {
+      milliseconds = strtoll(args.get("milliseconds").get<std::string>().c_str(), nullptr, 10);
+    }
+
+    time_t second = milliseconds / 1000;
+    struct tm start_date = {0};
+
+    tzset();
+    if (nullptr == localtime_r(&second, &start_date)) {
+      LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Invalid date."), &out);
+      return;
+    }
+
+    mktime(&start_date);
+
+    char str_date[kDateSize];
+
+    snprintf(str_date, sizeof(str_date), "%d %d %d %d %d %d %d", start_date.tm_year,
+             start_date.tm_mon, start_date.tm_mday, start_date.tm_hour, start_date.tm_min,
+             start_date.tm_sec, start_date.tm_isdst);
+
+    ret = app_control_add_extra_data(app_control, kAlarmAbsoluteDateKey, str_date);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LogAndReportError(
+          PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
+          ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
+      return;
+    }
+
+    if (alarm.end() != it_daysOfTheWeek && it_daysOfTheWeek->second.is<picojson::array>() &&
+        !(it_daysOfTheWeek->second.get<picojson::array>()).empty()) {
+      app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
+                                 kAlarmAbsoluteReccurrenceTypeByDayValue);
+
+      const picojson::array& days_of_the_week = it_daysOfTheWeek->second.get<picojson::array>();
+      int repeat_value = 0;
+      util::ArrayDaysToMask(days_of_the_week, &repeat_value);
+
+      platform_result = CommonNotification::SetAppControl(notification_handle, app_control);
+      if (!platform_result) {
+        LogAndReportError(
+            PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
+      }
+
+      ret = alarm_schedule_noti_with_recurrence_week_flag(notification_handle, &start_date,
+                                                          repeat_value, &alarm_id);
+    } else {
+      ret = app_control_add_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey,
+                                       kAlarmAbsoluteRecurrenceTypeNone);
+      if (APP_CONTROL_ERROR_NONE != ret) {
+        LogAndReportError(
+            PlatformResult(ErrorCode::ABORT_ERR, "Fail to add data from app_control."), &out,
+            ("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret)));
+        return;
+      }
+
+      platform_result = CommonNotification::SetAppControl(notification_handle, app_control);
+      if (!platform_result) {
+        LogAndReportError(
+            PlatformResult(platform_result.error_code(), platform_result.message().c_str()), &out);
+      }
+
+      ret = alarm_schedule_noti_once_at_date(notification_handle, &start_date, &alarm_id);
+    }
+  }
+
+  if (ALARM_ERROR_NONE != ret) {
+    if (ALARM_ERROR_INVALID_TIME == ret || ALARM_ERROR_INVALID_DATE == ret ||
+        ALARM_ERROR_INVALID_PARAMETER == ret) {
+      platform_result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid data.");
+    } else {
+      platform_result = PlatformResult(ErrorCode::ABORT_ERR, "Error while adding alarm to server.");
+    }
+
+    LogAndReportError(platform_result, &out,
+                      ("Error while add alarm to server: %d (%s)", ret, get_error_message(ret)));
+    return;
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  if (alarm_type == kAlarmRelative) {
+    int period = 0;
+    ret = alarm_get_scheduled_period(alarm_id, &period);
+    if (ALARM_ERROR_NONE != ret) {
+      LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred."), &out,
+                        ("Unknown error occurred: %d (%s)", ret, get_error_message(ret)));
+      return;
+    }
+    if (0 != period) {
+      result_obj.insert(std::make_pair("period", picojson::value(std::to_string(period))));
+    }
+  }
+
+  result_obj.insert(std::make_pair("id", picojson::value(std::to_string(alarm_id))));
+  ReportSuccess(result, out);
+}
+
 void AlarmManager::Remove(const picojson::value& args, picojson::object& out) {
   LoggerD("Entered");
   CHECK_PRIVILEGE_ACCESS(kPrivilegeAlarm, &out);
@@ -317,18 +519,30 @@ PlatformResult AlarmManager::GetAlarm(int id, picojson::object& obj) {
   char* alarm_type = nullptr;
   char* date_string = nullptr;
   char* delay_string = nullptr;
+  notification_h notification_handle = nullptr;
 
   SCOPE_EXIT {
     app_control_destroy(app_control);
     free(alarm_type);
     free(date_string);
     free(delay_string);
+    notification_free(notification_handle);
   };
 
-  ret = alarm_get_app_control(id, &app_control);
-  if (ALARM_ERROR_NONE != ret) {
-    return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Alarm not found.",
-                              ("Alarm not found: %d (%s)", ret, get_error_message(ret)));
+  if (ALARM_ERROR_NONE != alarm_get_app_control(id, &app_control)) {
+    if (ALARM_ERROR_NONE != alarm_get_notification(id, &notification_handle)) {
+      return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Alarm not found.",
+                                ("Alarm not found: %d (%s)", ret, get_error_message(ret)));
+    } else {
+      PlatformResult platform_result = extension::notification::CommonNotification::GetAppControl(
+          notification_handle, &app_control);
+      if (!platform_result) {
+        return LogAndCreateResult(
+            platform_result.error_code(), platform_result.message().c_str(),
+            ("Failed to get AppControl: %d (%s)", platform_result.error_code(),
+             platform_result.message().c_str()));
+      }
+    }
   }
 
   ret = app_control_get_extra_data(app_control, kAlarmKeyType, &alarm_type);
@@ -386,6 +600,7 @@ PlatformResult AlarmManager::GetAlarm(int id, picojson::object& obj) {
           obj.insert(std::make_pair("second", picojson::value(picojson::array())))
               .first->second.get<picojson::array>();
 
+      using namespace util;
       if (byDayValue & ALARM_WEEK_FLAG_SUNDAY) array.push_back(picojson::value(kSundayShort));
       if (byDayValue & ALARM_WEEK_FLAG_MONDAY) array.push_back(picojson::value(kMondayShort));
       if (byDayValue & ALARM_WEEK_FLAG_TUESDAY) array.push_back(picojson::value(kTuesdayShort));
@@ -447,6 +662,54 @@ void AlarmManager::Get(const picojson::value& args, picojson::object& out) {
   }
 }
 
+void AlarmManager::GetAlarmNotification(const picojson::value& args, picojson::object& out) {
+  using namespace extension::notification;
+  LoggerD("Entered");
+
+  int alarm_id = 0;
+  int ret = ALARM_ERROR_NONE;
+  notification_h notification_handle = nullptr;
+  PlatformResult platform_result = PlatformResult(ErrorCode::NO_ERROR);
+
+  SCOPE_EXIT {
+    notification_free(notification_handle);
+  };
+
+  if (args.contains("id") && args.get("id").is<double>()) {
+    alarm_id = static_cast<int>(args.get("id").get<double>());
+  }
+
+  ret = alarm_get_notification(alarm_id, &notification_handle);
+
+  if (ALARM_ERROR_NONE != ret) {
+    if (ALARM_ERROR_INVALID_PARAMETER == ret) {
+      platform_result =
+          PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alarm with given ID was not found.");
+    } else {
+      platform_result = PlatformResult(ErrorCode::ABORT_ERR, "Failed to get notification.");
+    }
+    LogAndReportError(platform_result, &out);
+  }
+
+  app_control_h app_control = nullptr;
+  platform_result = CommonNotification::GetAppControl(notification_handle, &app_control);
+
+  if (!platform_result) {
+    LogAndReportError(platform_result, &out);
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  platform_result = UserNotification::ToJson(-1, notification_handle, app_control, &result_obj);
+
+  if (ALARM_ERROR_NONE != ret) {
+    LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "Failed ToJson()."), &out);
+  }
+
+  ReportSuccess(result, out);
+}
+
 static bool AlarmIterateCB(int alarm_id, void* user_data) {
   LoggerD("Enter");
 
index 1e3b4b1..f7c0f3f 100644 (file)
@@ -29,9 +29,11 @@ class AlarmManager {
   virtual ~AlarmManager();
 
   void Add(const picojson::value& args, picojson::object& out);
+  void AddAlarmNotification(const picojson::value& args, picojson::object& out);
   void Remove(const picojson::value& args, picojson::object& out);
   void RemoveAll(const picojson::value& args, picojson::object& out);
   void Get(const picojson::value& args, picojson::object& out);
+  void GetAlarmNotification(const picojson::value& args, picojson::object& out);
   void GetAll(const picojson::value& args, picojson::object& out);
 
   // AlarmRelative
index 55c1965..a80e657 100644 (file)
@@ -24,6 +24,14 @@ namespace extension {
 namespace alarm {
 namespace util {
 
+const char* kSundayShort = "SU";
+const char* kMondayShort = "MO";
+const char* kTuesdayShort = "TU";
+const char* kWednesdayShort = "WE";
+const char* kThuesdayShort = "TH";
+const char* kFridayShort = "FR";
+const char* kSaturdayShort = "SA";
+
 using namespace common;
 
 PlatformResult AppControlToService(const picojson::object& obj, app_control_h* app_control) {
@@ -144,6 +152,31 @@ PlatformResult AppControlToServiceExtraData(const picojson::object& app_obj,
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+PlatformResult ArrayDaysToMask(const picojson::array& days_of_the_week, int* repeat_value) {
+  LoggerD("Entered");
+  for (auto iter = days_of_the_week.begin(); iter != days_of_the_week.end(); ++iter) {
+    auto day = (*iter).get<std::string>();
+    if (kSundayShort == day) {
+      *repeat_value |= ALARM_WEEK_FLAG_SUNDAY;
+    } else if (kMondayShort == day) {
+      *repeat_value |= ALARM_WEEK_FLAG_MONDAY;
+    } else if (kTuesdayShort == day) {
+      *repeat_value |= ALARM_WEEK_FLAG_TUESDAY;
+    } else if (kWednesdayShort == day) {
+      *repeat_value |= ALARM_WEEK_FLAG_WEDNESDAY;
+    } else if (kThuesdayShort == day) {
+      *repeat_value |= ALARM_WEEK_FLAG_THURSDAY;
+    } else if (kFridayShort == day) {
+      *repeat_value |= ALARM_WEEK_FLAG_FRIDAY;
+    } else if (kSaturdayShort == day) {
+      *repeat_value |= ALARM_WEEK_FLAG_SATURDAY;
+    } else {
+      return LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR, "Invalid days of the week value.");
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // util
 }  // alarm
 }  // extension
index 85e5345..c1a7fe2 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef ALARM_ALARM_UTILS_H_
 #define ALARM_ALARM_UTILS_H_
 
+#include <app_alarm.h>
 #include <app_control.h>
 
 #include "common/picojson.h"
@@ -26,9 +27,18 @@ namespace extension {
 namespace alarm {
 namespace util {
 
+extern const char* kSundayShort;
+extern const char* kMondayShort;
+extern const char* kTuesdayShort;
+extern const char* kWednesdayShort;
+extern const char* kThuesdayShort;
+extern const char* kFridayShort;
+extern const char* kSaturdayShort;
+
 common::PlatformResult AppControlToService(const picojson::object& obj, app_control_h* app_control);
 common::PlatformResult AppControlToServiceExtraData(const picojson::object& app_obj,
                                                     app_control_h* app_control);
+common::PlatformResult ArrayDaysToMask(const picojson::array& days_of_the_week, int* repeat_value);
 }  // util
 }  // alarm
 }  // extension
index 40b614f..38d04d0 100644 (file)
@@ -33,7 +33,8 @@
             'packages': [
               'aul',
               'capi-appfw-app-manager',
-              'capi-appfw-application',
+              'capi-appfw-app-control',
+              'capi-appfw-event',
               'capi-appfw-package-manager',
               'pkgmgr',
               'pkgmgr-info',
             ]
           },
         }],
+        ['extension_host_os == "mobile"', {
+          'variables': {
+            'packages': [
+              'capi-context',
+            ]
+          }
+        }],
       ],
     },
   ],
index b668dbb..3b53fc1 100755 (executable)
@@ -26,6 +26,11 @@ var ApplicationControlLaunchMode = {
   GROUP: 'GROUP'
 };
 
+var ApplicationUsageMode = {
+  RECENTLY: 'RECENTLY',
+  FREQUENTLY: 'FREQUENTLY'
+};
+
 //  TODO: Please uncomment below lines when system events is ready
 //var SystemEvent = {
 //  BATTERY_CHARGER_STATUS: 'BATTERY_CHARGER_STATUS',
@@ -496,6 +501,156 @@ ApplicationManager.prototype.getAppMetaData = function() {
   }
 };
 
+ApplicationManager.prototype.getBatteryUsageInfo = function() {
+  var args = AV.validateMethod(arguments, [
+  {
+    name: 'successCallback',
+    type: AV.Types.FUNCTION
+  },
+  {
+    name: 'errorCallback',
+    type: AV.Types.FUNCTION,
+    optional: true,
+    nullable: true
+  },
+  {
+    name: 'days',
+    type: AV.Types.LONG,
+    optional: true,
+    nullable: true
+  },
+  {
+    name: 'limit',
+    type: AV.Types.LONG,
+    optional: true,
+    nullable: true
+  }]);
+
+  var callArgs = {};
+
+  if (!T.isNullOrUndefined(args.days)) {
+    callArgs.days = args.days;
+  }
+
+  if (!T.isNullOrUndefined(args.limit)) {
+    callArgs.limit = args.limit;
+  }
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      var data = native.getResultObject(result);
+      var resultArray = [];
+      data.forEach(function (i) {
+        resultArray.push(new ApplicationBatteryUsage(i));
+      });
+      args.successCallback(resultArray);
+    }
+  };
+
+  var result = native.call('ApplicationManager_getBatteryUsageInfo', callArgs, callback);
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+ApplicationManager.prototype.getAppsUsageInfo = function() {
+  var args = AV.validateMethod(arguments, [
+  {
+    name: 'successCallback',
+    type: AV.Types.FUNCTION
+  },
+  {
+    name: 'errorCallback',
+    type: AV.Types.FUNCTION,
+    optional: true,
+    nullable: true
+  },
+  {
+    name: 'mode',
+    type: AV.Types.ENUM,
+    values: T.getValues(ApplicationUsageMode),
+    optional: true,
+    nullable: true
+  },
+  {
+    name: 'filter',
+    type: AV.Types.DICTIONARY,
+    optional: true,
+    nullable: true
+  },
+  {
+    name: 'limit',
+    type: AV.Types.LONG,
+    optional: true,
+    nullable: true
+  }]);
+
+  var callArgs = {};
+
+  if (!T.isNullOrUndefined(args.mode)) {
+    callArgs.mode = args.mode;
+  }
+
+  if (!T.isNullOrUndefined(args.filter) && typeof args.filter !== 'object') {
+    setTimeout(function() {
+        native.callIfPossible(args.errorCallback,
+            new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+            'filter must be an object.'));
+      }, 0);
+    return;
+  }
+
+  callArgs.filter = {};
+  if (!T.isNullOrUndefined(args.filter)) {
+    var filter = args.filter;
+    if (!T.isNullOrUndefined(filter.timeSpan)) {
+      callArgs.filter.timeSpan = Converter.toLong(filter.timeSpan);
+    } else {
+      if (!T.isNullOrUndefined(filter.startTime)) {
+        if (filter.startTime instanceof Date) {
+          callArgs.filter.startTime = filter.startTime.getTime() / 1000;
+        } else {
+          throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                'startTime given with invalid type.');
+        }
+      }
+
+      if (!T.isNullOrUndefined(filter.endTime)) {
+        if (filter.endTime instanceof Date) {
+          callArgs.filter.endTime = filter.endTime.getTime() / 1000;
+        } else {
+          throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                'endTime given with invalid type.');
+        }
+      }
+    }
+  }
+
+  if (!T.isNullOrUndefined(args.limit)) {
+    callArgs.limit = args.limit;
+  }
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      var data = native.getResultObject(result);
+      var resultArray = [];
+      data.forEach(function(i) {
+        resultArray.push(new ApplicationUsage(i));
+      });
+      args.successCallback(resultArray);
+    }
+  };
+
+  var result = native.call('ApplicationManager_getAppsUsageInfo', callArgs, callback);
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
 function ListenerManager(native, listenerName) {
   this.listeners = {};
   this.nextId = 1;
@@ -593,6 +748,110 @@ ApplicationManager.prototype.removeAppInfoEventListener = function() {
   applicationEventListener.removeListener(args.watchId);
 };
 
+function StatusListenerManager(native, listenerName) {
+  this.listeners = {};
+  this.listenersCount = 0;
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+};
+
+StatusListenerManager.prototype.onListenerCalled = function(msg) {
+  var statusType = msg.statusType;
+  var app_id = msg.appId;
+
+  for (var watchId in this.listeners) {
+    if (this.listeners.hasOwnProperty(watchId)) {
+      var listener = this.listeners[watchId];
+      if (!listener.appId || listener.appId === app_id) {
+        listener.callback(app_id, statusType);
+      }
+    }
+  }
+};
+
+StatusListenerManager.prototype.addListener = function(callback, appId) {
+  if (!this.nativeSet) {
+    var result = this.native.callSync('ApplicationManager_addAppStatusChangeListener');
+    if (this.native.isFailure(result)) {
+      throw this.native.getErrorObject(result);
+    }
+
+    this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+    this.nativeSet = true;
+  }
+
+  var listener = {
+    'callback' : callback,
+    'appId' : appId
+  };
+
+  var id = this.nextId++;
+  this.listeners[id] = listener;
+  this.listenersCount++;
+
+  return id;
+};
+
+StatusListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    if (this.listenersCount > 1) {
+      delete this.listeners[watchId];
+      this.listenersCount--;
+      return;
+    }
+
+    if (this.nativeSet) {
+      var result = this.native.callSync('ApplicationManager_removeStatusChangeListener');
+      if (this.native.isFailure(result)) {
+        throw this.native.getErrorObject(result);
+      }
+
+      delete this.listeners[watchId];
+      this.listenersCount--;
+
+      this.native.removeListener(this.listenerName);
+      this.nativeSet = false;
+    }
+  }
+};
+
+var APP_STATUS_CHANGE_LISTENER = 'AppStatusChangeListener';
+var appStatusChangeListener = new StatusListenerManager(native, APP_STATUS_CHANGE_LISTENER);
+
+ApplicationManager.prototype.addAppStatusChangeListener = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'statusChangeListener',
+        type : AV.Types.FUNCTION,
+      },
+      {
+        name : 'appId',
+        type : AV.Types.STRING,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  if (args.appId !== undefined && args.appId !== null && !args.appId.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Application id is empty');
+  }
+
+  return appStatusChangeListener.addListener(args.statusChangeListener, args.appId);
+};
+
+ApplicationManager.prototype.removeAppStatusChangeListener = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'watchId',
+        type : AV.Types.LONG
+      }
+  ]);
+
+  appStatusChangeListener.removeListener(args.watchId);
+};
+
 // class Application ////////////////////////////////////////////////////
 
 function Application(data) {
@@ -1107,7 +1366,7 @@ function ApplicationCertificate(data) {
   });
 }
 
-// class ApplicationMetaData ////////////////////////////////////////////////////
+// class ApplicationMetaData ///////////////////////////////////////////////////////
 function ApplicationMetaData(data) {
   Object.defineProperties(this, {
     key : {
@@ -1123,5 +1382,47 @@ function ApplicationMetaData(data) {
   });
 }
 
+//class ApplicationBatteryUsage ////////////////////////////////////////////////////
+function ApplicationBatteryUsage(data) {
+  Object.defineProperties(this, {
+    appId : {
+      value : data.appId,
+      writable : false,
+      enumerable : true
+    },
+    batteryUsage : {
+      value : data.batteryUsage,
+      writable : false,
+      enumerable : true
+    }
+  });
+}
+
+//class ApplicationUsage ////////////////////////////////////////////////////////
+function ApplicationUsage(data) {
+  Object.defineProperties(this, {
+    appId : {
+      value : data.appId,
+      writable : false,
+      enumerable : true
+    },
+    totalCount : {
+      value : data.totalCount,
+      writable : false,
+      enumerable : true
+    },
+    totalDuration : {
+      value : data.totalDuration,
+      writable : false,
+      enumerable : true
+    },
+    lastTime : {
+      value : new Date(data.lastTime * 1000),
+      writable : false,
+      enumerable : true
+    }
+  });
+}
+
 // exports ////////////////////////////////////////////////////
 exports = new ApplicationManager();
index e266380..e289614 100644 (file)
@@ -33,6 +33,7 @@ const std::string kPrivilegeAppManagerCertificate =
 const std::string kPrivilegeAppManagerKill = "http://tizen.org/privilege/appmanager.kill";
 const std::string kPrivilegeApplicationInfo = "http://tizen.org/privilege/application.info";
 const std::string kPrivilegeApplicationLaunch = "http://tizen.org/privilege/application.launch";
+const std::string kPrivilegeAppHistoryRead = "http://tizen.org/privilege/apphistory.read";
 }  // namespace
 
 using namespace common;
@@ -61,6 +62,8 @@ ApplicationInstance::ApplicationInstance() : manager_(*this) {
   REGISTER_SYNC("ApplicationManager_getAppMetaData", GetAppMetaData);
   REGISTER_SYNC("ApplicationManager_addAppInfoEventListener", AddAppInfoEventListener);
   REGISTER_SYNC("ApplicationManager_removeAppInfoEventListener", RemoveAppInfoEventListener);
+  REGISTER_SYNC("ApplicationManager_addAppStatusChangeListener", AddStatusListener);
+  REGISTER_SYNC("ApplicationManager_removeStatusChangeListener", RemoveStatusListener);
 
   // Application
   REGISTER_SYNC("Application_getRequestedAppControl", GetRequestedAppControl);
@@ -86,6 +89,8 @@ ApplicationInstance::ApplicationInstance() : manager_(*this) {
   REGISTER_ASYNC("ApplicationManager_findAppControl", FindAppControl);
   REGISTER_ASYNC("ApplicationManager_getAppsContext", GetAppsContext);
   REGISTER_ASYNC("ApplicationManager_getAppsInfo", GetAppsInfo);
+  REGISTER_ASYNC("ApplicationManager_getAppsUsageInfo", GetAppsUsageInfo);
+  REGISTER_ASYNC("ApplicationManager_getBatteryUsageInfo", GetBatteryUsageInfo);
 #undef REGISTER_ASYNC
 }
 
@@ -158,6 +163,20 @@ void ApplicationInstance::GetAppMetaData(const picojson::value& args, picojson::
   manager_.GetAppMetaData(app_id, &out);
 }
 
+void ApplicationInstance::GetBatteryUsageInfo(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeAppHistoryRead, &out);
+
+  manager_.GetBatteryUsageInfo(args, &out);
+}
+
+void ApplicationInstance::GetAppsUsageInfo(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeAppHistoryRead, &out);
+
+  manager_.GetAppsUsageInfo(args, &out);
+}
+
 void ApplicationInstance::AddAppInfoEventListener(const picojson::value& args,
                                                   picojson::object& out) {
   LoggerD("Entered");
@@ -296,5 +315,31 @@ void ApplicationInstance::RemoveEventListener(const picojson::value& args, picoj
   manager_.StopEventListener(event_name);
 }
 
+void ApplicationInstance::AddStatusListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  JsonCallback cb = [this](picojson::value* event) -> void {
+    Instance::PostMessage(this, event->serialize().c_str());
+  };
+
+  PlatformResult result = manager_.StartStatusListener(cb);
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LogAndReportError(result, &out);
+  }
+}
+
+void ApplicationInstance::RemoveStatusListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  PlatformResult result = manager_.StopStatusChangeListener();
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LogAndReportError(result, &out);
+  }
+}
+
 }  // namespace application
 }  // namespace extension
index e43cb1c..8cafed2 100644 (file)
@@ -39,6 +39,8 @@ class ApplicationInstance : public common::ParsedInstance {
   void GetAppCerts(const picojson::value& args, picojson::object& out);
   void GetAppSharedURI(const picojson::value& args, picojson::object& out);
   void GetAppMetaData(const picojson::value& args, picojson::object& out);
+  void GetBatteryUsageInfo(const picojson::value& args, picojson::object& out);
+  void GetAppsUsageInfo(const picojson::value& args, picojson::object& out);
   void AddAppInfoEventListener(const picojson::value& args, picojson::object& out);
   void RemoveAppInfoEventListener(const picojson::value& args, picojson::object& out);
   void GetRequestedAppControl(const picojson::value& args, picojson::object& out);
@@ -55,6 +57,8 @@ class ApplicationInstance : public common::ParsedInstance {
   void BroadcastTrustedEvent(const picojson::value& args, picojson::object& out);
   void AddEventListener(const picojson::value& args, picojson::object& out);
   void RemoveEventListener(const picojson::value& args, picojson::object& out);
+  void AddStatusListener(const picojson::value& args, picojson::object& out);
+  void RemoveStatusListener(const picojson::value& args, picojson::object& out);
 
   ApplicationManager manager_;
   Application current_application_;
index 4c19abe..a5e69f9 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <app_control_internal.h>
 #include <app_info.h>
-#include <app_manager.h>
 #include <app_manager_extension.h>
 #include <appsvc.h>
 #include <aul.h>
@@ -67,6 +66,12 @@ const std::string kOnInstalled = "oninstalled";
 const std::string kOnUpdated = "onupdated";
 const std::string kOnUninstalled = "onuninstalled";
 const std::string kData = "data";
+const std::string kStatusType = "statusType";
+const std::string kAppId = "appId";
+const std::string kListenerId = "listenerId";
+const std::string kAppStatusChangeListener = "AppStatusChangeListener";
+const std::string kAppUsageModeFrequently = "FREQUENTLY";
+const std::string kAppUsageModeRecently = "RECENTLY";
 
 const std::map<std::string, std::string> event_map_ = {
     {SYSTEM_EVENT_BATTERY_CHARGER_STATUS, EVENT_KEY_BATTERY_CHARGER_STATUS},
@@ -91,18 +96,33 @@ const std::map<std::string, std::string> event_map_ = {
     {SYSTEM_EVENT_MOBILE_DATA_STATE, EVENT_KEY_MOBILE_DATA_STATE},
     {SYSTEM_EVENT_DATA_ROAMING_STATE, EVENT_KEY_DATA_ROAMING_STATE},
     {SYSTEM_EVENT_FONT_SET, EVENT_KEY_FONT_SET}};
+
+#ifdef TIZEN_MOBILE
+const int kMaximumBatteryRetrievedObjects = 30;
+const int kMaximumAppsRetrievedObjects = 10;
+const int kDefaultPeriodOfTime = 30;
+#endif
 }
 
 ApplicationManager::ApplicationManager(ApplicationInstance& instance)
     : pkgmgr_client_handle_(nullptr),
       pkgmgr_client_uninstall_handle_(nullptr),
-      instance_(instance) {
+      instance_(instance),
+      app_status_handle_(nullptr) {
   LoggerD("Enter");
 }
 
 ApplicationManager::~ApplicationManager() {
   LoggerD("Enter");
   StopAppInfoEventListener();
+  StopStatusChangeListener();
+
+  if (app_status_handle_) {
+    int ret = app_manager_event_destroy(app_status_handle_);
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      LoggerE("app_manager_event_destroy failed, error: %d", ret);
+    }
+  }
 }
 
 void ApplicationManager::GetCurrentApplication(const std::string& app_id, picojson::object* out) {
@@ -1155,6 +1175,268 @@ void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::ob
   ReportSuccess(result, *out);
 }
 
+#ifdef TIZEN_MOBILE
+PlatformResult ApplicationManager::BatteryUsageFilter(const picojson::value& args,
+                                                      const context_history_filter_h filter,
+                                                      context_history_data_e* data_type_out) {
+  LoggerD("Entered");
+  int ret = CONTEXT_HISTORY_ERROR_NONE;
+  int limit = kMaximumBatteryRetrievedObjects;
+  if (args.contains("limit")) {
+    limit = static_cast<int>(args.get("limit").get<double>());
+  }
+
+  ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
+
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
+        ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  context_history_data_e data_type_in = CONTEXT_HISTORY_RECENT_BATTERY_USAGE;
+
+  if (args.contains("days")) {
+    const int days = static_cast<int>(args.get("days").get<double>());
+    data_type_in = CONTEXT_HISTORY_BATTERY_USAGE;
+    ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, days);
+
+    if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+      return LogAndCreateResult(
+          ErrorCode::INVALID_VALUES_ERR, "days given with invalid value.",
+          ("days given with invalid value: %d (%s)", ret, get_error_message(ret)));
+    }
+  }
+
+  *data_type_out = data_type_in;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_record_h record,
+                                                          picojson::object* object) {
+  LoggerD("Entered");
+
+  int ret = CONTEXT_HISTORY_ERROR_NONE;
+  double amount = 0.0;
+  char* app_id = nullptr;
+  SCOPE_EXIT {
+    free(app_id);
+  };
+
+  ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
+                              ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  ret = context_history_record_get_double(record, CONTEXT_HISTORY_TOTAL_AMOUNT, &amount);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get amount.",
+                              ("Failed to get amount: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  object->insert(std::make_pair("appId", picojson::value(app_id)));
+  object->insert(std::make_pair("batteryUsage", picojson::value(amount)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args,
+                                                   const context_history_filter_h filter,
+                                                   context_history_data_e* data_type_out) {
+  LoggerD("Entered");
+  int ret = CONTEXT_HISTORY_ERROR_NONE;
+  int limit = kMaximumAppsRetrievedObjects;
+  if (args.contains("limit")) {
+    limit = static_cast<int>(args.get("limit").get<double>());
+  }
+
+  ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.",
+        ("limit given with invalid value: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  context_history_data_e data_type_in = CONTEXT_HISTORY_FREQUENTLY_USED_APP;
+  if (args.contains("mode") && kAppUsageModeRecently == args.get("mode").get<std::string>()) {
+    data_type_in = CONTEXT_HISTORY_RECENTLY_USED_APP;
+  }
+
+  int time_span = kDefaultPeriodOfTime;
+  const picojson::object& JS_filter = args.get("filter").get<picojson::object>();
+  auto time_span_iter = JS_filter.find("timeSpan");
+  if (JS_filter.end() != time_span_iter || (JS_filter.end() == JS_filter.find("startTime") &&
+                                            JS_filter.end() == JS_filter.find("endTime"))) {
+    // In the second case, we treat the filter object just like an empty object.
+    // The default value of filter will be used instead.
+    if (JS_filter.end() != time_span_iter) {
+      time_span = static_cast<int>(time_span_iter->second.get<double>());
+    }
+    ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, time_span);
+    // context_history_filter_set_int may return only success or
+    // CONTEXT_HISTORY_ERROR_INVALID_PARAMETER
+    // Although this should never happen, it's better to check ret's value
+    if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::ABORT_ERR,
+                                "Error while setting the default TIME_SPAN value.",
+                                ("Error while setting the default TIME_SPAN value: %d (%s)", ret,
+                                 get_error_message(ret)));
+    }
+  } else {
+    auto start_time_iter = JS_filter.find("startTime");
+    auto end_time_iter = JS_filter.find("endTime");
+    if (start_time_iter != JS_filter.end()) {
+      int start_time = static_cast<int>(start_time_iter->second.get<double>());
+      ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_START_TIME, start_time);
+      if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+        return LogAndCreateResult(
+            ErrorCode::INVALID_VALUES_ERR, "startTime given with invalid value.",
+            ("startTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
+      }
+    }
+    if (end_time_iter != JS_filter.end()) {
+      int end_time = static_cast<int>(end_time_iter->second.get<double>());
+      ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_END_TIME, end_time);
+      if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+        return LogAndCreateResult(
+            ErrorCode::INVALID_VALUES_ERR, "endTime given with invalid value.",
+            ("endTime given with invalid value: %d (%s)", ret, get_error_message(ret)));
+      }
+    }
+  }
+
+  *data_type_out = data_type_in;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record,
+                                                       picojson::object* object) {
+  LoggerD("Entered");
+
+  int ret = CONTEXT_HISTORY_ERROR_NONE;
+  int total_count = 0;
+  int total_duration = 0;
+  int last_time = 0;
+  char* app_id = nullptr;
+  SCOPE_EXIT {
+    free(app_id);
+  };
+
+  ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.",
+                              ("Failed to get string: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_COUNT, &total_count);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get total count.",
+                              ("Failed to get total count: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_DURATION, &total_duration);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::ABORT_ERR, "Failed to get total duration.",
+        ("Failed to get total duration: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  ret = context_history_record_get_int(record, CONTEXT_HISTORY_LAST_TIME, &last_time);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get last time.",
+                              ("Failed to get last time: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  object->insert(std::make_pair("appId", picojson::value(app_id)));
+  object->insert(std::make_pair("totalCount", picojson::value(static_cast<double>(total_count))));
+  object->insert(
+      std::make_pair("totalDuration", picojson::value(static_cast<double>(total_duration))));
+  object->insert(std::make_pair("lastTime", picojson::value(static_cast<double>(last_time))));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+#endif
+
+void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) {
+  LoggerD("Entered");
+
+#ifdef TIZEN_MOBILE
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  auto get_battery_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Entered");
+    PlatformResult result = ApplicationManager::GetContextHistory(
+        args, &response.get()->get<picojson::object>(), &ApplicationManager::BatteryUsageFilter,
+        &ApplicationManager::BatteryUsageAttributes);
+    if (!result) {
+      LogAndReportError(result, &response.get()->get<picojson::object>());
+    }
+  };
+
+  auto get_battery_usage_response =
+      [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Entered");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(get_battery_usage, get_battery_usage_response,
+                                                  data);
+#else
+  // 20170510 Context API is supported only for mobile profile, other ones would result with
+  // NotSupportedError
+  LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+                                   "This feature is not supported on this profile."),
+                    out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
+#endif
+}
+
+void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) {
+  LoggerD("Entered");
+
+#ifdef TIZEN_MOBILE
+  int callback_id = static_cast<int>(args.get(kCallbackId).get<double>());
+
+  auto get_apps_usage = [args](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Entered");
+    PlatformResult result = ApplicationManager::GetContextHistory(
+        args, &response.get()->get<picojson::object>(), &ApplicationManager::AppsUsageFilter,
+        &ApplicationManager::AppsUsageAttributes);
+    if (!result) {
+      LogAndReportError(result, &response.get()->get<picojson::object>());
+    }
+  };
+
+  auto get_apps_usage_response =
+      [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Entered");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(get_apps_usage, get_apps_usage_response, data);
+#else
+  // Context API is supported only for mobile profile, other ones would result with
+  // NotSupportedError
+  LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+                                   "This feature is not supported on this profile."),
+                    out, ("NOT_SUPPORTED_ERR: This feature is not supported on this profile"));
+#endif
+}
+
 void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
   LoggerD("Entered");
 
@@ -1633,5 +1915,180 @@ void ApplicationManager::StopEventListener(const std::string& event_name) {
   }
 }
 
+void ApplicationManager::OnStatusEvent(const char* type, const char* app_id,
+                                       app_manager_event_type_e event_type,
+                                       app_manager_event_state_e event_state,
+                                       app_manager_event_h handle, void* user_data) {
+  LoggerD("Entered");
+
+  if (APP_MANAGER_EVENT_STATE_COMPLETED != event_state) {
+    LoggerD("State different from completed");
+    return;
+  }
+
+  ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
+
+  if (!manager || !manager->status_callback_) {
+    LoggerD("No event listener registered, skipping.");
+    return;
+  }
+
+  bool status_type;
+  switch (event_type) {
+    case APP_MANAGER_EVENT_ENABLE_APP:
+      status_type = true;
+      break;
+    case APP_MANAGER_EVENT_DISABLE_APP:
+      status_type = false;
+      break;
+    default:
+      LoggerD("Uknown status type skipping.");
+      return;
+  }
+
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& event_o = event.get<picojson::object>();
+
+  event_o[kStatusType] = picojson::value(status_type);
+  event_o[kAppId] = picojson::value(app_id);
+  event_o[kListenerId] = picojson::value(kAppStatusChangeListener);
+
+  manager->status_callback_(&event);
+}
+
+#ifdef TIZEN_MOBILE
+PlatformResult ApplicationManager::GetContextHistory(
+    const picojson::value& args, picojson::object* out,
+    common::PlatformResult (*modify_filter_cb)(const picojson::value&,
+                                               const context_history_filter_h,
+                                               context_history_data_e* data_type),
+    common::PlatformResult (*add_attributes_to_object)(const context_history_record_h,
+                                                       picojson::object*)) {
+  LoggerD("Entered");
+  context_history_list_h list = nullptr;
+  context_history_h handle = nullptr;
+  context_history_filter_h filter = nullptr;
+
+  SCOPE_EXIT {
+    context_history_list_destroy(list);
+    context_history_destroy(handle);
+    context_history_filter_destroy(filter);
+  };
+
+  int ret = context_history_create(&handle);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::ABORT_ERR, "Failed to create context handle.",
+        ("Failed to create context handle: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  ret = context_history_filter_create(&filter);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::ABORT_ERR, "Failed to create filter handle.",
+        ("Failed to create filter handle: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  context_history_data_e data_type;
+
+  PlatformResult result = modify_filter_cb(args, filter, &data_type);
+  if (!result) {
+    return result;
+  }
+
+  picojson::value result_array = picojson::value(picojson::array());
+  picojson::array& array_obj = result_array.get<picojson::array>();
+
+  ret = context_history_get_list(handle, data_type, filter, &list);
+  if (CONTEXT_HISTORY_ERROR_NO_DATA == ret) {
+    ReportSuccess(result_array, *out);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  } else if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list.",
+                              ("Failed to get list: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  int size = 0;
+  ret = context_history_list_get_count(list, &size);
+  if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get list size.",
+                              ("Failed to get list size: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  array_obj.resize(size, picojson::value(picojson::object()));
+
+  for (int i = 0; i < size; ++i) {
+    context_history_record_h record = nullptr;
+    SCOPE_EXIT {
+      context_history_record_destroy(record);
+    };
+
+    ret = context_history_list_get_current(list, &record);
+    if (CONTEXT_HISTORY_ERROR_NONE != ret) {
+      return LogAndCreateResult(
+          ErrorCode::ABORT_ERR, "Failed to get current record.",
+          ("Failed to get current record: %d (%s)", ret, get_error_message(ret)));
+    }
+
+    result = add_attributes_to_object(record, &array_obj[i].get<picojson::object>());
+    if (!result) {
+      return result;
+    }
+
+    ret = context_history_list_move_next(list);
+    if (CONTEXT_HISTORY_ERROR_NONE != ret && CONTEXT_HISTORY_ERROR_NO_DATA != ret) {
+      return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to move iterator.",
+                                ("Failed to move iterator: %d (%s)", ret, get_error_message(ret)));
+    }
+  }
+
+  ReportSuccess(result_array, *out);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+#endif
+
+PlatformResult ApplicationManager::StartStatusListener(const JsonCallback& callback) {
+  LoggerD("Entered");
+
+  int ret = APP_MANAGER_ERROR_NONE;
+
+  if (!app_status_handle_) {
+    ret = app_manager_event_create(&app_status_handle_);
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while creating event handle",
+                                ("app_manager_event_create failed, error: %d", ret));
+    }
+
+    ret = app_manager_event_set_status(app_status_handle_, APP_MANAGER_EVENT_STATUS_TYPE_ALL);
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status type",
+                                ("app_manager_event_set_status failed, error: %d", ret));
+    }
+  }
+
+  status_callback_ = callback;
+  ret = app_manager_set_event_cb(app_status_handle_, OnStatusEvent, this);
+  if (APP_MANAGER_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while setting status listener",
+                              ("app_manager_set_event_cb failed, error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ApplicationManager::StopStatusChangeListener() {
+  LoggerD("Entered");
+
+  if (app_status_handle_) {
+    int ret = app_manager_unset_event_cb(app_status_handle_);
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::ABORT_ERR, "Error while removing status listener",
+                                ("app_manager_unset_event_cb failed, error: %d", ret));
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // namespace application
 }  // namespace extension
index 7e7be7f..6bb4ecc 100644 (file)
 #define SRC_APPLICATION_APPLICATION_MANAGER_H__
 
 #include <app_event.h>
+#include <app_manager.h>
 #include <bundle.h>
 #include <package-manager.h>
 #include <pkgmgr-info.h>
 #include <functional>
+#include <functional>
 #include <memory>
 #include <string>
+#ifdef TIZEN_MOBILE
+#include <context-service/context_history.h>
+#endif
 
 #include "common/picojson.h"
 #include "common/platform_result.h"
@@ -52,6 +57,8 @@ class ApplicationManager {
   void GetAppCerts(const std::string& app_id, picojson::object* out);
   void GetAppSharedUri(const std::string& app_id, picojson::object* out);
   void GetAppMetaData(const std::string& app_id, picojson::object* out);
+  void GetBatteryUsageInfo(const picojson::value& args, picojson::object* out);
+  void GetAppsUsageInfo(const picojson::value& args, picojson::object* out);
   void StartAppInfoEventListener(picojson::object* out);
   void StopAppInfoEventListener();
   void GetApplicationInformationSize(const picojson::value& args, picojson::object* out);
@@ -61,6 +68,8 @@ class ApplicationManager {
   common::PlatformResult StartEventListener(const std::string& event_name,
                                             const JsonCallback& callback);
   void StopEventListener(const std::string& event_name);
+  common::PlatformResult StartStatusListener(const JsonCallback& callback);
+  common::PlatformResult StopStatusChangeListener();
 
  private:
   char* GetPackageId(const std::string& app_id);
@@ -68,10 +77,36 @@ class ApplicationManager {
   pkgmgr_client* pkgmgr_client_handle_;
   pkgmgr_client* pkgmgr_client_uninstall_handle_;
   ApplicationInstance& instance_;
+  app_manager_event_h app_status_handle_;
 
   JsonCallback event_callback_;
+  JsonCallback status_callback_;
   std::map<std::string, event_handler_h> event_handler_map_;
   static void OnEvent(const char* event_name, bundle* event_data, void* user_data);
+  static void OnStatusEvent(const char* type, const char* app_id,
+                            app_manager_event_type_e event_type,
+                            app_manager_event_state_e event_state, app_manager_event_h handle,
+                            void* user_data);
+
+#ifdef TIZEN_MOBILE
+  static common::PlatformResult GetContextHistory(
+      const picojson::value& args, picojson::object* out,
+      common::PlatformResult (*)(const picojson::value&, const context_history_filter_h,
+                                 context_history_data_e* data_type),
+      common::PlatformResult (*)(const context_history_record_h, picojson::object*));
+
+  static common::PlatformResult BatteryUsageFilter(const picojson::value&,
+                                                   const context_history_filter_h,
+                                                   context_history_data_e* data_type);
+  static common::PlatformResult BatteryUsageAttributes(const context_history_record_h,
+                                                       picojson::object*);
+
+  static common::PlatformResult AppsUsageFilter(const picojson::value&,
+                                                const context_history_filter_h,
+                                                context_history_data_e* data_type);
+  static common::PlatformResult AppsUsageAttributes(const context_history_record_h,
+                                                    picojson::object*);
+#endif
 };
 
 }  // namespace application
index 7454b18..ee78266 100644 (file)
@@ -197,22 +197,21 @@ PlatformResult Node::getChildNames(Node::NameList* out_name_list) const {
     return LogAndCreateResult(ErrorCode::IO_ERR, "Node has been deleted from platform.");
   }
 
-  int err = 0;
-  struct dirent entry = {0};
-  struct dirent* result = nullptr;
+  errno = 0;
+  struct dirent* entry = nullptr;
   NameList name_list;
-  while ((0 == (err = readdir_r(dir, &entry, &result))) && result) {
-    if (!strcmp(entry.d_name, ".") || !strncmp(entry.d_name, "..", 2)) {
+  while (nullptr != (entry = readdir(dir))) {
+    if (!strcmp(entry->d_name, ".") || !strncmp(entry->d_name, "..", 2)) {
       continue;
     }
-    name_list.push_back(entry.d_name);
+    name_list.push_back(entry->d_name);
   }
 
   if (closedir(dir) != 0) {
     return LogAndCreateResult(ErrorCode::IO_ERR, "Could not close platform node.");
   }
 
-  if (0 != err) {
+  if (0 != errno) {
     return LogAndCreateResult(ErrorCode::IO_ERR, "Error while reading directory.");
   }
 
@@ -239,17 +238,16 @@ PlatformResult Node::getChildNodes(NodeList* out_node_list) const {
     return LogAndCreateResult(ErrorCode::IO_ERR, "Node has been deleted from platform.");
   }
 
-  int err = 0;
-  struct dirent entry = {0};
-  struct dirent* result = nullptr;
+  errno = 0;
+  struct dirent* entry = nullptr;
   NodeList node_list;
-  while ((0 == (err = readdir_r(dir, &entry, &result))) && result) {
-    if (!strcmp(entry.d_name, ".") || !strncmp(entry.d_name, "..", 2)) {
+  while (nullptr != (entry = readdir(dir))) {
+    if (!strcmp(entry->d_name, ".") || !strncmp(entry->d_name, "..", 2)) {
       continue;
     }
 
     NodePtr node;
-    Node::resolve(*m_path + entry.d_name, &node);
+    Node::resolve(*m_path + entry->d_name, &node);
     node->setPermissions(getPermissions());  // inherit access rights
     node_list.push_back(node);
   }
@@ -259,7 +257,7 @@ PlatformResult Node::getChildNodes(NodeList* out_node_list) const {
     return LogAndCreateResult(ErrorCode::IO_ERR, "Could not close platform node.");
   }
 
-  if (0 != err) {
+  if (0 != errno) {
     SLoggerE("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
     return LogAndCreateResult(ErrorCode::IO_ERR, "Error while reading directory.");
   }
@@ -536,14 +534,13 @@ PlatformResult Node::removeAsDirectory(const PathPtr& path, bool recursive) {
       SLoggerE("File %s", path->getFullPath().c_str());
       return LogAndCreateResult(ErrorCode::IO_ERR, "Node does not exist or access denied.");
     }
-    struct dirent entry = {0};
-    struct dirent* result = nullptr;
+    struct dirent* entry = nullptr;
     PlatformResult platform_result(ErrorCode::NO_ERROR);
-    while ((0 == (readdir_r(dir, &entry, &result))) && result) {
-      if (!strcmp(entry.d_name, ".") || !strncmp(entry.d_name, "..", 2)) {
+    while (nullptr != (entry = readdir(dir))) {
+      if (!strcmp(entry->d_name, ".") || !strncmp(entry->d_name, "..", 2)) {
         continue;
       }
-      PathPtr subPath = *path + entry.d_name;
+      PathPtr subPath = *path + entry->d_name;
       struct stat info;
       memset(&info, 0, sizeof(struct stat));
       if (lstat(subPath->getFullPath().c_str(), &info) == 0) {
index 72eb206..8981306 100644 (file)
@@ -50,6 +50,7 @@
          'variables': {
             'packages': [
               'capi-network-bluetooth',
+              'capi-appfw-app-control',
               'capi-system-info',
               'libpcrecpp',
             ]
index f00cec5..8835000 100644 (file)
@@ -755,7 +755,7 @@ _out:
  * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
  */
 gboolean
-_auto_gen_org_tizen_system_deviced_display_call_lockstate_sync (
+_auto_gen_org_tizen_system_deviced_display_call_lockstate_nopt_sync (
     _auto_genOrgTizenSystemDevicedDisplay *proxy,
     const gchar *arg_state,
     const gchar *arg_option1,
@@ -767,7 +767,8 @@ _auto_gen_org_tizen_system_deviced_display_call_lockstate_sync (
 {
   GVariant *_ret;
   _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
-    "lockstate",
+    "lockstate_nopt", //Since Tizen 4.0 we call "lockstate_nopt" method
+                      //because "lockstate" requires additional privilege
     g_variant_new ("(sssi)",
                    arg_state,
                    arg_option1,
index c90e84f..04a0a07 100644 (file)
@@ -90,7 +90,7 @@ gboolean _auto_gen_org_tizen_system_deviced_display_call_lockstate_finish(
     _auto_genOrgTizenSystemDevicedDisplay *proxy, gint *out_result, GAsyncResult *res,
     GError **error);
 
-gboolean _auto_gen_org_tizen_system_deviced_display_call_lockstate_sync(
+gboolean _auto_gen_org_tizen_system_deviced_display_call_lockstate_nopt_sync(
     _auto_genOrgTizenSystemDevicedDisplay *proxy, const gchar *arg_state, const gchar *arg_option1,
     const gchar *arg_option2, gint arg_timeout, gint *out_result, GCancellable *cancellable,
     GError **error);
index f280ab4..d17a75d 100644 (file)
@@ -153,7 +153,7 @@ bool GDBusPowerWrapper::LockStateRaw(const std::string &state, const std::string
   const gint _timeout = static_cast<gint>(timeout);
 
   gint out_result;
-  gboolean ret = _auto_gen_org_tizen_system_deviced_display_call_lockstate_sync(
+  gboolean ret = _auto_gen_org_tizen_system_deviced_display_call_lockstate_nopt_sync(
       proxy_, arg_state, arg_option1, arg_option2, _timeout, &out_result, NULL, &error);
   if (!ret) {
     err_->ReportError(error);
index 7f4e78e..64404f8 100644 (file)
@@ -68,7 +68,7 @@
           'variables': {
             'packages': [
               'capi-appfw-app-manager',
-              'capi-appfw-application',
+              'capi-appfw-app-common',
               'capi-appfw-package-manager',
               'storage',
               'security-privilege-manager',
index cb7158e..5d60996 100755 (executable)
@@ -18,18 +18,201 @@ tizen.debug = extension;
 
 var JSON_ = xwalk.JSON;
 var validator_ = xwalk.utils.validator;
+var converter_ = xwalk.utils.converter;
 var types_ = validator_.Types;
+var type_ = xwalk.utils.type;
+var native_ = new xwalk.utils.NativeManager(extension);
 
 var callbackId = 0;
 var callbacks = {};
+var listeners_ = {};
 
+var DATA_CONTROL_MANAGER_LISTENER_ID = 'DataControlManagerChangeCallback';
+
+var DataType = {
+  'MAP': 'MAP',
+  'SQL': 'SQL'
+};
+
+var EventType = {
+  'SQL_UPDATE': 'SQL_UPDATE',
+  'SQL_INSERT': 'SQL_INSERT',
+  'SQL_DELETE': 'SQL_DELETE',
+  'MAP_SET': 'MAP_SET',
+  'MAP_ADD': 'MAP_ADD',
+  'MAP_REMOVE': 'MAP_REMOVE'
+};
+
+
+var DataControlListenersManager = (function() {
+
+  function changeEvent(event) {
+    var successCallback;
+
+    if (DataType.SQL === event.eventType) {
+      if (type_.isEmptyObject(this._SQLDataControlCallbackMap)) {
+        return;
+      }
+      for (var listenerId in this._SQLDataControlCallbackMap) {
+        if (this._SQLDataControlCallbackMap.hasOwnProperty(listenerId)) {
+          if (this._SQLDataControlCallbackMap[listenerId].providerId === event.providerId &&
+              this._SQLDataControlCallbackMap[listenerId].dataId === event.dataId) {
+            successCallback = this._SQLDataControlCallbackMap[listenerId].changeCallback;
+            if (type_.isFunction(successCallback)) {
+              successCallback(event.type, {columns: event.columns, values: event.values});
+            }
+          }
+        }
+      }
+    } else {
+      if (type_.isEmptyObject(this._MAPDataControlCallbackMap)) {
+        return;
+      }
+      for (var listenerId in this._MAPDataControlCallbackMap) {
+        if (this._MAPDataControlCallbackMap.hasOwnProperty(listenerId)) {
+          if (this._MAPDataControlCallbackMap[listenerId].providerId === event.providerId &&
+              this._MAPDataControlCallbackMap[listenerId].dataId === event.dataId) {
+            successCallback = this._MAPDataControlCallbackMap[listenerId].changeCallback;
+            if (type_.isFunction(successCallback)) {
+              successCallback(event.type, {columns: event.columns, values: event.values});
+            }
+          }
+        }
+      }
+    }
+  }
+
+  function _DataControlListenerManager() {
+    this._SQLDataControlCallbackMap = {};
+    this._MAPDataControlCallbackMap = {};
+    this.lastListenerId = 0;
+    this.changeEvent = changeEvent.bind(this);
+  }
+
+  _DataControlListenerManager.prototype.addChangeListener = function(type, providerId, dataId, changeCallback, errorCallback) {
+    var _realWatchId = 0;
+    if (DataType.SQL === type) {
+      for (var i in this._SQLDataControlCallbackMap) {
+        if (this._SQLDataControlCallbackMap.hasOwnProperty(i) &&
+            this._SQLDataControlCallbackMap[i].providerId === providerId &&
+            this._SQLDataControlCallbackMap[i].dataId === dataId) {
+          _realWatchId = this._SQLDataControlCallbackMap[i].realWatchId;
+        }
+      }
+    } else {
+      for (var i in this._MAPDataControlCallbackMap) {
+        if (this._MAPDataControlCallbackMap.hasOwnProperty(i) &&
+            this._MAPDataControlCallbackMap[i].providerId === providerId &&
+            this._MAPDataControlCallbackMap[i].dataId === dataId) {
+          _realWatchId = this._MAPDataControlCallbackMap[i].realWatchId;
+        }
+      }
+    }
+
+    if (!_realWatchId) {
+      var callback = function(result) {
+        if (native_.isFailure(result)) {
+          native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+          return;
+        }
+      }
+      var result =
+        callNativeWithCallback('DataControlConsumerObject_addChangeListener', {
+                               providerId: providerId,
+                               dataId: dataId,
+                               type: type
+        }, callback);
+
+      if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+      } else {
+        _realWatchId = converter_.toLong(result.watchId, true);
+      }
+      if (type_.isEmptyObject(this._SQLDataControlCallbackMap) &&
+          type_.isEmptyObject(this._MAPDataControlCallbackMap)) {
+        AddListener(DATA_CONTROL_MANAGER_LISTENER_ID, this.changeEvent);
+      }
+    }
+
+    if (DataType.SQL === type) {
+      this._SQLDataControlCallbackMap[++this.lastListenerId] = {'providerId': providerId,
+                                                                'dataId': dataId,
+                                                                'changeCallback': changeCallback,
+                                                                'realWatchId': _realWatchId};
+    } else {
+      this._MAPDataControlCallbackMap[++this.lastListenerId] = {'providerId': providerId,
+                                                                'dataId': dataId,
+                                                                'changeCallback': changeCallback,
+                                                                'realWatchId': _realWatchId};
+    }
+
+    return this.lastListenerId;
+  };
+
+  _DataControlListenerManager.prototype.removeChangeListener = function(type, providerId, dataId, listenerId) {
+    var _realWatchId = 0;
+    if (DataType.SQL === type && !type_.isUndefined(this._SQLDataControlCallbackMap[listenerId])) {
+      _realWatchId = this._SQLDataControlCallbackMap[listenerId].realWatchId;
+      delete this._SQLDataControlCallbackMap[listenerId];
+      for (var i in this._SQLDataControlCallbackMap) {
+        if (this._SQLDataControlCallbackMap.hasOwnProperty(i) &&
+            this._SQLDataControlCallbackMap[i].realWatchId === _realWatchId) {
+          return;
+        }
+      }
+    } else if (DataType.MAP === type && !type_.isUndefined(this._MAPDataControlCallbackMap[listenerId])) {
+      _realWatchId = this._MAPDataControlCallbackMap[listenerId].realWatchId;
+      delete this._MAPDataControlCallbackMap[listenerId];
+      for (var i in this._MAPDataControlCallbackMap) {
+        if (this._MAPDataControlCallbackMap.hasOwnProperty(i) &&
+            this._MAPDataControlCallbackMap[i].realWatchId === _realWatchId) {
+          return;
+        }
+      }
+    } else {
+      console.log("Type invalid or listener was not added")
+      return;
+    }
+
+    if (0 != _realWatchId) {
+      callNative('DataControlConsumerObject_removeChangeListener',{
+        providerId: providerId,
+        dataId: dataId,
+        watchId: _realWatchId,
+        type: type
+      })
+
+      if (type_.isEmptyObject(this._SQLDataControlCallbackMap) &&
+          type_.isEmptyObject(this._MAPDataControlCallbackMap)) {
+        RemoveListener(DATA_CONTROL_MANAGER_LISTENER_ID);
+      }
+    }
+  };
+
+  return _DataControlListenerManager;
+
+})();
+
+var listenersManager = new DataControlListenersManager();
+
+// TODO refactor setMessageListener to start using common functionality
 extension.setMessageListener(function(json) {
   var result = JSON_.parse(json);
-  var callback = callbacks[result['callbackId']];
-  setTimeout(function() {
-    callback(result);
-    delete callbacks[result['callbackId']];
-  }, 0);
+  if (result.hasOwnProperty("callbackId")) {
+    var callback = callbacks[result['callbackId']];
+    setTimeout(function() {
+      callback(result);
+      delete callbacks[result['callbackId']];
+    }, 0);
+  }
+  if (result.hasOwnProperty("listenerId")) {
+    var id = result['listenerId'];
+    delete result['listenerId'];
+    var f = listeners_[id];
+    setTimeout(function() {
+      f(result);
+    }, 0);
+  }
 });
 
 function nextCallbackId() {
@@ -71,15 +254,24 @@ function callNativeWithCallback(cmd, args, callback) {
   return callNative(cmd, args);
 }
 
+function AddListener(name, callback) {
+  if (!type_.isString(name) || !name.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  listeners_[name] = callback;
+};
+
+function RemoveListener(name) {
+  if (listeners_.hasOwnProperty(name)) {
+    delete listeners_[name];
+  }
+};
+
 function SetReadOnlyProperty(obj, n, v) {
   Object.defineProperty(obj, n, {value: v, writable: false});
 }
 
-var DataType = {
-  'MAP': 'MAP',
-  'SQL': 'SQL'
-};
-
 function DataControlManager() {
   // constructor of DataControlManager
 }
@@ -91,15 +283,16 @@ var getDataControlConsumer = function(providerId, dataId, type) {
   var args = validator_.validateArgs(arguments, [
     {'name': 'providerId', 'type': types_.STRING},
     {'name': 'dataId', 'type': types_.STRING},
-    {'name': 'type', 'type': types_.ENUM, 'values': ['MAP', 'SQL']}
+    {'name': 'type', 'type': types_.ENUM, 'values': [DataType.SQL, DataType.MAP]}
   ]);
 
   var returnObject = null;
-  if (type === 'SQL') {
+  if (DataType.SQL === type) {
     returnObject = new SQLDataControlConsumer();
-  } else if (type === 'MAP') {
+  } else if (DataType.MAP == type) {
     returnObject = new MappedDataControlConsumer();
   }
+
   SetReadOnlyProperty(returnObject, 'type', args.type); // read only property
   SetReadOnlyProperty(returnObject, 'providerId', args.providerId); // read only property
   SetReadOnlyProperty(returnObject, 'dataId', args.dataId); // read only property
@@ -116,7 +309,34 @@ function DataControlConsumerObject() {
   // constructor of DataControlConsumerObject
 }
 
+DataControlConsumerObject.prototype.addChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'dataChangeCallback', 'type': types_.FUNCTION, optional: false, nullable: false},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var type = DataType.SQL;
+  if (this instanceof MappedDataControlConsumer) {
+    type = DataType.MAP;
+  }
+
+  return listenersManager.addChangeListener(type, this.providerId, this.dataId,
+                                            args.dataChangeCallback, args.errorCallback);
+}
+
+DataControlConsumerObject.prototype.removeChangeListener = function() {
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'watchId', 'type': types_.LONG}
+  ]);
 
+  var type = DataType.SQL;
+  if (this instanceof MappedDataControlConsumer) {
+    type = DataType.MAP;
+  }
+
+  listenersManager.removeChangeListener(type, this.providerId, this.dataId, args.watchId);
+}
 
 function SQLDataControlConsumer() {
   // constructor of SQLDataControlConsumer
index 216d391..131b203 100644 (file)
@@ -21,7 +21,6 @@
 #include <algorithm>
 #include <functional>
 #include <map>
-#include <memory>
 #include <string>
 #include <vector>
 
@@ -38,7 +37,10 @@ namespace datacontrol {
 namespace {
 // The privileges that required in Datacontrol API
 const std::string kPrivilegeDatacontrol = "http://tizen.org/privilege/datacontrol.consumer";
-
+const std::string kPrivilegeDatasharing = "http://tizen.org/privilege/datasharing";
+const std::string kPrivilegeAppmanagerLaunch = "http://tizen.org/privilege/appmanager.launch";
+const std::string SQL = "SQL";
+const std::string MAP = "MAP";
 }  // namespace
 
 using common::InvalidValuesException;
@@ -47,10 +49,13 @@ using common::IOException;
 using common::SecurityException;
 using common::UnknownException;
 using common::NotFoundException;
+using common::AbortException;
 
 using common::ScopeExit;
 using common::operator+;
 
+using namespace common;
+
 struct DatacontrolInformation {
   int callbackId;
   int requestId;
@@ -74,7 +79,12 @@ DatacontrolInstance::DatacontrolInstance() {
                 DataControlManagerGetdatacontrolconsumer);
   REGISTER_SYNC("SQLDataControlConsumer_insert", SQLDataControlConsumerInsert);
   REGISTER_SYNC("MappedDataControlConsumer_getValue", MappedDataControlConsumerGetvalue);
+  REGISTER_SYNC("DataControlConsumerObject_removeChangeListener", RemoveChangeListener);
 #undef REGISTER_SYNC
+#define REGISTER_ASYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&DatacontrolInstance::x, this, _1, _2));
+  REGISTER_ASYNC("DataControlConsumerObject_addChangeListener", AddChangeListener);
+#undef REGISTER_ASYNC
 }
 
 DatacontrolInstance::~DatacontrolInstance() {
@@ -883,6 +893,306 @@ void DatacontrolInstance::MappedDataControlConsumerUpdatevalue(const picojson::v
   }
 }
 
+int DatacontrolInstance::CreateMAPHandle(const std::string& providerId, const std::string& dataId,
+                                         data_control_h* handle) {
+  LoggerD("Enter");
+  int result = DATA_CONTROL_ERROR_NONE;
+
+  result = ::data_control_map_create(handle);
+  RETURN_IF_FAIL(result, "Creating map data control handle is failed with error");
+
+  result = ::data_control_map_set_provider_id(*handle, providerId.c_str());
+  RETURN_IF_FAIL(result, "Setting provider id is failed with error");
+
+  result = ::data_control_map_set_data_id(*handle, dataId.c_str());
+  RETURN_IF_FAIL(result, "Setting data id is failed the error");
+
+  return result;
+}
+
+int DatacontrolInstance::CreateSQLHandle(const std::string& providerId, const std::string& dataId,
+                                         data_control_h* handle) {
+  LoggerD("Enter");
+  int result = DATA_CONTROL_ERROR_NONE;
+
+  result = ::data_control_sql_create(handle);
+  RETURN_IF_FAIL(result, "Creating sql data control handle is failed with error");
+
+  result = ::data_control_sql_set_provider_id(*handle, providerId.c_str());
+  RETURN_IF_FAIL(result, "Setting provider id is failed with error");
+
+  result = ::data_control_sql_set_data_id(*handle, dataId.c_str());
+  RETURN_IF_FAIL(result, "Setting data id is failed the error");
+
+  return result;
+}
+
+PlatformResult DatacontrolInstance::ChangeTypeToString(data_control_data_change_type_e type_e,
+                                                       std::string* type) {
+  LoggerD("Enter");
+
+  switch (type_e) {
+    case DATA_CONTROL_DATA_CHANGE_SQL_UPDATE:
+      *type = "SQL_UPDATE";
+      break;
+    case DATA_CONTROL_DATA_CHANGE_SQL_INSERT:
+      *type = "SQL_INSERT";
+      break;
+    case DATA_CONTROL_DATA_CHANGE_SQL_DELETE:
+      *type = "SQL_DELETE";
+      break;
+    case DATA_CONTROL_DATA_CHANGE_MAP_SET:
+      *type = "MAP_SET";
+      break;
+    case DATA_CONTROL_DATA_CHANGE_MAP_ADD:
+      *type = "MAP_ADD";
+      break;
+    case DATA_CONTROL_DATA_CHANGE_MAP_REMOVE:
+      *type = "MAP_REMOVE";
+      break;
+    default:
+      return LogAndCreateResult(ErrorCode::ABORT_ERR, "Undefined data change type");
+      break;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void DatacontrolInstance::callback(data_control_h provider, data_control_data_change_type_e type,
+                                   bundle* bundle_data, void* user_data) {
+  LoggerD("Enter");
+
+  auto data = static_cast<ReplyCallbackData*>(user_data);
+
+  char* provider_id = nullptr;
+  char* data_id = nullptr;
+  int result = DATA_CONTROL_ERROR_NONE;
+
+  if (DATA_CONTROL_DATA_CHANGE_SQL_UPDATE == type || DATA_CONTROL_DATA_CHANGE_SQL_INSERT == type ||
+      DATA_CONTROL_DATA_CHANGE_SQL_DELETE == type) {
+    if (MAP == data->event_type) {
+      LoggerI("Callback registered for different type");
+      return;
+    }
+
+    result = data_control_sql_get_provider_id(provider, &provider_id);
+
+    if (DATA_CONTROL_ERROR_NONE == result) {
+      result = data_control_sql_get_data_id(provider, &data_id);
+    }
+  } else {
+    if (SQL == data->event_type) {
+      LoggerI("Callback registered for different type");
+      return;
+    }
+
+    result = data_control_map_get_provider_id(provider, &provider_id);
+
+    if (DATA_CONTROL_ERROR_NONE == result) {
+      result = data_control_map_get_data_id(provider, &data_id);
+    }
+  }
+
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+
+  if (DATA_CONTROL_ERROR_NONE != result) {
+    obj.insert(std::make_pair("callbackId", picojson::value(std::to_string(data->callbackId))));
+    // According to native documentation only IOError can be returned to webapi, other errors are
+    // handled earlier
+    LogAndReportError(PlatformResult(ErrorCode::IO_ERR, "Get callback data failed"), &obj);
+    Instance::PostMessage(data->_instance, event.serialize().c_str());
+    return;
+  }
+
+  std::string event_type = "";
+  PlatformResult status = ChangeTypeToString(type, &event_type);
+
+  if (status.IsError()) {
+    obj.insert(std::make_pair("callbackId", picojson::value(std::to_string(data->callbackId))));
+    LogAndReportError(status, &obj);
+    Instance::PostMessage(data->_instance, event.serialize().c_str());
+    return;
+  }
+
+  obj.insert(std::make_pair("type", picojson::value(event_type)));
+
+  obj.insert(std::make_pair("providerId", picojson::value(std::string(provider_id))));
+  obj.insert(std::make_pair("dataId", picojson::value(std::string(data_id))));
+
+  obj.insert(std::make_pair("columns", picojson::value(picojson::array())));
+  obj.insert(std::make_pair("values", picojson::value(picojson::array())));
+
+  bundle_foreach(
+      bundle_data,
+      [](const char* key, const int type, const bundle_keyval_t* kv, void* user_data) {
+        LoggerD("Enter");
+
+        picojson::object& row_data = *(static_cast<picojson::object*>(user_data));
+
+        void* basic_val = NULL;
+        size_t basic_size = 0;
+
+        LoggerD("Key:%s, Type:%d\n", key, type);
+        bundle_keyval_get_basic_val(const_cast<bundle_keyval_t*>(kv), &basic_val, &basic_size);
+
+        row_data["columns"].get<picojson::array>().push_back(picojson::value(std::string(key)));
+        row_data["values"].get<picojson::array>().push_back(
+            picojson::value(std::string(static_cast<char*>(basic_val))));
+      },
+      &obj);
+
+  obj.insert(std::make_pair("listenerId", picojson::value("DataControlManagerChangeCallback")));
+
+  Instance::PostMessage(data->_instance, event.serialize().c_str());
+}
+
+// result_callback method is used only for pass information to errorCallback if any error
+// occur while adding listener
+void DatacontrolInstance::result_callback(data_control_h provider, data_control_error_e result,
+                                          int callback_id, void* user_data) {
+  LoggerD("Enter");
+  if (DATA_CONTROL_ERROR_NONE != result) {
+    auto data = static_cast<ReplyCallbackData*>(user_data);
+    picojson::value event = picojson::value(picojson::object());
+    picojson::object& obj = event.get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(std::to_string(data->callbackId))));
+    // According to native documentation only IOError can be returned to webapi, other errors are
+    // handled earlier
+    LogAndReportError(IOException("AddChangeListener failed"), obj);
+    Instance::PostMessage(data->_instance, event.serialize().c_str());
+    if (0 != callback_id) {
+      data->_instance->EraseMap(callback_id);
+    }
+  }
+}
+
+void DatacontrolInstance::AddChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeDatasharing, &out);
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeAppmanagerLaunch, &out);
+
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+  CHECK_EXIST(args, "type", out)
+  CHECK_EXIST(args, "callbackId", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  const std::string& type = args.get("type").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int result = DATA_CONTROL_ERROR_NONE;
+  data_control_h handle = nullptr;
+  std::function<int(data_control_h)> del;
+
+  if (SQL == type) {
+    result = CreateSQLHandle(providerId, dataId, &handle);
+    del = data_control_sql_destroy;
+  } else {
+    result = CreateMAPHandle(providerId, dataId, &handle);
+    del = data_control_map_destroy;
+  }
+
+  auto deleter = [&del](data_control_h handle) {
+    if (handle && DATA_CONTROL_ERROR_NONE != del(handle)) {
+      LoggerE("Destroy handle failed");
+    }
+  };
+
+  std::unique_ptr<std::remove_pointer<data_control_h>::type, decltype(deleter)> handle_ptr(handle,
+                                                                                           deleter);
+
+  std::shared_ptr<ReplyCallbackData> user_data(new ReplyCallbackData());
+  user_data->_instance = this;
+  user_data->callbackId = callbackId;
+  user_data->event_type = type;
+
+  if (DATA_CONTROL_ERROR_NONE != result) {
+    // According to native documentation only IOError can be returned to webapi, other errors are
+    // handled earlier
+    result_callback(handle, DATA_CONTROL_ERROR_IO_ERROR, 0, user_data.get());
+    return;
+  }
+
+  int watch_id = 0;
+  result = ::data_control_add_data_change_cb(handle, callback, user_data.get(), result_callback,
+                                             user_data.get(), &watch_id);
+
+  if (DATA_CONTROL_ERROR_NONE != result) {
+    // According to native documentation only IOError can be returned to webapi, other errors are
+    // handled earlier
+    result_callback(handle, DATA_CONTROL_ERROR_IO_ERROR, 0, user_data.get());
+    return;
+  }
+
+  reply_map.insert(std::pair<int, ReplyCallbackDataPtr>(watch_id, user_data));
+
+  picojson::value return_value = picojson::value(picojson::object());
+  picojson::object& return_value_obj = return_value.get<picojson::object>();
+
+  return_value_obj.insert(std::make_pair("watchId", picojson::value(std::to_string(watch_id))));
+  ReportSuccess(return_value, out);
+}
+
+void DatacontrolInstance::RemoveChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeDatasharing, &out);
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeAppmanagerLaunch, &out);
+
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+  CHECK_EXIST(args, "watchId", out)
+  CHECK_EXIST(args, "type", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  const std::string& type = args.get("type").get<std::string>();
+  int watch_id = static_cast<int>(args.get("watchId").get<double>());
+  data_control_h handle = nullptr;
+  std::function<int(data_control_h)> del;
+  int result = DATA_CONTROL_ERROR_NONE;
+
+  if (SQL == type) {
+    result = CreateSQLHandle(providerId, dataId, &handle);
+    del = data_control_sql_destroy;
+  } else {
+    result = CreateMAPHandle(providerId, dataId, &handle);
+    del = data_control_map_destroy;
+  }
+
+  if (DATA_CONTROL_ERROR_NONE != result) {
+    // According to native documentation only IOError can be returned to webapi, other errors are
+    // handled earlier
+    LogAndReportError(IOException("RemoveChangeListener failed"), out,
+                      ("RemoveChangeListener failed: %d (%s)", result, get_error_message(result)));
+    return;
+  }
+
+  auto deleter = [&del](data_control_h handle) {
+    if (handle && DATA_CONTROL_ERROR_NONE != del(handle)) {
+      LoggerE("Destroy handle failed");
+    }
+  };
+
+  std::unique_ptr<std::remove_pointer<data_control_h>::type, decltype(deleter)> handle_ptr(handle,
+                                                                                           deleter);
+
+  result = ::data_control_remove_data_change_cb(handle, watch_id);
+
+  if (DATA_CONTROL_ERROR_NONE != result) {
+    // According to native documentation only IOError can be returned to webapi, other errors are
+    // handled earlier
+    LogAndReportError(IOException("RemoveChangeListener failed"), out,
+                      ("RemoveChangeListener failed: %d (%s)", result, get_error_message(result)));
+    return;
+  }
+
+  reply_map.erase(watch_id);
+
+  ReportSuccess(out);
+}
+
 #undef CHECK_EXIST
 
 }  // namespace datacontrol
index eed2bce..3478e97 100644 (file)
@@ -18,6 +18,8 @@
 #define DATACONTROL_DATACONTROL_INSTANCE_H_
 
 #include <data_control.h>
+#include <map>
+#include <memory>
 #include <string>
 
 #include "common/extension.h"
 namespace extension {
 namespace datacontrol {
 
+class DatacontrolInstance;
+
+struct ReplyCallbackData {
+  DatacontrolInstance* _instance;
+  int callbackId;
+  std::string event_type;
+};
+
+typedef std::shared_ptr<ReplyCallbackData> ReplyCallbackDataPtr;
+typedef std::map<int, ReplyCallbackDataPtr> ReplyCallbackDataMap;
+
 class DatacontrolInstance : public common::ParsedInstance {
  public:
   DatacontrolInstance();
@@ -36,6 +49,23 @@ class DatacontrolInstance : public common::ParsedInstance {
   int RunSQLDataControlJob(const std::string& providerId, const std::string& dataId, int callbackId,
                            int userRequestId, DataControlJob job);
 
+  int CreateMAPHandle(const std::string& providerId, const std::string& dataId,
+                      data_control_h* handle);
+
+  int CreateSQLHandle(const std::string& providerId, const std::string& dataId,
+                      data_control_h* handle);
+
+  void EraseMap(int watch_id) {
+    reply_map.erase(watch_id);
+  };
+
+  static void callback(data_control_h provider, data_control_data_change_type_e type,
+                       bundle* bundle_data, void* user_data);
+  static void result_callback(data_control_h provider, data_control_error_e result, int callback_id,
+                              void* user_data);
+  static common::PlatformResult ChangeTypeToString(data_control_data_change_type_e type_e,
+                                                   std::string* type);
+
  private:
   void DataControlManagerGetdatacontrolconsumer(const picojson::value& args, picojson::object& out);
   void SQLDataControlConsumerInsert(const picojson::value& args, picojson::object& out);
@@ -46,6 +76,10 @@ class DatacontrolInstance : public common::ParsedInstance {
   void MappedDataControlConsumerRemovevalue(const picojson::value& args, picojson::object& out);
   void MappedDataControlConsumerGetvalue(const picojson::value& args, picojson::object& out);
   void MappedDataControlConsumerUpdatevalue(const picojson::value& args, picojson::object& out);
+  void AddChangeListener(const picojson::value& args, picojson::object& out);
+  void RemoveChangeListener(const picojson::value& args, picojson::object& out);
+
+  ReplyCallbackDataMap reply_map;
 };
 
 }  // namespace datacontrol
index 3ea612b..1217373 100644 (file)
@@ -23,9 +23,9 @@
 #include "common/filesystem/filesystem_provider.h"
 #include "common/logger.h"
 #include "common/picojson.h"
+#include "common/scope_exit.h"
 #include "common/tools.h"
 #include "common/typeutil.h"
-#include "common/scope_exit.h"
 
 namespace extension {
 namespace download {
@@ -530,8 +530,8 @@ void DownloadInstance::DownloadManagerStart(const picojson::value& args, picojso
 
   if (CONNECTION_TYPE_DISCONNECTED == connection_type) {
     LogAndReportError(
-        common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Connection problem occured"),
-        &out, ("Connection type is disconnected"));
+        common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Connection problem occured"), &out,
+        ("Connection type is disconnected"));
     return;
   }
 
index d4c7b7e..b0bdcfd 100644 (file)
@@ -100,17 +100,17 @@ FilesystemError copyDirectory(const std::string& originPath, const std::string&
   SCOPE_EXIT {
     (void)closedir(dp);
   };
-  struct dirent entry;
-  struct dirent* result = nullptr;
-  while (0 == (status = readdir_r(dp, &entry, &result)) && result != nullptr) {
-    if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0) continue;
+  errno = 0;
+  struct dirent* entry = nullptr;
+  while (nullptr != (entry = readdir(dp))) {
+    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
 
-    std::string oldLocation = originPath + std::string("/") + std::string(result->d_name);
-    std::string newLocation = destPath + std::string("/") + std::string(result->d_name);
+    std::string oldLocation = originPath + std::string("/") + std::string(entry->d_name);
+    std::string newLocation = destPath + std::string("/") + std::string(entry->d_name);
     FilesystemError fstatus = FilesystemError::None;
-    if (result->d_type == DT_DIR) {
+    if (entry->d_type == DT_DIR) {
       fstatus = copyDirectory(oldLocation, newLocation);
-    } else if (result->d_type == DT_REG) {
+    } else if (entry->d_type == DT_REG) {
       fstatus = copyFile(oldLocation, newLocation);
     }
     if (fstatus != FilesystemError::None) {
@@ -118,7 +118,8 @@ FilesystemError copyDirectory(const std::string& originPath, const std::string&
       return fstatus;
     }
   }
-  if (status != 0) {
+
+  if (0 != errno) {
     LoggerE("error occured");
     return FilesystemError::Other;
   }
@@ -349,18 +350,17 @@ void FilesystemManager::ReadDir(
 
   std::vector<std::string> fileList;
   DIR* dp = nullptr;
-  struct dirent entry;
-  struct dirent* result = nullptr;
-  int status = 0;
+  struct dirent* entry = nullptr;
 
   dp = opendir(path.c_str());
   if (dp != NULL) {
-    while ((status = readdir_r(dp, &entry, &result)) == 0 && result != nullptr) {
-      if (strcmp(result->d_name, ".") != 0 && strcmp(result->d_name, "..") != 0)
-        fileList.push_back(path + "/" + std::string(result->d_name));
+    errno = 0;
+    while (nullptr != (entry = readdir(dp))) {
+      if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
+        fileList.push_back(path + "/" + std::string(entry->d_name));
     }
     (void)closedir(dp);
-    if (status == 0) {
+    if (0 == errno) {
       success_cb(fileList);
     } else {
       LoggerE("error occured");
index 889a808..ebc78ac 100644 (file)
@@ -115,19 +115,18 @@ FilesystemStat FilesystemStat::getStat(const std::string& path) {
       (void)closedir(dir);
     };
 
-    struct dirent entry;
-    struct dirent* result = nullptr;
-    int status;
+    errno = 0;
+    struct dirent* entry = nullptr;
 
-    while ((0 == (status = readdir_r(dir, &entry, &result)) && result != nullptr)) {
-      std::string name = result->d_name;
+    while (nullptr != (entry = readdir(dir))) {
+      std::string name = entry->d_name;
       if (name == "." || name == "..") {
         continue;
       }
       _result.nlink++;
     }
 
-    if (status != 0) {
+    if (0 != errno) {
       LoggerE("Cannot count files in directory: %s", GetErrorString(errno).c_str());
       return _result;
     }
diff --git a/src/humanactivitymonitor/gesture_manager.cc b/src/humanactivitymonitor/gesture_manager.cc
new file mode 100644 (file)
index 0000000..1168f4b
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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 "humanactivitymonitor/gesture_manager.h"
+
+#include <gesture_recognition.h>
+
+#include "common/extension.h"
+#include "common/logger.h"
+#include "common/optional.h"
+#include "common/picojson.h"
+#include "common/scope_exit.h"
+#include "common/tools.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+using common::PlatformResult;
+using common::ErrorCode;
+using common::tools::ReportError;
+using common::tools::ReportSuccess;
+
+namespace {
+
+const std::string kListenerId = "listenerId";
+const std::string kListener = "GestureRecognitionListener";
+const std::string kType = "type";
+const std::string kTimestamp = "timestamp";
+const std::string kAlwayOn = "alwaysOn";
+const std::string kAction = "action";
+const std::string kEvent = "event";
+const std::string kError = "error";
+const std::string kOnError = "onerror";
+const std::string kOnDetect = "ondetect";
+
+ErrorCode getErrorCode(int error) {
+  switch (error) {
+    case GESTURE_ERROR_NONE:
+      return ErrorCode::NO_ERROR;
+    case GESTURE_ERROR_INVALID_PARAMETER:
+      return ErrorCode::INVALID_VALUES_ERR;
+    case GESTURE_ERROR_OPERATION_FAILED:
+      return ErrorCode::IO_ERR;
+    case GESTURE_ERROR_NOT_SUPPORTED:
+      return ErrorCode::NOT_SUPPORTED_ERR;
+    case GESTURE_ERROR_INVALID_OPERATION:
+    case GESTURE_ERROR_OUT_OF_MEMORY:
+    case GESTURE_ERROR_PERMISSION_DENIED:
+    case GESTURE_ERROR_ALREADY_STARTED:
+    case GESTURE_ERROR_NOT_STARTED:
+    default:
+      return ErrorCode::ABORT_ERR;
+  }
+}
+
+PlatformResult StrToGestureType(const std::string& type, gesture_type_e* type_e) {
+  if ("GESTURE_DOUBLE_TAP" == type) {
+    *type_e = GESTURE_DOUBLE_TAP;
+  } else if ("GESTURE_MOVE_TO_EAR" == type) {
+    *type_e = GESTURE_MOVE_TO_EAR;
+  } else if ("GESTURE_NO_MOVE" == type) {
+    *type_e = GESTURE_NO_MOVE;
+  } else if ("GESTURE_PICK_UP" == type) {
+    *type_e = GESTURE_PICK_UP;
+  } else if ("GESTURE_SHAKE" == type) {
+    *type_e = GESTURE_SHAKE;
+  } else if ("GESTURE_SNAP" == type) {
+    *type_e = GESTURE_SNAP;
+  } else if ("GESTURE_TILT" == type) {
+    *type_e = GESTURE_TILT;
+  } else if ("GESTURE_TURN_FACE_DOWN" == type) {
+    *type_e = GESTURE_TURN_FACE_DOWN;
+  } else if ("GESTURE_WRIST_UP" == type) {
+    *type_e = GESTURE_WRIST_UP;
+  } else {
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unknown gesture type");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::string GestureTypeToStr(gesture_type_e type) {
+  switch (type) {
+    case GESTURE_DOUBLE_TAP:
+      return "GESTURE_DOUBLE_TAP";
+    case GESTURE_MOVE_TO_EAR:
+      return "GESTURE_MOVE_TO_EAR";
+    case GESTURE_NO_MOVE:
+      return "GESTURE_NO_MOVE";
+    case GESTURE_PICK_UP:
+      return "GESTURE_PICK_UP";
+    case GESTURE_SHAKE:
+      return "GESTURE_SHAKE";
+    case GESTURE_SNAP:
+      return "GESTURE_SNAP";
+    case GESTURE_TILT:
+      return "GESTURE_TILT";
+    case GESTURE_TURN_FACE_DOWN:
+      return "GESTURE_TURN_FACE_DOWN";
+    case GESTURE_WRIST_UP:
+      return "GESTURE_WRIST_UP";
+    default:
+      return "GESTURE_UNKNOWN_TYPE";
+  }
+}
+std::string GestureEventToStr(gesture_event_e event, gesture_type_e gesture) {
+  switch (event) {
+    // GESTURE_EVENT_DETECTED == GESTURE_SHAKE_DETECTED == GESTURE_SNAP_X_NEGATIVE == 1
+    case GESTURE_EVENT_DETECTED:
+      if (GESTURE_SHAKE == gesture) {
+        return "GESTURE_SHAKE_DETECTED";
+      } else if (GESTURE_SNAP == gesture) {
+        return "GESTURE_SNAP_X_NEGATIVE";
+      } else {
+        return "GESTURE_EVENT_DETECTED";
+      }
+    // GESTURE_SHAKE_FINISHED == GESTURE_SNAP_X_POSITIVE == 2
+    case GESTURE_SHAKE_FINISHED:
+      if (GESTURE_SHAKE == gesture) {
+        return "GESTURE_SHAKE_FINISHED";
+      } else {
+        return "GESTURE_SNAP_X_POSITIVE";
+      }
+    case GESTURE_SNAP_Y_NEGATIVE:
+      return "GESTURE_SNAP_Y_NEGATIVE";
+    case GESTURE_SNAP_Y_POSITIVE:
+      return "GESTURE_SNAP_Y_POSITIVE";
+    case GESTURE_SNAP_Z_NEGATIVE:
+      return "GESTURE_SNAP_Z_NEGATIVE";
+    case GESTURE_SNAP_Z_POSITIVE:
+      return "GESTURE_SNAP_Z_POSITIVE";
+    default:
+      return "GESTURE_EVENT_NONE";
+  }
+}
+
+void GestureRecognitionDefaultCb(gesture_type_e gesture, const gesture_data_h data,
+                                 double timestamp, gesture_error_e error, void* user_data) {
+  ScopeLogger();
+
+  GestureManager* manager = static_cast<GestureManager*>(user_data);
+  if (!manager) {
+    LoggerW("User data is null");
+    return;
+  }
+
+  manager->CompleteGestureListenerCb(gesture, data, timestamp, error, false);
+}
+
+void GestureRecognitionAlwaysOnCb(gesture_type_e gesture, const gesture_data_h data,
+                                  double timestamp, gesture_error_e error, void* user_data) {
+  ScopeLogger();
+  GestureManager* manager = static_cast<GestureManager*>(user_data);
+
+  if (!manager) {
+    LoggerW("User data is null");
+    return;
+  }
+
+  manager->CompleteGestureListenerCb(gesture, data, timestamp, error, true);
+}
+
+}  // namespace
+
+GestureManager::GestureManager()
+    : m_callback(nullptr), m_recognition_default_map(), m_recognition_always_on_map() {
+  ScopeLogger();
+}
+
+GestureManager::~GestureManager() {
+  ScopeLogger();
+
+  int ret = GESTURE_ERROR_NONE;
+
+  for (auto& it : m_recognition_default_map) {
+    ret = gesture_stop_recognition(it.second);
+    if (GESTURE_ERROR_NONE != ret) {
+      LoggerE("gesture_stop_recognition() failed");
+    }
+
+    ret = gesture_release(it.second);
+    if (GESTURE_ERROR_NONE != ret) {
+      LoggerE("gesture_release() failed");
+    }
+  }
+
+  for (auto& it : m_recognition_always_on_map) {
+    ret = gesture_stop_recognition(it.second);
+    if (GESTURE_ERROR_NONE != ret) {
+      LoggerE("gesture_stop_recognition() failed");
+    }
+
+    ret = gesture_release(it.second);
+    if (GESTURE_ERROR_NONE != ret) {
+      LoggerE("gesture_release() failed");
+    }
+  }
+
+  m_recognition_default_map.clear();
+  m_recognition_always_on_map.clear();
+}
+
+PlatformResult GestureManager::IsSupported(const std::string& type, bool* is_supported) {
+  ScopeLogger();
+
+  gesture_type_e type_e = GESTURE_DOUBLE_TAP;
+  PlatformResult result = StrToGestureType(type, &type_e);
+  if (!result) {
+    return result;
+  }
+
+  int ret = gesture_is_supported(type_e, is_supported);
+  if (GESTURE_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        getErrorCode(ret), "Checking gesture failed",
+        ("Checking gesture failed, error: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+gesture_event_e GestureManager::GetGestureEvent(const gesture_data_h data) {
+  ScopeLogger();
+
+  gesture_event_e event = GESTURE_EVENT_NONE;
+  int ret = gesture_get_event(data, &event);
+  if (GESTURE_ERROR_NONE != ret) {
+    LoggerE("gesture_get_event() failed, error %d (%s)", ret, get_error_message(ret));
+  }
+
+  return event;
+}
+
+void GestureManager::FillTiltData(const gesture_data_h data, picojson::object* obj) {
+  ScopeLogger();
+
+  int x = 0;
+  int y = 0;
+
+  int ret = gesture_get_tilt(data, &x, &y);
+  if (GESTURE_ERROR_NONE != ret) {
+    LoggerE("gesture_get_tilt() failed, error %d (%s)", ret, get_error_message(ret));
+  }
+
+  obj->insert(std::make_pair("x", picojson::value(static_cast<double>(x))));
+  obj->insert(std::make_pair("y", picojson::value(static_cast<double>(y))));
+}
+
+void GestureManager::CompleteGestureListenerCb(gesture_type_e gesture, const gesture_data_h data,
+                                               double timestamp, gesture_error_e error,
+                                               bool always_on) {
+  ScopeLogger();
+
+  picojson::value response = picojson::value(picojson::object());
+  auto& obj = response.get<picojson::object>();
+
+  obj.insert(std::make_pair(kAlwayOn, picojson::value(always_on)));
+  obj.insert(std::make_pair(kListenerId, picojson::value(kListener)));
+
+  if (GESTURE_ERROR_NONE != error) {
+    obj.insert(std::make_pair(kAction, picojson::value(kOnError)));
+
+    PlatformResult result =
+        LogAndCreateResult(getErrorCode(error), "Error occurred during recognition");
+    ReportError(result, &obj);
+  } else {
+    gesture_event_e event = GetGestureEvent(data);
+    if (GESTURE_EVENT_NONE == event) {
+      LoggerD("Gesture event none detected.");
+      return;
+    }
+
+    std::string gesture_str = GestureTypeToStr(gesture);
+    if ("GESTURE_UNKNOWN_TYPE" == gesture_str) {
+      LoggerE("Unknown gesture type");
+      return;
+    }
+
+    obj.insert(std::make_pair(kAction, picojson::value(kOnDetect)));
+
+    picojson::value result = picojson::value(picojson::object());
+    auto& result_obj = result.get<picojson::object>();
+
+    result_obj.insert(std::make_pair(kEvent, picojson::value(GestureEventToStr(event, gesture))));
+    result_obj.insert(std::make_pair(kTimestamp, picojson::value(timestamp)));
+    result_obj.insert(std::make_pair(kType, picojson::value(gesture_str)));
+
+    if (GESTURE_TILT == gesture) {
+      FillTiltData(data, &result_obj);
+    }
+
+    ReportSuccess(result, obj);
+  }
+
+  if (!m_callback) {
+    LoggerE("Callback is not defined");
+  } else {
+    m_callback(&response);
+  }
+}
+
+PlatformResult GestureManager::AddListener(gesture_type_e type, gesture_option_e option,
+                                           RecognitionMap& gesture_map,
+                                           gesture_recognition_cb callback) {
+  ScopeLogger();
+
+  gesture_h handle = nullptr;
+
+  int ret = gesture_create(&handle);
+  if (GESTURE_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        getErrorCode(ret), "Creating handle failed",
+        ("Creating handle failed, error: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  ret = gesture_start_recognition(handle, type, option, callback, this);
+  if (GESTURE_ERROR_NONE != ret) {
+    gesture_release(handle);
+    return LogAndCreateResult(
+        getErrorCode(ret), "Starting recognition failed",
+        ("Starting recognition failed, error: %d (%s)", ret, get_error_message(ret)));
+  }
+
+  gesture_map[type] = handle;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult GestureManager::AddGestureRecognitionListener(const std::string& type,
+                                                             bool always_on, JsonCallback cb) {
+  ScopeLogger();
+
+  gesture_type_e type_e = GESTURE_DOUBLE_TAP;
+  PlatformResult result = StrToGestureType(type, &type_e);
+  if (!result) {
+    return result;
+  }
+
+  gesture_option_e option = GESTURE_OPTION_DEFAULT;
+  gesture_recognition_cb callback = GestureRecognitionDefaultCb;
+  RecognitionMap* gesture_map = &m_recognition_default_map;
+
+  if (!m_callback) {
+    m_callback = cb;
+  }
+
+  if (always_on) {
+    option = GESTURE_OPTION_ALWAYS_ON;
+    callback = GestureRecognitionAlwaysOnCb;
+    gesture_map = &m_recognition_always_on_map;
+  }
+
+  return AddListener(type_e, option, *gesture_map, callback);
+}
+
+PlatformResult GestureManager::RemoveGestureRecognitionListener(const std::string& type,
+                                                                bool always_on) {
+  ScopeLogger();
+
+  auto& recognition_map = always_on ? m_recognition_always_on_map : m_recognition_default_map;
+  gesture_type_e type_e = GESTURE_DOUBLE_TAP;
+  PlatformResult result = StrToGestureType(type, &type_e);
+  if (!result) {
+    LoggerD("Unknown gesture type.");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  gesture_h handle = nullptr;
+  RecognitionMap::iterator it = recognition_map.find(type_e);
+
+  if (recognition_map.end() != it) {
+    handle = it->second;
+  }
+
+  if (handle) {
+    int ret = gesture_stop_recognition(handle);
+    if (GESTURE_ERROR_NONE != ret) {
+      return LogAndCreateResult(
+          getErrorCode(ret), "Stoping recognition failed",
+          ("Stoping recognition failed, error: %d (%s)", ret, get_error_message(ret)));
+    }
+
+    ret = gesture_release(handle);
+    if (GESTURE_ERROR_NONE != ret) {
+      LoggerE("gesture_release() failed");
+    }
+
+    recognition_map.erase(it);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace humanactivitymonitor
+}  // namespace extension
diff --git a/src/humanactivitymonitor/gesture_manager.h b/src/humanactivitymonitor/gesture_manager.h
new file mode 100644 (file)
index 0000000..75b05f9
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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 HUMANACTIVITYMONITOR_GESTURE_MANAGER_H
+#define HUMANACTIVITYMONITOR_GESTURE_MANAGER_H
+
+#include <gesture_recognition.h>
+#include <functional>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+using JsonCallback = std::function<void(picojson::value*)>;
+
+typedef std::map<gesture_type_e, gesture_h> RecognitionMap;
+
+class GestureManager {
+ public:
+  GestureManager();
+  virtual ~GestureManager();
+
+  common::PlatformResult IsSupported(const std::string& types, bool* is_supported);
+  common::PlatformResult AddGestureRecognitionListener(const std::string& type, bool always_on,
+                                                       JsonCallback cb);
+  common::PlatformResult RemoveGestureRecognitionListener(const std::string& type, bool always_on);
+  void CompleteGestureListenerCb(gesture_type_e gesture, const gesture_data_h data,
+                                 double timestamp, gesture_error_e error, bool always_on);
+
+ private:
+  gesture_event_e GetGestureEvent(const gesture_data_h data);
+  void FillTiltData(const gesture_data_h data, picojson::object* obj);
+  common::PlatformResult AddListener(gesture_type_e type, gesture_option_e option,
+                                     RecognitionMap& gesture_map, gesture_recognition_cb callback);
+
+  JsonCallback m_callback;
+  RecognitionMap m_recognition_default_map;
+  RecognitionMap m_recognition_always_on_map;
+};
+
+}  // namespace humanactivitymonitor
+}  // namespace extension
+
+#endif  // HUMANACTIVITYMONITOR_GESTURE_MANAGER_H
index 6c250c1..c6b54a0 100755 (executable)
@@ -17,6 +17,8 @@
         'humanactivitymonitor_instance.h',
         'humanactivitymonitor_manager.cc',
         'humanactivitymonitor_manager.h',
+        'gesture_manager.cc',
+        'gesture_manager.h',
       ],
       'conditions': [
         ['tizen == 1', {
index 3f06004..7b3a8f7 100755 (executable)
@@ -78,6 +78,18 @@ var SleepStatus = {
   AWAKE: 'AWAKE'
 };
 
+var GestureType = {
+  GESTURE_DOUBLE_TAP : 'GESTURE_DOUBLE_TAP',
+  GESTURE_MOVE_TO_EAR : 'GESTURE_MOVE_TO_EAR',
+  GESTURE_NO_MOVE : 'GESTURE_NO_MOVE',
+  GESTURE_PICK_UP : 'GESTURE_PICK_UP',
+  GESTURE_SHAKE : 'GESTURE_SHAKE',
+  GESTURE_SNAP : 'GESTURE_SNAP',
+  GESTURE_TILT : 'GESTURE_TILT',
+  GESTURE_TURN_FACE_DOWN : 'GESTURE_TURN_FACE_DOWN',
+  GESTURE_WRIST_UP : 'GESTURE_WRIST_UP',
+};
+
 function convertActivityData(type, data) {
   switch (type) {
     case HumanActivityType.PEDOMETER:
@@ -512,6 +524,157 @@ HumanActivityMonitorManager.prototype.readRecorderData = function() {
   }
 };
 
+HumanActivityMonitorManager.prototype.isGestureSupported = function() {
+  var args = validator_.validateMethod(arguments, [{
+    name : 'type',
+    type: types_.ENUM,
+    values: Object.keys(GestureType)
+  }
+  ]);
+
+  var callArgs = {};
+  callArgs.type = args.type;
+
+  var result = native_.callSync('GestureManager_isGestureSupported', callArgs);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return native_.getResultObject(result);
+};
+
+function GestureListenerManager(native, listenerName) {
+  this.listeners = {};
+  //below maps keep information about number of registered listeners for the specific type
+  //there are two maps as one keeps information about listeners which should be always called
+  //and one keeps information about number of the listeners which should be called only
+  //if power-saving mode is off
+  this.typeCountMapDefault = {};
+  this.typeCountMapAlwaysOn = {};
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+  for (var type in GestureType) {
+    this.typeCountMapDefault[type] = this.typeCountMapAlwaysOn[type] = 0;
+  }
+};
+
+GestureListenerManager.prototype.onListenerCalled = function(msg) {
+  var d = undefined;
+  var result = undefined;
+  var alwaysOn = msg.alwaysOn;
+  switch (msg.action) {
+    case 'ondetect':
+      d = new GestureData(this.native.getResultObject(msg));
+      break;
+    case 'onerror':
+      d = this.native.getErrorObject(msg);
+      break;
+    default:
+      utils_.log('Unknown mode: ' + msg.action);
+      return;
+  }
+
+  for (var watchId in this.listeners) {
+    if (this.listeners.hasOwnProperty(watchId)) {
+      var listener = this.listeners[watchId];
+      var call = alwaysOn ? listener.alwaysOn : true;
+      if (call && listener[msg.action]) {
+        listener[msg.action](d);
+      }
+    }
+  }
+};
+
+GestureListenerManager.prototype.addListener = function(successCb, errorCb, type, alwaysOn) {
+  var listener = {
+      'type' : type,
+      'alwaysOn' : alwaysOn,
+      'ondetect' : successCb,
+      'onerror' : errorCb
+  };
+
+  var typeCountMap = alwaysOn ? this.typeCountMapAlwaysOn : this.typeCountMapDefault;
+  if (typeCountMap[type] === 0) {
+    var result = this.native.callSync('GestureManager_addGestureRecognitionListener', listener);
+    if (this.native.isFailure(result)) {
+      throw this.native.getErrorObject(result);
+    }
+  }
+
+  typeCountMap[type]++;
+  var id = this.nextId++;
+  this.listeners[id] = listener;
+
+  if (!this.nativeSet) {
+    this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+    this.nativeSet = true;
+  }
+
+  return id;
+};
+
+GestureListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+      var listener = this.listeners[watchId];
+      var typeCountMap = listener.alwaysOn ? this.typeCountMapAlwaysOn : this.typeCountMapDefault;
+
+      if (typeCountMap[listener.type] === 1) {
+        var result = this.native.callSync('GestureManager_removeGestureRecognitionListener', listener);
+        if (this.native.isFailure(result)) {
+          throw this.native.getErrorObject(result);
+        }
+      }
+
+      delete this.listeners[watchId];
+      typeCountMap[listener.type]--;
+  }
+
+  if (this.nativeSet && type_.isEmptyObject(this.listeners)) {
+    this.native.removeListener(this.listenerName);
+    this.nativeSet = false;
+  }
+};
+
+var GESTURE_RECOGNITION_LISTENER = 'GestureRecognitionListener';
+var gestureRecognitionListener = new GestureListenerManager(native_, GESTURE_RECOGNITION_LISTENER);
+
+HumanActivityMonitorManager.prototype.addGestureRecognitionListener = function() {
+  var args = validator_.validateMethod(arguments, [{
+    name : 'type',
+    type: types_.ENUM,
+    values: Object.keys(GestureType)
+  },
+  {
+    name : 'eventCallback',
+    type : types_.FUNCTION
+  },
+  {
+    name : 'errorCallback',
+    type : types_.FUNCTION,
+    optional: true,
+    nullable: true
+  },
+  {
+    name : 'alwaysOn',
+    type : types_.BOOLEAN,
+    optional : true,
+    nullable : true
+  }]);
+
+  return gestureRecognitionListener.addListener(args.eventCallback, args.errorCallback, args.type, args.alwaysOn);
+};
+
+HumanActivityMonitorManager.prototype.removeGestureRecognitionListener = function() {
+  var args = validator_.validateMethod(arguments, [{
+    name : 'watchId',
+    type : types_.LONG,
+  }]);
+
+  gestureRecognitionListener.removeListener(args.watchId);
+};
+
 function StepDifference(data) {
   SetReadOnlyProperty(this, 'stepCountDifference', data.stepCountDifference);
   SetReadOnlyProperty(this, 'timestamp', data.timestamp);
@@ -649,6 +812,22 @@ function HumanActivityRecorderPressureData(data) {
   SetReadOnlyProperty(this, 'average', data.average);
 }
 
+function GestureData(data) {
+  if (data) {
+    SetReadOnlyProperty(this, 'type', data.type);
+    SetReadOnlyProperty(this, 'event', data.event);
+    SetReadOnlyProperty(this, 'timestamp', data.timestamp);
+
+    if (data.type === 'GESTURE_TILT') {
+      SetReadOnlyProperty(this, 'x', data.x);
+      SetReadOnlyProperty(this, 'y', data.y);
+    } else {
+      SetReadOnlyProperty(this, 'x', null);
+      SetReadOnlyProperty(this, 'y', null);
+    }
+  }
+}
+
 HumanActivityRecorderPressureData.prototype = new HumanActivityRecorderData();
 HumanActivityRecorderPressureData.prototype.constructor = HumanActivityRecorderPressureData;
 
index efa07ab..2ba412d 100644 (file)
@@ -43,7 +43,7 @@ using common::PlatformResult;
 using common::ErrorCode;
 using common::TaskQueue;
 
-HumanActivityMonitorInstance::HumanActivityMonitorInstance() {
+HumanActivityMonitorInstance::HumanActivityMonitorInstance() : gesture_manager_() {
   LoggerD("Enter");
   using std::placeholders::_1;
   using std::placeholders::_2;
@@ -64,6 +64,11 @@ HumanActivityMonitorInstance::HumanActivityMonitorInstance() {
                 HumanActivityMonitorManagerStopRecorder);
   REGISTER_SYNC("HumanActivityMonitorManager_readRecorderData",
                 HumanActivityMonitorManagerReadRecorderData);
+  REGISTER_SYNC("GestureManager_isGestureSupported", GestureManagerIsGestureSupported);
+  REGISTER_SYNC("GestureManager_addGestureRecognitionListener",
+                GestureManagerAddGestureRecognitionListener);
+  REGISTER_SYNC("GestureManager_removeGestureRecognitionListener",
+                GestureManagerRemoveGestureRecognitionListener);
 #undef REGISTER_SYNC
 }
 
@@ -377,6 +382,66 @@ void HumanActivityMonitorInstance::HumanActivityMonitorManagerReadRecorderData(
   ReportSuccess(out);
 }
 
+void HumanActivityMonitorInstance::GestureManagerIsGestureSupported(const picojson::value& args,
+                                                                    picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "type", out)
+  const auto& type = args.get("type").get<std::string>();
+  bool is_supported = false;
+
+  PlatformResult result = gesture_manager_.IsSupported(type, &is_supported);
+  if (result) {
+    ReportSuccess(picojson::value(is_supported), out);
+  } else {
+    LogAndReportError(result, &out, ("Failed: gesture_manager_->IsSupported()"));
+  }
+}
+
+void HumanActivityMonitorInstance::GestureManagerAddGestureRecognitionListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "type", out)
+  CHECK_EXIST(args, "alwaysOn", out)
+  const auto& type = args.get("type").get<std::string>();
+  bool always_on = args.get("alwaysOn").get<bool>();
+
+  auto cb = [this](picojson::value* data) -> void {
+    if (!data) {
+      LoggerE("No data passed to json callback");
+      return;
+    }
+
+    Instance::PostMessage(this, data->serialize().c_str());
+  };
+
+  PlatformResult result = gesture_manager_.AddGestureRecognitionListener(type, always_on, cb);
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LogAndReportError(result, &out, ("Failed: gesture_manager_->AddGestureRecognitionListener()"));
+  }
+}
+
+void HumanActivityMonitorInstance::GestureManagerRemoveGestureRecognitionListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "type", out)
+  CHECK_EXIST(args, "alwaysOn", out)
+  const auto& type = args.get("type").get<std::string>();
+  bool always_on = args.get("alwaysOn").get<bool>();
+
+  PlatformResult result = gesture_manager_.RemoveGestureRecognitionListener(type, always_on);
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LogAndReportError(result, &out,
+                      ("Failed: gesture_manager_->RemoveGestureRecognitionListener()"));
+  }
+}
+
 #undef CHECK_EXIST
 
 }  // namespace humanactivitymonitor
index e55dc1f..e0ed215 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "common/extension.h"
 #include "common/platform_result.h"
+#include "humanactivitymonitor/gesture_manager.h"
 #include "humanactivitymonitor/humanactivitymonitor_manager.h"
 
 namespace extension {
@@ -44,8 +45,14 @@ class HumanActivityMonitorInstance : public common::ParsedInstance {
   void HumanActivityMonitorManagerStopRecorder(const picojson::value& args, picojson::object& out);
   void HumanActivityMonitorManagerReadRecorderData(const picojson::value& args,
                                                    picojson::object& out);
+  void GestureManagerIsGestureSupported(const picojson::value& args, picojson::object& out);
+  void GestureManagerAddGestureRecognitionListener(const picojson::value& args,
+                                                   picojson::object& out);
+  void GestureManagerRemoveGestureRecognitionListener(const picojson::value& args,
+                                                      picojson::object& out);
 
   std::shared_ptr<HumanActivityMonitorManager> manager_;
+  GestureManager gesture_manager_;
   common::PlatformResult Init();
 };
 
index 25b02f9..79597cd 100644 (file)
@@ -34,7 +34,7 @@
             'packages': [
                 'capi-system-info',
                 'capi-network-nfc',
-                'capi-appfw-application'
+                'capi-appfw-app-control',
             ]
           },
         }],
index 8c3b5ca..5cf9331 100644 (file)
@@ -89,6 +89,7 @@ NFCAdapter::NFCAdapter()
       m_is_ndef_listener_set(false),
       m_se_handle(nullptr),
       m_is_hce_listener_set(false),
+      m_is_preferred_app_set(false),
       responder_(nullptr) {
   LoggerD("Entered");
   // NFC library initialization
@@ -121,6 +122,9 @@ NFCAdapter::~NFCAdapter() {
   if (m_is_hce_listener_set) {
     nfc_manager_unset_hce_event_cb();
   }
+  if (m_is_preferred_app_set) {
+    nfc_se_unset_preferred_handler();
+  }
 
   // NFC library deinitialization
   int ret = nfc_manager_deinitialize();
@@ -1486,5 +1490,40 @@ void NFCAdapter::GetAIDsForCategory(const std::string& type,
   success_cb(aids);
 }
 
+PlatformResult NFCAdapter::SetPreferredApp() {
+  LoggerD("Entered");
+
+  if (m_is_preferred_app_set) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int ret = nfc_se_set_preferred_handler();
+  if (ret != NFC_ERROR_NONE) {
+    LoggerE("SetPreferredApp failed: %d", ret);
+    return NFCUtil::CodeToResult(ret, NFCUtil::getNFCErrorMessage(ret).c_str(), true);
+  }
+  m_is_preferred_app_set = true;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::UnsetPreferredApp() {
+  LoggerD("Entered");
+
+  if (!m_is_preferred_app_set) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int ret = nfc_se_unset_preferred_handler();
+  if (ret != NFC_ERROR_NONE) {
+    LoggerE("SetPreferredApp failed: %d", ret);
+    return NFCUtil::CodeToResult(ret, NFCUtil::getNFCErrorMessage(ret).c_str(), true);
+  }
+
+  m_is_preferred_app_set = false;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // nfc
 }  // extension
index 791453e..8e7c1b0 100644 (file)
@@ -117,6 +117,8 @@ class NFCAdapter {
   void GetAIDsForCategory(const std::string& type, nfc_card_emulation_category_type_e category,
                           const std::function<void(const AIDDataVector&)>& success_cb,
                           const std::function<void(const common::PlatformResult&)>& error_cb);
+  common::PlatformResult SetPreferredApp();
+  common::PlatformResult UnsetPreferredApp();
 
  private:
   NFCAdapter();
@@ -135,6 +137,7 @@ class NFCAdapter {
   bool m_is_ndef_listener_set;
   nfc_se_h m_se_handle;
   bool m_is_hce_listener_set;
+  bool m_is_preferred_app_set;
 
   IResponder* responder_;
 };
index 8aa8b58..5448c6d 100644 (file)
@@ -142,7 +142,7 @@ var activeSecureElementChangeListener = new ListenerManager(native_, ACTIVE_SECU
 var transactionEventListenerEse = new ListenerManager(native_, TRANSACTION_EVENT_ESE_LISTENER);
 var transactionEventListenerUicc = new ListenerManager(native_, TRANSACTION_EVENT_UICC_LISTENER);
 var HCEEventListener = new ListenerManager(native_, HCE_EVENT_LISTENER);
-
+var isWebkitVisibilityChangeListenerSet = false;
 
 //////////////////NFCManager /////////////////
 
@@ -907,6 +907,45 @@ NFCAdapter.prototype.getAIDsForCategory = function(type, category, successCallba
   }
 };
 
+function WebkitVisibilityChangeListener() {
+  var result;
+  if (true === privUtils_.global.document.hidden) {
+    result = native_.call('NFCAdapter_unsetPreferredApp');
+  } else if (false === privUtils_.global.document.hidden) {
+    result = native_.call('NFCAdapter_setPreferredApp');
+  }
+
+  if (native_.isFailure(result)) {
+    privUtils_.log('Failed to (un)set: ' + result.error.message);
+  }
+}
+
+NFCAdapter.prototype.setPreferredApp = function() {
+  var result = native_.call('NFCAdapter_setPreferredApp');
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  } else {
+    if (false === isWebkitVisibilityChangeListenerSet) {
+      privUtils_.global.document.addEventListener("webkitvisibilitychange", WebkitVisibilityChangeListener);
+      isWebkitVisibilityChangeListenerSet = true;
+    }
+  }
+};
+
+NFCAdapter.prototype.unsetPreferredApp = function() {
+  var result = native_.call('NFCAdapter_unsetPreferredApp');
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  } else {
+    if (true === isWebkitVisibilityChangeListenerSet) {
+      privUtils_.global.document.removeEventListener("webkitvisibilitychange", WebkitVisibilityChangeListener);
+      isWebkitVisibilityChangeListenerSet = false;
+    }
+  }
+};
+
 function InternalRecordData(tnf, type, payload, id) {
   this.tnf = tnf;
   this.type = type;
index 337bcd6..5218c2c 100644 (file)
@@ -112,6 +112,8 @@ NFCInstance::NFCInstance() {
   REGISTER_SYNC("NFCAdapter_registerAID", RegisterAID);
   REGISTER_SYNC("NFCAdapter_unregisterAID", UnregisterAID);
   REGISTER_ASYNC("NFCAdapter_getAIDsForCategory", GetAIDsForCategory);
+  REGISTER_SYNC("NFCAdapter_setPreferredApp", SetPreferredApp);
+  REGISTER_SYNC("NFCAdapter_unsetPreferredApp", UnsetPreferredApp);
 
   REGISTER_SYNC("NFCPeer_setReceiveNDEFListener", SetReceiveNDEFListener);
   REGISTER_SYNC("NFCPeer_unsetReceiveNDEFListener", UnsetReceiveNDEFListener);
@@ -991,5 +993,29 @@ void NFCInstance::GetAIDsForCategory(const picojson::value& args, picojson::obje
                                                    required_category, success_cb, error_cb));
 }
 
+void NFCInstance::SetPreferredApp(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeNfcCardEmulation, &out);
+
+  PlatformResult result = NFCAdapter::GetInstance()->SetPreferredApp();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LogAndReportError(result, &out);
+  }
+}
+
+void NFCInstance::UnsetPreferredApp(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeNfcCardEmulation, &out);
+
+  PlatformResult result = NFCAdapter::GetInstance()->UnsetPreferredApp();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LogAndReportError(result, &out);
+  }
+}
+
 }  // namespace nfc
 }  // namespace extension
index b23c517..73fd71e 100644 (file)
@@ -84,6 +84,8 @@ class NFCInstance : public common::ParsedInstance, NFCAdapter::IResponder {
   void RegisterAID(const picojson::value& args, picojson::object& out);
   void UnregisterAID(const picojson::value& args, picojson::object& out);
   void GetAIDsForCategory(const picojson::value& args, picojson::object& out);
+  void SetPreferredApp(const picojson::value& args, picojson::object& out);
+  void UnsetPreferredApp(const picojson::value& args, picojson::object& out);
 };
 
 }  // namespace nfc
index 33f0990..3d3327c 100644 (file)
@@ -32,7 +32,8 @@ UCharVector NFCUtil::ToVector(const unsigned char* ch, const int size) {
   return vec;
 }
 
-PlatformResult NFCUtil::CodeToResult(const int errorCode, const std::string& message) {
+PlatformResult NFCUtil::CodeToResult(const int errorCode, const std::string& message,
+                                     const bool newAPIVersion) {
   LoggerD("Entered");
   switch (errorCode) {
     case NFC_ERROR_INVALID_PARAMETER:
@@ -54,7 +55,11 @@ PlatformResult NFCUtil::CodeToResult(const int errorCode, const std::string& mes
     case NFC_ERROR_OUT_OF_MEMORY:
     case NFC_ERROR_NOT_INITIALIZED:
     default:
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, message);
+      if (newAPIVersion) {
+        return LogAndCreateResult(ErrorCode::ABORT_ERR, message);
+      } else {
+        return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, message);
+      }
   }
 }
 
index 1e806c2..a08b2ad 100644 (file)
@@ -60,7 +60,8 @@ typedef std::vector<unsigned char> UCharVector;
 class NFCUtil {
  public:
   static UCharVector ToVector(const unsigned char* ch, const int size);
-  static common::PlatformResult CodeToResult(const int errorCode, const std::string& message);
+  static common::PlatformResult CodeToResult(const int errorCode, const std::string& message,
+                                             const bool newAPIVersion = false);
   static std::string getNFCErrorString(const int error_code);
   static const std::string getNFCErrorMessage(const int error_code);
   static std::string ToStringNFCTag(const nfc_tag_type_e tag_type);
diff --git a/src/notification/common_notification.cc b/src/notification/common_notification.cc
new file mode 100644 (file)
index 0000000..eafe781
--- /dev/null
@@ -0,0 +1,1369 @@
+/*
+ * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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 "notification/common_notification.h"
+
+#include <app_control_internal.h>
+#include <notification_internal.h>
+
+#include "common/converter.h"
+#include "common/filesystem/filesystem_provider.h"
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+namespace extension {
+namespace notification {
+
+using namespace common;
+
+const InformationEnumMap CommonNotification::info_map_ = {{0, NOTIFICATION_TEXT_TYPE_INFO_1},
+                                                          {1, NOTIFICATION_TEXT_TYPE_INFO_2},
+                                                          {2, NOTIFICATION_TEXT_TYPE_INFO_3}};
+
+const InformationEnumMap CommonNotification::info_sub_map_ = {
+    {0, NOTIFICATION_TEXT_TYPE_INFO_SUB_1},
+    {1, NOTIFICATION_TEXT_TYPE_INFO_SUB_2},
+    {2, NOTIFICATION_TEXT_TYPE_INFO_SUB_3}};
+
+const ImageEnumMap CommonNotification::thumbnails_map_ = {{0, NOTIFICATION_IMAGE_TYPE_LIST_1},
+                                                          {1, NOTIFICATION_IMAGE_TYPE_LIST_2},
+                                                          {2, NOTIFICATION_IMAGE_TYPE_LIST_3},
+                                                          {3, NOTIFICATION_IMAGE_TYPE_LIST_4}};
+
+const InformationEnumMap CommonNotification::buttons_texts_map_ = {
+    {0, NOTIFICATION_TEXT_TYPE_BUTTON_1}, {1, NOTIFICATION_TEXT_TYPE_BUTTON_2},
+    {2, NOTIFICATION_TEXT_TYPE_BUTTON_3}, {3, NOTIFICATION_TEXT_TYPE_BUTTON_4},
+    {4, NOTIFICATION_TEXT_TYPE_BUTTON_5}, {5, NOTIFICATION_TEXT_TYPE_BUTTON_6}};
+
+const ImageEnumMap CommonNotification::buttons_icon_paths_map_ = {
+    {0, NOTIFICATION_IMAGE_TYPE_BUTTON_1}, {1, NOTIFICATION_IMAGE_TYPE_BUTTON_2},
+    {2, NOTIFICATION_IMAGE_TYPE_BUTTON_3}, {3, NOTIFICATION_IMAGE_TYPE_BUTTON_4},
+    {4, NOTIFICATION_IMAGE_TYPE_BUTTON_5}, {5, NOTIFICATION_IMAGE_TYPE_BUTTON_6}};
+
+CommonNotification::CommonNotification() {
+}
+
+CommonNotification::~CommonNotification() {
+}
+
+bool CommonNotification::IsColorFormatNumeric(const std::string& color) {
+  LoggerD("Enter");
+  std::string hexCode = "0123456789abcdef";
+  if (7 != color.length() || '#' != color[0]) {
+    return false;
+  }
+
+  for (size_t i = 1; i < color.length(); i++) {
+    if (hexCode.find(color[i]) == std::string::npos) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+PlatformResult CommonNotification::SetLayout(notification_h noti_handle,
+                                             const std::string& noti_type) {
+  LoggerD("Enter");
+  notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+
+  if ("SIMPLE" == noti_type) {
+    long number;
+    PlatformResult status = GetNumber(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &number);
+    if (status.IsError()) {
+      LoggerE("Failed: GetNumber");
+      return status;
+    }
+    if (number > 0)
+      noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
+    else
+      noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
+  } else if ("THUMBNAIL" == noti_type) {
+    noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
+  }
+  if ("ONGOING" == noti_type) {
+    noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
+  } else if ("PROGRESS" == noti_type) {
+    noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
+  }
+  int ret = notification_set_layout(noti_handle, noti_layout);
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification layout error",
+                              ("Set notification layout error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static bool ServiceExtraDataCb(app_control_h service, const char* key, void* user_data) {
+  LoggerD("Enter");
+  if (nullptr == user_data || nullptr == key) {
+    LoggerE("User data or key not exist");
+    return true;
+  }
+
+  picojson::array* control_data = static_cast<picojson::array*>(user_data);
+
+  int length = 0;
+  char** value = nullptr;
+  SCOPE_EXIT {
+    free(value);
+  };
+
+  int ret = app_control_get_extra_data_array(service, key, &value, &length);
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Get app control extra data error: %d", ret);
+    return true;
+  }
+
+  if (!value || !length) {
+    LoggerE("Get app control extra data value error");
+    return true;
+  }
+
+  picojson::array values = picojson::array();
+  for (int index = 0; index < length; ++index) {
+    values.push_back(picojson::value(value[index]));
+  }
+
+  picojson::object data_control_elem = picojson::object();
+  data_control_elem["key"] = picojson::value(key);
+  data_control_elem["value"] = picojson::value(values);
+
+  control_data->push_back(picojson::value(data_control_elem));
+
+  return true;
+}
+
+PlatformResult CommonNotification::Create(notification_type_e noti_type,
+                                          notification_h* noti_handle) {
+  LoggerD("Enter");
+  *noti_handle = notification_create(noti_type);
+  if (!*noti_handle) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot make new notification object");
+  }
+
+  if (NOTIFICATION_TYPE_ONGOING == noti_type) {
+    int ret =
+        notification_set_display_applist(*noti_handle, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+                                                           NOTIFICATION_DISPLAY_APP_INDICATOR);
+    if (NOTIFICATION_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot set notification display applist",
+                                ("Cannot make new notification object: %d", ret));
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::StatusTypeFromPlatform(notification_type_e noti_type,
+                                                          notification_ly_type_e noti_layout,
+                                                          std::string* type) {
+  LoggerD("Enter");
+  if (NOTIFICATION_TYPE_NOTI == noti_type) {
+    if (NOTIFICATION_LY_NOTI_EVENT_SINGLE == noti_layout ||
+        NOTIFICATION_LY_NOTI_EVENT_MULTIPLE == noti_layout) {
+      *type = "SIMPLE";
+    } else if (NOTIFICATION_LY_NOTI_THUMBNAIL == noti_layout) {
+      *type = "THUMBNAIL";
+    }
+  } else if (NOTIFICATION_TYPE_ONGOING == noti_type) {
+    if (NOTIFICATION_LY_ONGOING_EVENT == noti_layout) {
+      *type = "ONGOING";
+    } else if (NOTIFICATION_LY_ONGOING_PROGRESS == noti_layout) {
+      *type = "PROGRESS";
+    }
+  } else {
+    return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Notification type not found");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::StatusTypeToPlatform(const std::string& type,
+                                                        notification_type_e* noti_type) {
+  LoggerD("Enter");
+  if ("SIMPLE" == type || "THUMBNAIL" == type) {
+    *noti_type = NOTIFICATION_TYPE_NOTI;
+  } else if ("ONGOING" == type || "PROGRESS" == type) {
+    *noti_type = NOTIFICATION_TYPE_ONGOING;
+  } else {
+    return LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR, "Invalide notification type",
+                              ("Invalide noti type: %s", type.c_str()));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetImage(notification_h noti_handle,
+                                            notification_image_type_e image_type,
+                                            std::string* image_path) {
+  LoggerD("Enter");
+  char* path = nullptr;
+
+  *image_path = "";
+
+  if (NOTIFICATION_ERROR_NONE != notification_get_image(noti_handle, image_type, &path)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification image error",
+                              ("Get notification image error, image_type: %d", image_type));
+  }
+  if (path) {
+    *image_path = path;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetImage(notification_h noti_handle,
+                                            notification_image_type_e image_type,
+                                            const std::string& image_path) {
+  LoggerD("Enter");
+  int ret = notification_set_image(noti_handle, image_type, image_path.c_str());
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Set notification image error",
+        ("Set notification image error, image_type: %d, error: %d", image_type, ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetText(notification_h noti_handle,
+                                           notification_text_type_e text_type,
+                                           std::string* noti_text) {
+  LoggerD("Enter");
+  char* text = nullptr;
+
+  *noti_text = "";
+
+  if (NOTIFICATION_ERROR_NONE != notification_get_text(noti_handle, text_type, &text)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification text error",
+                              ("Get notification text error, text_type: %d", text_type));
+  }
+
+  if (text) *noti_text = text;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetText(notification_h noti_handle,
+                                           notification_text_type_e text_type,
+                                           const std::string& noti_text) {
+  LoggerD("Enter");
+  int ret = notification_set_text(noti_handle, text_type, noti_text.c_str(), nullptr,
+                                  NOTIFICATION_VARIABLE_TYPE_NONE);
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Set notification text error",
+        ("Set notification text error, text_type: %d, error: %d", text_type, ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetNumber(notification_h noti_handle,
+                                             notification_text_type_e text_type, long* number) {
+  LoggerD("Enter");
+  std::string text;
+  PlatformResult status = GetText(noti_handle, text_type, &text);
+  CHECK_ERROR(status);
+
+  if (text.length())
+    *number = std::stol(text);
+  else
+    *number = -1;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetLedColor(notification_h noti_handle, std::string* led_color) {
+  LoggerD("Enter");
+  unsigned int color = 0;
+  notification_led_op_e type = NOTIFICATION_LED_OP_ON;
+
+  if (NOTIFICATION_ERROR_NONE != notification_get_led(noti_handle, &type, (int*)&color)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
+                              "Get notification led displaying option error");
+  }
+
+  *led_color = "";
+  std::stringstream stream;
+
+  if (NOTIFICATION_LED_OP_OFF != type) {
+    color = 0x00FFFFFF & color;
+    stream << std::hex << color;
+    *led_color = "#" + stream.str();
+
+    while (led_color->length() < 7) {
+      led_color->insert(1, "0");
+    }
+
+    std::transform(led_color->begin(), led_color->end(), led_color->begin(), ::tolower);
+  }
+
+  LoggerD("color:%s", (*led_color).c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetLedPeriod(notification_h noti_handle,
+                                                unsigned long* on_period,
+                                                unsigned long* off_period) {
+  LoggerD("Enter");
+  int on_time = 0;
+  int off_time = 0;
+
+  if (NOTIFICATION_ERROR_NONE !=
+      notification_get_led_time_period(noti_handle, &on_time, &off_time)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification led on/off period error");
+  }
+
+  if (on_period) *on_period = on_time;
+  if (off_period) *off_period = off_time;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetSoundPath(notification_h noti_handle,
+                                                std::string* sound_path) {
+  LoggerD("Enter");
+  *sound_path = "";
+
+  const char* path = nullptr;
+  notification_sound_type_e type = NOTIFICATION_SOUND_TYPE_NONE;
+
+  if (NOTIFICATION_ERROR_NONE != notification_get_sound(noti_handle, &type, &path)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification sound error");
+  }
+
+  LoggerD("Sound type = %d", type);
+
+  if (path && (NOTIFICATION_SOUND_TYPE_USER_DATA == type)) {
+    *sound_path = path;
+  }
+
+  LoggerD("Sound path = %s", sound_path->c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetSoundPath(notification_h noti_handle,
+                                                const std::string& sound_path) {
+  LoggerD("Enter");
+  int ret =
+      notification_set_sound(noti_handle, NOTIFICATION_SOUND_TYPE_USER_DATA, sound_path.c_str());
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification sound error",
+                              ("Set notification sound error: %d", ret));
+  }
+
+  LoggerD("Sound path = %s", sound_path.c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetVibration(notification_h noti_handle, bool* vibration) {
+  LoggerD("Enter");
+  notification_vibration_type_e vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+
+  if (NOTIFICATION_ERROR_NONE != notification_get_vibration(noti_handle, &vib_type, nullptr)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification vibration error");
+  }
+
+  if (NOTIFICATION_VIBRATION_TYPE_DEFAULT == vib_type ||
+      NOTIFICATION_VIBRATION_TYPE_USER_DATA == vib_type) {
+    *vibration = true;
+  } else {
+    *vibration = false;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetApplicationControl(app_control_h app_handle,
+                                                         picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  char* operation = nullptr;
+  char* uri = nullptr;
+  char* mime = nullptr;
+  char* category = nullptr;
+  SCOPE_EXIT {
+    free(operation);
+    free(uri);
+    free(mime);
+    free(category);
+  };
+
+  int ret = app_control_get_operation(app_handle, &operation);
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control operation error",
+                              ("Get application control operation error: %d", ret));
+  }
+  if (operation) {
+    out["operation"] = picojson::value(operation);
+    LoggerD("operation = %s", operation);
+  }
+
+  if (APP_CONTROL_ERROR_NONE != app_control_get_uri(app_handle, &uri)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control uri error");
+  }
+  if (uri) {
+    out["uri"] = picojson::value(uri);
+    LoggerD("uri = %s", uri);
+  }
+
+  if (APP_CONTROL_ERROR_NONE != app_control_get_mime(app_handle, &mime)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control mime error");
+  }
+  if (mime) {
+    out["mime"] = picojson::value(mime);
+    LoggerD("mime = %s", mime);
+  }
+
+  if (APP_CONTROL_ERROR_NONE != app_control_get_category(app_handle, &category)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control category error");
+  }
+  if (category) {
+    out["category"] = picojson::value(category);
+    LoggerD("category = %s", category);
+  }
+
+  picojson::array app_control_data = picojson::array();
+  if (APP_CONTROL_ERROR_NONE !=
+      app_control_foreach_extra_data(app_handle, ServiceExtraDataCb, (void*)&app_control_data)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control data error");
+  }
+  out["data"] = picojson::value(app_control_data);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetApplicationControl(app_control_h app_handle,
+                                                         const picojson::object& app_ctrl) {
+  LoggerD("Enter");
+  picojson::value val(app_ctrl);
+  const std::string& operation = FromJson<std::string>(app_ctrl, "operation");
+
+  int ret;
+  if (operation.length()) {
+    ret = app_control_set_operation(app_handle, operation.c_str());
+  } else {
+    ret = app_control_set_operation(app_handle, APP_CONTROL_OPERATION_DEFAULT);
+  }
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control operation error",
+                              ("Set application control operation error: %d", ret));
+  }
+
+  if (val.contains("uri") && !IsNull(app_ctrl, "uri")) {
+    const std::string& uri = FromJson<std::string>(app_ctrl, "uri");
+    ret = app_control_set_uri(app_handle, uri.c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control uri error",
+                                ("Set application control uri error: %d", ret));
+    }
+  }
+
+  if (val.contains("mime") && !IsNull(app_ctrl, "mime")) {
+    const std::string& mime = FromJson<std::string>(app_ctrl, "mime");
+    ret = app_control_set_mime(app_handle, mime.c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control mime error",
+                                ("Set application control mime error: %d", ret));
+    }
+  }
+
+  if (val.contains("category") && !IsNull(app_ctrl, "category")) {
+    const std::string& category = FromJson<std::string>(app_ctrl, "category");
+    ret = app_control_set_category(app_handle, category.c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control category error",
+                                ("Set application control category error: %d", ret));
+    }
+  }
+
+  if (!picojson::value(app_ctrl).contains("data") || IsNull(app_ctrl, "data")) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  auto& items = FromJson<picojson::array>(app_ctrl, "data");
+
+  int idx = 0;
+
+  for (auto item : items) {
+    const picojson::object& obj = JsonCast<picojson::object>(item);
+    const std::string key = FromJson<std::string>(obj, "key");
+    const picojson::array values = FromJson<picojson::array>(obj, "value");
+    const char** arrayValue = (const char**)calloc(sizeof(char*), values.size());
+    SCOPE_EXIT {
+      free(arrayValue);
+    };
+    idx = 0;
+    for (auto& item : values) {
+      arrayValue[idx] = JsonCast<std::string>(item).c_str();
+      ++idx;
+    }
+    ret = app_control_add_extra_data_array(app_handle, key.c_str(), arrayValue, values.size());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control extra data error",
+                                ("Set application control extra data error: %d", ret));
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetApplicationId(app_control_h app_handle, std::string* app_id) {
+  LoggerD("Enter");
+  char* app_id_str = nullptr;
+  SCOPE_EXIT {
+    free(app_id_str);
+  };
+
+  *app_id = "";
+
+  if (APP_CONTROL_ERROR_NONE != app_control_get_app_id(app_handle, &app_id_str)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get applicaiton ID failed");
+  }
+
+  if (nullptr != app_id_str) {
+    *app_id = app_id_str;
+  }
+
+  LoggerD("Get appId = %s", /*(*app_id).c_str()*/ app_id_str);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetApplicationId(app_control_h app_handle,
+                                                    const std::string& app_id) {
+  LoggerD("Enter");
+  int ret = app_control_set_app_id(app_handle, app_id.c_str());
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set applicaiton ID error",
+                              ("Set applicaiton ID error: %d", ret));
+  }
+
+  LoggerD("Set appId = %s", app_id.c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetProgressValue(notification_h noti_handle,
+                                                    const std::string& progress_type,
+                                                    double* progress_value) {
+  LoggerD("Enter");
+  double tmp_progress_value = 0.0;
+
+  if (kProgressTypeByte == progress_type) {
+    if (NOTIFICATION_ERROR_NONE != notification_get_size(noti_handle, &tmp_progress_value)) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification size error");
+    }
+  } else if (kProgressTypePercentage == progress_type) {
+    if (NOTIFICATION_ERROR_NONE != notification_get_progress(noti_handle, &tmp_progress_value)) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification progress error");
+    }
+    // native api uses range 0-1, but webapi expects 0-100, so we need to multiply result with 100
+    tmp_progress_value *= 100;
+  } else {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown notification progress type",
+                              ("Unknown notification progress type: %s ", progress_type.c_str()));
+  }
+
+  LoggerD("Progress %s = %lf", progress_type.c_str(), tmp_progress_value);
+
+  *progress_value = tmp_progress_value;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetProgressValue(notification_h noti_handle,
+                                                    const std::string& progress_type,
+                                                    double progress_value, bool is_update) {
+  LoggerD("Enter");
+  int ret;
+
+  if (kProgressTypeByte == progress_type) {
+    ret = notification_set_size(noti_handle, progress_value);
+
+    if (is_update) {
+      ret = notification_update_size(noti_handle, NOTIFICATION_PRIV_ID_NONE, progress_value);
+    }
+  } else if (kProgressTypePercentage == progress_type) {
+    // native api uses range 0-1, but webapi expects 0-100, so we need to divide by 100
+    ret = notification_set_progress(noti_handle, progress_value / 100);
+
+    if (is_update) {
+      ret = notification_update_progress(noti_handle, NOTIFICATION_PRIV_ID_NONE, progress_value);
+    }
+  } else {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown notification progress type",
+                              ("Unknown notification progress type: %s ", progress_type.c_str()));
+  }
+
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification progress/size error",
+                              ("Set notification progress/size error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetPostedTime(notification_h noti_handle, time_t* posted_time) {
+  LoggerD("Enter");
+  *posted_time = 0;
+
+  if (NOTIFICATION_ERROR_NONE != notification_get_insert_time(noti_handle, posted_time)) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification posted time error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetNotiHandle(int id, notification_h* noti_handle) {
+  LoggerD("Enter");
+  *noti_handle = notification_load(nullptr, id);
+  if (nullptr == *noti_handle) {
+    return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Not found or removed notification id");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::GetAppControl(notification_h noti_handle,
+                                                 app_control_h* app_control) {
+  LoggerD("Enter");
+  int ret = notification_get_launch_option(noti_handle, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL,
+                                           static_cast<void*>(app_control));
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification get launch option error",
+                              ("Notification get launch option error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::CreateAppControl(app_control_h* app_control) {
+  LoggerD("Enter");
+  int ret = app_control_create(app_control);
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Application create error",
+                              ("Application create error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetAppControl(notification_h noti_handle,
+                                                 app_control_h app_control) {
+  LoggerD("Enter");
+  int ret = notification_set_launch_option(noti_handle, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL,
+                                           static_cast<void*>(app_control));
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification set launch option error",
+                              ("Notification set launch option error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::UpdateNotificationAfterPost(notification_h noti_handle, int id,
+                                                               picojson::object* out_ptr) {
+  time_t posted_time;
+  PlatformResult status = GetPostedTime(noti_handle, &posted_time);
+  CHECK_ERROR(status);
+
+  picojson::object& out = *out_ptr;
+  out["postedTime"] = picojson::value(static_cast<double>(posted_time) * 1000.0);
+  out["id"] = picojson::value(std::to_string(id));
+  out["type"] = picojson::value("STATUS");
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::PostNotification(const picojson::object& args, bool is_update,
+                                                    picojson::object* out_ptr,
+                                                    GetHandleFromJsonFun getHandle) {
+  LoggerD("Enter");
+  notification_h noti_handle = nullptr;
+  int ret = NOTIFICATION_ERROR_NONE;
+  int id = NOTIFICATION_PRIV_ID_NONE;
+
+  SCOPE_EXIT {
+    notification_free(noti_handle);
+  };
+
+  const auto& noti_val_it = args.find("notification");
+  if (args.end() == noti_val_it) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot post notification");
+  }
+  PlatformResult status = getHandle(noti_val_it->second, is_update, &noti_handle);
+  CHECK_ERROR(status);
+
+  if (is_update) {
+    ret = notification_update(noti_handle);
+    if (NOTIFICATION_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Update notification error",
+                                ("Update notification error: %d", ret));
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+  } else {
+    ret = notification_insert(noti_handle, &id);
+    if (NOTIFICATION_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot insert notification",
+                                ("Cannot insert notification: %d", ret));
+    }
+  }
+
+  return UpdateNotificationAfterPost(noti_handle, id, out_ptr);
+}
+
+PlatformResult CommonNotification::AddCommonMembersToJson(int id, notification_h noti_handle,
+                                                          picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  out["id"] = picojson::value(std::to_string(id));
+  out["type"] = picojson::value("STATUS");
+
+  time_t posted_time = 0;
+  PlatformResult ret = GetPostedTime(noti_handle, &posted_time);
+  CHECK_ERROR(ret);
+  out["postedTime"] = picojson::value(static_cast<double>(posted_time) * 1000.0);
+
+  std::string value_str;
+  ret = GetText(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, &value_str);
+  CHECK_ERROR(ret);
+  out["title"] = picojson::value(value_str);
+
+  ret = GetText(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, &value_str);
+  CHECK_ERROR(ret);
+  if (value_str.length()) {
+    out["content"] = picojson::value(value_str);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddTypeToJson(notification_h noti_handle, const std::string& key,
+                                                 picojson::object* out_ptr,
+                                                 std::string* noti_type_str) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+  // Notification type
+  notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
+  int ret = notification_get_type(noti_handle, &noti_type);
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Notification get type error",
+                              ("Notification get type error: %d", ret));
+  }
+
+  notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+  ret = notification_get_layout(noti_handle, &noti_layout);
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Notification get layout error",
+                              ("Notification get layout error: %d", ret));
+  }
+
+  PlatformResult status = StatusTypeFromPlatform(noti_type, noti_layout, noti_type_str);
+  CHECK_ERROR(status);
+  out[key] = picojson::value(*noti_type_str);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddProgressTypeAndValueToJson(notification_h noti_handle,
+                                                                 const std::string& noti_type_str,
+                                                                 picojson::object* out_ptr) {
+  LoggerD("Enter");
+
+  picojson::object& out = *out_ptr;
+  std::string progress_type;
+  // native code does not support progress_type value, we are using NOTIFICATION_IMAGE_TYPE_LIST_5
+  // to store this field on native level
+  PlatformResult status = GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_LIST_5, &progress_type);
+  CHECK_ERROR(status)
+
+  // notification service daemon doesn't set progress type - NOTIFICATION_IMAGE_TYPE_LIST_5 is used
+  // as workaround, so use default if notification type is different from "PROGRESS"
+  if ("PROGRESS" != noti_type_str) {
+    progress_type = progress_type == kProgressTypeByte ? progress_type : kProgressTypePercentage;
+  }
+  out["progressType"] = picojson::value(progress_type);
+
+  double progress_value;
+  status = GetProgressValue(noti_handle, progress_type, &progress_value);
+  CHECK_ERROR(status);
+  out["progressValue"] = picojson::value(progress_value);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddEventsNumberToJson(notification_h noti_handle,
+                                                         const std::string& key,
+                                                         picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  long number = 0;
+  PlatformResult status = GetNumber(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &number);
+  CHECK_ERROR(status);
+  if (number >= 0) {
+    out[key] = picojson::value(static_cast<double>(number));
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddDetailInfosToJson(notification_h noti_handle,
+                                                        picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  picojson::value result_json = picojson::value(picojson::array());
+  picojson::array& detail_info_array = result_json.get<picojson::array>();
+
+  if (info_map_.size() != info_sub_map_.size()) {
+    return LogAndCreateResult(ErrorCode::VALIDATION_ERR,
+                              "Different notification information types element size");
+  }
+
+  picojson::value detail_info = picojson::value(picojson::object());
+  picojson::object& detail_info_obj = detail_info.get<picojson::object>();
+
+  std::string text;
+  size_t info_map_size = info_map_.size();
+  for (size_t idx = 0; idx < info_map_size; ++idx) {
+    PlatformResult status = GetText(noti_handle, info_map_.at(idx), &text);
+    CHECK_ERROR(status);
+
+    if (text.length()) {
+      detail_info_obj["mainText"] = picojson::value(text);
+
+      status = AddTextToJson(noti_handle, info_sub_map_.at(idx), "subText", &detail_info_obj);
+      CHECK_ERROR(status);
+      detail_info_array.push_back(detail_info);
+    }
+  }
+  out["detailInfo"] = result_json;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddPathToJson(notification_h noti_handle,
+                                                 notification_image_type_e type,
+                                                 const std::string& key,
+                                                 picojson::object* out_ptr) {
+  picojson::object& out = *out_ptr;
+
+  std::string value_str;
+  PlatformResult status = GetImage(noti_handle, type, &value_str);
+  CHECK_ERROR(status);
+  if (value_str.length()) {
+    out[key] = picojson::value(FilesystemProvider::Create().GetVirtualPath(value_str));
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddTextToJson(notification_h noti_handle,
+                                                 notification_text_type_e type,
+                                                 const std::string& key,
+                                                 picojson::object* out_ptr) {
+  picojson::object& out = *out_ptr;
+
+  std::string value_str;
+  PlatformResult ret = GetText(noti_handle, type, &value_str);
+  CHECK_ERROR(ret);
+  if (value_str.length()) {
+    out[key] = picojson::value(value_str);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddLedOnOffPeriodToJson(notification_h noti_handle,
+                                                           picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  unsigned long on_period = 0;
+  unsigned long off_period = 0;
+  PlatformResult status = GetLedPeriod(noti_handle, &on_period, &off_period);
+  CHECK_ERROR(status);
+
+  out["ledOnPeriod"] = picojson::value(static_cast<double>(on_period));
+  out["ledOffPeriod"] = picojson::value(static_cast<double>(off_period));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddPathsArrayToJson(notification_h noti_handle, ImageEnumMap map,
+                                                       const std::string& key,
+                                                       picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  picojson::value result_json = picojson::value(picojson::array());
+  picojson::array& result_array = result_json.get<picojson::array>();
+
+  std::string path;
+  size_t map_size = map.size();
+  for (size_t idx = 0; idx < map_size; ++idx) {
+    PlatformResult status = GetImage(noti_handle, map.at(idx), &path);
+    CHECK_ERROR(status);
+
+    if (path.length()) {
+      result_array.push_back(picojson::value(FilesystemProvider::Create().GetVirtualPath(path)));
+    }
+  }
+
+  out[key] = result_json;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddTextsArrayToJson(notification_h noti_handle,
+                                                       InformationEnumMap map,
+                                                       const std::string& key,
+                                                       picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  picojson::value result_json = picojson::value(picojson::array());
+  picojson::array& result_array = result_json.get<picojson::array>();
+
+  std::string text;
+  size_t map_size = map.size();
+  for (size_t idx = 0; idx < map_size; ++idx) {
+    PlatformResult status = GetText(noti_handle, map.at(idx), &text);
+
+    CHECK_ERROR(status);
+    if (text.length()) {
+      result_array.push_back(picojson::value(text));
+    }
+  }
+
+  out[key] = result_json;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddLedColorToJson(notification_h noti_handle,
+                                                     picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  std::string color;
+  PlatformResult status = GetLedColor(noti_handle, &color);
+  CHECK_ERROR(status);
+  if (color.length()) {
+    out["ledColor"] = picojson::value(color);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddSoundPathToJson(notification_h noti_handle,
+                                                      picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  std::string sound_path;
+  PlatformResult status = GetSoundPath(noti_handle, &sound_path);
+  CHECK_ERROR(status);
+  if (sound_path.length()) {
+    out["soundPath"] = picojson::value(FilesystemProvider::Create().GetVirtualPath(sound_path));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddVibrationToJson(notification_h noti_handle,
+                                                      picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  bool vibration;
+  PlatformResult status = GetVibration(noti_handle, &vibration);
+  CHECK_ERROR(status);
+  out["vibration"] = picojson::value(vibration);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::AddAppControlInfoToJson(notification_h noti_handle,
+                                                           app_control_h app_handle,
+                                                           picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  if (app_handle) {
+    picojson::object app_control = picojson::object();
+    PlatformResult status = GetApplicationControl(app_handle, &app_control);
+    CHECK_ERROR(status);
+    if (app_control.size()) {
+      out["appControl"] = picojson::value(app_control);
+    }
+
+    std::string app_id;
+    status = GetApplicationId(app_handle, &app_id);
+    CHECK_ERROR(status);
+    if (app_id.length()) {
+      out["appId"] = picojson::value(app_id);
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::InitNotiFromJson(const picojson::object& noti_obj,
+                                                    const std::string& type_key, bool is_update,
+                                                    notification_h* noti_handle) {
+  LoggerD("Enter");
+  notification_h tmp_noti = nullptr;
+
+  const std::string& status_type = FromJson<std::string>(noti_obj, type_key.c_str());
+
+  notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
+  PlatformResult status = StatusTypeToPlatform(status_type, &noti_type);
+  CHECK_ERROR(status);
+
+  if (is_update) {
+    int id = std::stoi(FromJson<std::string>(noti_obj, "id"));
+
+    status = GetNotiHandle(id, &tmp_noti);
+    CHECK_ERROR(status);
+  } else {
+    status = Create(noti_type, &tmp_noti);
+    CHECK_ERROR(status);
+  }
+  std::unique_ptr<std::remove_pointer<notification_h>::type, int (*)(notification_h)> tmp_noti_ptr(
+      tmp_noti, &notification_free);  // automatically release the memory
+
+  status = SetLayout(tmp_noti, status_type);
+  CHECK_ERROR(status);
+
+  *noti_handle = tmp_noti_ptr.release();
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetCommonMembersFromJson(const picojson::value& noti_value,
+                                                            notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+  PlatformResult status =
+      SetText(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, FromJson<std::string>(noti_obj, "title"));
+  CHECK_ERROR(status);
+
+  SetTextFromJson(noti_value, NOTIFICATION_TEXT_TYPE_CONTENT, "content", noti_handle);
+  CHECK_ERROR(status);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetPathFromJson(const picojson::value& noti_value,
+                                                   notification_image_type_e type,
+                                                   const std::string& key,
+                                                   notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+  if (noti_value.contains(key) && !IsNull(noti_obj, key.c_str())) {
+    const std::string& value_str = FromJson<std::string>(noti_obj, key.c_str());
+    std::string real_path = FilesystemProvider::Create().GetRealPath(value_str);
+
+    PlatformResult status = SetImage(noti_handle, type, real_path);
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetLedColorFromJson(const picojson::value& noti_value,
+                                                       notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+  if (noti_value.contains("ledColor") && !IsNull(noti_obj, "ledColor")) {
+    std::string color_str = FromJson<std::string>(noti_obj, "ledColor");
+    std::transform(color_str.begin(), color_str.end(), color_str.begin(), ::tolower);
+
+    if (!IsColorFormatNumeric(color_str)) {
+      return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Led color is not numeric value",
+                                ("Led color is not numeric value: %s", color_str.c_str()));
+    }
+
+    std::stringstream stream;
+    unsigned int color = 0;
+    notification_led_op_e type = NOTIFICATION_LED_OP_ON;
+    std::string color_code = color_str.substr(1, color_str.length()).insert(0, "ff");
+
+    stream << std::hex << color_code;
+    stream >> color;
+
+    if (0 != color)
+      type = NOTIFICATION_LED_OP_ON_CUSTOM_COLOR;
+    else
+      type = NOTIFICATION_LED_OP_OFF;
+
+    int ret = notification_set_led(noti_handle, type, static_cast<int>(color));
+    if (NOTIFICATION_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification led color eror",
+                                ("Set notification led color eror: %d", ret));
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetLedOnPeriodFromJson(const picojson::value& noti_value,
+                                                          notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+  unsigned long on_period = static_cast<unsigned long>(FromJson<double>(noti_obj, "ledOnPeriod"));
+
+  unsigned long off_period = 0;
+  PlatformResult status = GetLedPeriod(noti_handle, nullptr, &off_period);
+  CHECK_ERROR(status);
+
+  int ret = notification_set_led_time_period(noti_handle, on_period, off_period);
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification led on period error",
+                              ("Set notification led on period error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetLedOffPeriodFromJson(const picojson::value& noti_value,
+                                                           notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+  unsigned long off_period = static_cast<unsigned long>(FromJson<double>(noti_obj, "ledOffPeriod"));
+  unsigned long on_period = 0;
+  PlatformResult status = GetLedPeriod(noti_handle, &on_period, nullptr);
+  CHECK_ERROR(status);
+
+  int ret = notification_set_led_time_period(noti_handle, on_period, off_period);
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification led off period error",
+                              ("Set notification led off period error: %d", ret));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetProgressTypeAndValueFromJson(
+    const picojson::value& noti_value, bool is_update, notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+
+  // progressType
+  // native code does not support progress_type value, we are using NOTIFICATION_IMAGE_TYPE_LIST_5
+  // to store this field on native level
+  const std::string& progress_type = FromJson<std::string>(noti_obj, "progressType");
+  PlatformResult status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_LIST_5, progress_type);
+  CHECK_ERROR(status);
+
+  // progressValue
+  double progress_value = -1;
+  if (noti_value.contains("progressValue") && !IsNull(noti_obj, "progressValue")) {
+    progress_value = FromJson<double>(noti_obj, "progressValue");
+  }
+  status = SetProgressValue(noti_handle, progress_type, progress_value, is_update);
+  CHECK_ERROR(status);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetAppControlInfoFromJson(const picojson::value& noti_value,
+                                                             notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+
+  app_control_h app_control = nullptr;
+  SCOPE_EXIT {
+    if (app_control) {
+      app_control_destroy(app_control);
+    }
+  };
+
+  PlatformResult status = CreateAppControl(&app_control);
+  CHECK_ERROR(status);
+
+  if (noti_value.contains("appControl") && !IsNull(noti_obj, "appControl")) {
+    status = SetApplicationControl(app_control, FromJson<picojson::object>(noti_obj, "appControl"));
+    CHECK_ERROR(status);
+  }
+
+  if (noti_value.contains("appId") && !IsNull(noti_obj, "appId")) {
+    status = SetApplicationId(app_control, FromJson<std::string>(noti_obj, "appId"));
+    CHECK_ERROR(status);
+  }
+
+  status = SetAppControl(noti_handle, app_control);
+  CHECK_ERROR(status);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetEventsNumberFromJson(const picojson::value& noti_value,
+                                                           const std::string& key,
+                                                           notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+
+  if (noti_value.contains(key) && !IsNull(noti_obj, key.c_str())) {
+    long number = (long)FromJson<double>(noti_obj, key.c_str());
+    PlatformResult status =
+        SetText(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, std::to_string(number));
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetDetailInfosFromJson(const picojson::value& noti_value,
+                                                          notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+  if (noti_value.contains("detailInfo") && !IsNull(noti_obj, "detailInfo")) {
+    const picojson::array& array = FromJson<picojson::array>(noti_obj, "detailInfo");
+
+    if (array.size() > info_map_.size()) {
+      return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
+                                "Too many values in notification detailInfo array");
+    }
+    size_t idx = 0;
+
+    for (auto& item : array) {
+      const picojson::object& obj = JsonCast<picojson::object>(item);
+
+      PlatformResult status =
+          SetText(noti_handle, info_map_.at(idx), FromJson<std::string>(obj, "mainText"));
+      CHECK_ERROR(status);
+
+      SetTextFromJson(picojson::value(obj), info_sub_map_.at(idx), "subText", noti_handle);
+      CHECK_ERROR(status);
+      ++idx;
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetVibrationFromJson(const picojson::value& noti_value,
+                                                        notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+  bool vibration = FromJson<bool>(noti_obj, "vibration");
+
+  bool platform_vibration;
+  PlatformResult status = GetVibration(noti_handle, &platform_vibration);
+  CHECK_ERROR(status);
+
+  if (platform_vibration != vibration) {
+    notification_vibration_type_e vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+
+    if (vibration) {
+      vib_type = NOTIFICATION_VIBRATION_TYPE_DEFAULT;
+    }
+
+    int ret = notification_set_vibration(noti_handle, vib_type, nullptr);
+    if (NOTIFICATION_ERROR_NONE != ret) {
+      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification vibration error",
+                                ("Set notification vibration error: %d", ret));
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetSoundPathFromJson(const picojson::value& noti_value,
+                                                        notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+
+  if (noti_value.contains("soundPath") && !IsNull(noti_obj, "soundPath")) {
+    const std::string& value_str = FromJson<std::string>(noti_obj, "soundPath");
+    std::string real_path = FilesystemProvider::Create().GetRealPath(value_str);
+
+    PlatformResult status = SetSoundPath(noti_handle, real_path);
+    CHECK_ERROR(status);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetPathsArrayFromJson(const picojson::value& noti_value,
+                                                         ImageEnumMap map, const std::string& key,
+                                                         notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+
+  if (noti_value.contains(key) && !IsNull(noti_obj, key.c_str())) {
+    const picojson::array& array = FromJson<picojson::array>(noti_obj, key.c_str());
+    if (array.size() > map.size()) {
+      return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Too many values in array");
+    }
+    size_t idx = 0;
+    for (auto& item : array) {
+      const std::string& text = JsonCast<std::string>(item);
+      std::string real_path = FilesystemProvider::Create().GetRealPath(text);
+
+      PlatformResult status = SetImage(noti_handle, map.at(idx), real_path);
+      CHECK_ERROR(status);
+
+      ++idx;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetTextsArrayFromJson(const picojson::value& noti_value,
+                                                         InformationEnumMap map,
+                                                         const std::string& key,
+                                                         notification_h noti_handle) {
+  LoggerD("Enter");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+
+  if (noti_value.contains(key) && !IsNull(noti_obj, key.c_str())) {
+    const picojson::array& array = FromJson<picojson::array>(noti_obj, key.c_str());
+    if (array.size() > map.size()) {
+      return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Too many values in array");
+    }
+
+    size_t idx = 0;
+    for (auto& item : array) {
+      const std::string& text = JsonCast<std::string>(item);
+      PlatformResult status = SetText(noti_handle, map.at(idx), text);
+      CHECK_ERROR(status);
+
+      ++idx;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CommonNotification::SetTextFromJson(const picojson::value& noti_value,
+                                                   notification_text_type_e type,
+                                                   const std::string& key,
+                                                   notification_h noti_handle) {
+  LoggerD("Entered");
+  const picojson::object& noti_obj = noti_value.get<picojson::object>();
+
+  if (noti_value.contains(key) && !IsNull(noti_obj, key.c_str())) {
+    PlatformResult status =
+        SetText(noti_handle, type, FromJson<std::string>(noti_obj, key.c_str()));
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace notification
+}  // namespace extension
diff --git a/src/notification/common_notification.h b/src/notification/common_notification.h
new file mode 100644 (file)
index 0000000..a5c813d
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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 NOTIFICATION_COMMON_NOTIFICATION_H_
+#define NOTIFICATION_COMMON_NOTIFICATION_H_
+
+#include <app_control.h>
+#include <notification.h>
+#include <functional>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "common/XW_Extension.h"
+
+namespace extension {
+namespace notification {
+
+#define CHECK_ERROR(ret) \
+  if (ret.IsError()) {   \
+    return ret;          \
+  }
+
+const std::string kProgressTypePercentage = "PERCENTAGE";
+const std::string kProgressTypeByte = "BYTE";
+
+typedef std::map<int, notification_text_type_e> InformationEnumMap;
+typedef std::map<int, notification_image_type_e> ImageEnumMap;
+
+XW_EXPORT typedef std::function<common::PlatformResult(const picojson::value& noti_val,
+                                                       bool is_update, notification_h* noti_handle)>
+    GetHandleFromJsonFun;
+
+class CommonNotification {
+ public:
+  XW_EXPORT static common::PlatformResult GetAppControl(notification_h noti_handle,
+                                                        app_control_h* app_control);
+  static common::PlatformResult GetNotiHandle(int id, notification_h* noti_handle);
+  XW_EXPORT static common::PlatformResult SetAppControl(notification_h noti_handle,
+                                                        app_control_h app_control);
+
+  static const InformationEnumMap info_map_;
+  static const InformationEnumMap info_sub_map_;
+  static const ImageEnumMap thumbnails_map_;
+  static const InformationEnumMap buttons_texts_map_;
+  static const ImageEnumMap buttons_icon_paths_map_;
+
+  static common::PlatformResult StatusTypeFromPlatform(notification_type_e noti_type,
+                                                       notification_ly_type_e noti_layout,
+                                                       std::string* type);
+  static common::PlatformResult StatusTypeToPlatform(const std::string& type,
+                                                     notification_type_e* noti_type);
+  static common::PlatformResult Create(notification_type_e noti_type, notification_h* noti_handle);
+  static common::PlatformResult GetImage(notification_h noti_handle,
+                                         notification_image_type_e image_type,
+                                         std::string* image_path);
+  static common::PlatformResult SetImage(notification_h noti_handle,
+                                         notification_image_type_e image_type,
+                                         const std::string& image_path);
+  static common::PlatformResult GetText(notification_h noti_handle,
+                                        notification_text_type_e text_type, std::string* noti_text);
+  static common::PlatformResult SetText(notification_h noti_handle,
+                                        notification_text_type_e text_type,
+                                        const std::string& noti_text);
+  static common::PlatformResult GetNumber(notification_h noti_handle,
+                                          notification_text_type_e text_type, long* number);
+  static common::PlatformResult GetLedColor(notification_h noti_handle, std::string* led_color);
+  static common::PlatformResult GetLedPeriod(notification_h noti_handle, unsigned long* on_period,
+                                             unsigned long* off_period);
+  static common::PlatformResult GetSoundPath(notification_h noti_handle, std::string* sound_path);
+  static common::PlatformResult SetSoundPath(notification_h noti_handle,
+                                             const std::string& sound_path);
+  static common::PlatformResult GetVibration(notification_h noti_handle, bool* vibration);
+  static common::PlatformResult GetApplicationControl(app_control_h app_handle,
+                                                      picojson::object* out_ptr);
+  static common::PlatformResult SetApplicationControl(app_control_h app_handle,
+                                                      const picojson::object& app_ctrl);
+  static common::PlatformResult GetApplicationId(app_control_h app_handle, std::string* app_id);
+  static common::PlatformResult SetApplicationId(app_control_h app_handle,
+                                                 const std::string& app_id);
+  static common::PlatformResult GetProgressValue(notification_h noti_handle,
+                                                 const std::string& progess_type,
+                                                 double* progress_value);
+  static common::PlatformResult SetProgressValue(notification_h noti_handle,
+                                                 const std::string& progress_type,
+                                                 double progress_value, bool is_update);
+  static common::PlatformResult GetPostedTime(notification_h noti_handle, time_t* posted_time);
+  static common::PlatformResult SetLayout(notification_h noti_handle, const std::string& noti_type);
+  static common::PlatformResult CreateAppControl(app_control_h* app_control);
+
+  static bool IsColorFormatNumeric(const std::string& color);
+  static common::PlatformResult UpdateNotificationAfterPost(notification_h noti_handle, int id,
+                                                            picojson::object* out_ptr);
+
+  // ToJson section
+  static common::PlatformResult AddCommonMembersToJson(int id, notification_h noti_handle,
+                                                       picojson::object* out_ptr);
+  static common::PlatformResult AddTypeToJson(notification_h noti_handle, const std::string& key,
+                                              picojson::object* out_ptr,
+                                              std::string* noti_type_str);
+  static common::PlatformResult AddProgressTypeAndValueToJson(notification_h noti_handle,
+                                                              const std::string& noti_type_str,
+                                                              picojson::object* out_ptr);
+  static common::PlatformResult AddEventsNumberToJson(notification_h noti_handle,
+                                                      const std::string& key,
+                                                      picojson::object* out_ptr);
+  static common::PlatformResult AddDetailInfosToJson(notification_h noti_handle,
+                                                     picojson::object* out_ptr);
+  static common::PlatformResult AddPathToJson(notification_h noti_handle,
+                                              notification_image_type_e type,
+                                              const std::string& key, picojson::object* out_ptr);
+  static common::PlatformResult AddTextToJson(notification_h noti_handle,
+                                              notification_text_type_e type, const std::string& key,
+                                              picojson::object* out_ptr);
+  static common::PlatformResult AddIconPathToJson(notification_h noti_handle,
+                                                  picojson::object* out_ptr);
+  static common::PlatformResult AddSubIconPathToJson(notification_h noti_handle,
+                                                     picojson::object* out_ptr);
+  static common::PlatformResult AddBackgroundImagePathToJson(notification_h noti_handle,
+                                                             picojson::object* out_ptr);
+  static common::PlatformResult AddLedOnOffPeriodToJson(notification_h noti_handle,
+                                                        picojson::object* out_ptr);
+  static common::PlatformResult AddLedColorToJson(notification_h noti_handle,
+                                                  picojson::object* out_ptr);
+  static common::PlatformResult AddSoundPathToJson(notification_h noti_handle,
+                                                   picojson::object* out_ptr);
+  static common::PlatformResult AddVibrationToJson(notification_h noti_handle,
+                                                   picojson::object* out_ptr);
+  static common::PlatformResult AddAppControlInfoToJson(notification_h noti_handle,
+                                                        app_control_h app_handle,
+                                                        picojson::object* out_ptr);
+  static common::PlatformResult AddPathsArrayToJson(notification_h noti_handle, ImageEnumMap map,
+                                                    const std::string& key,
+                                                    picojson::object* out_ptr);
+  static common::PlatformResult AddTextsArrayToJson(notification_h noti_handle,
+                                                    InformationEnumMap map, const std::string& key,
+                                                    picojson::object* out_ptr);
+
+  // FromJson section
+  static common::PlatformResult InitNotiFromJson(const picojson::object& args,
+                                                 const std::string& type_key, bool is_update,
+                                                 notification_h* noti_handle);
+  static common::PlatformResult SetCommonMembersFromJson(const picojson::value& noti_val,
+                                                         notification_h noti_handle);
+  static common::PlatformResult SetPathFromJson(const picojson::value& noti_value,
+                                                notification_image_type_e type,
+                                                const std::string& key, notification_h noti_handle);
+  static common::PlatformResult SetLedColorFromJson(const picojson::value& noti_value,
+                                                    notification_h noti_handle);
+  static common::PlatformResult SetLedOnPeriodFromJson(const picojson::value& noti_value,
+                                                       notification_h noti_handle);
+  static common::PlatformResult SetLedOffPeriodFromJson(const picojson::value& noti_value,
+                                                        notification_h noti_handle);
+  static common::PlatformResult SetProgressTypeAndValueFromJson(const picojson::value& noti_value,
+                                                                bool is_update,
+                                                                notification_h noti_handle);
+  static common::PlatformResult SetAppControlInfoFromJson(const picojson::value& noti_value,
+                                                          notification_h noti_handle);
+  static common::PlatformResult SetEventsNumberFromJson(const picojson::value& noti_value,
+                                                        const std::string& key,
+                                                        notification_h noti_handle);
+  static common::PlatformResult SetDetailInfosFromJson(const picojson::value& noti_value,
+                                                       notification_h noti_handle);
+  static common::PlatformResult SetVibrationFromJson(const picojson::value& noti_value,
+                                                     notification_h noti_handle);
+  static common::PlatformResult SetSoundPathFromJson(const picojson::value& noti_value,
+                                                     notification_h noti_handle);
+  static common::PlatformResult SetPathsArrayFromJson(const picojson::value& noti_value,
+                                                      ImageEnumMap map, const std::string& key,
+                                                      notification_h noti_handle);
+  static common::PlatformResult SetTextsArrayFromJson(const picojson::value& noti_value,
+                                                      InformationEnumMap map,
+                                                      const std::string& key,
+                                                      notification_h noti_handle);
+  static common::PlatformResult SetTextFromJson(const picojson::value& noti_value,
+                                                notification_text_type_e type,
+                                                const std::string& key, notification_h noti_handle);
+
+  static common::PlatformResult PostNotification(const picojson::object& args, bool is_update,
+                                                 picojson::object* out_ptr,
+                                                 GetHandleFromJsonFun getHandle);
+
+ protected:
+  CommonNotification();
+  virtual ~CommonNotification();
+};
+
+}  // namespace notification
+}  // namespace extension
+
+#endif /* NOTIFICATION_COMMON_NOTIFICATION_H_ */
index 9c219a8..32a8fd9 100755 (executable)
         'notification_manager.h',
         'notification_manager.cc',
         'status_notification.cc',
-        'status_notification.h'
+        'status_notification.h',
+        'user_notification.cc',
+        'user_notification.h',
+        'common_notification.cc',
+        'common_notification.h'
       ],
       'conditions': [
         ['tizen == 1', {
             'packages': [
               'notification',
               'capi-system-device',
+              'capi-appfw-app-control',
             ]
           },
         }],
       ],
+      'direct_dependent_settings': {
+        'libraries' : [
+          '-ltizen_notification',
+        ],
+      },
     },
   ],
 }
index 21bcadf..1b8bc52 100644 (file)
@@ -69,6 +69,13 @@ var StatusNotificationType = {
   PROGRESS: 'PROGRESS'
 };
 
+var UserNotificationType = {
+  SIMPLE: 'SIMPLE',
+  THUMBNAIL: 'THUMBNAIL',
+  ONGOING: 'ONGOING',
+  PROGRESS: 'PROGRESS'
+};
+
 var NotificationProgressType = {
   PERCENTAGE: 'PERCENTAGE',
   BYTE: 'BYTE'
@@ -84,10 +91,12 @@ function NotificationManager() {}
 
 NotificationManager.prototype.post = function(notification) {
   var args = validator_.validateArgs(arguments, [
-    {name: 'notification', type: types_.PLATFORM_OBJECT, values: StatusNotification}
+    {name: 'notification', type: types_.PLATFORM_OBJECT, values: Notification}
   ]);
 
   var data = {
+    //add marker for UserNotification implementation
+    newImpl: (args.notification instanceof tizen.UserNotification),
     notification: args.notification
   };
 
@@ -107,7 +116,7 @@ NotificationManager.prototype.post = function(notification) {
 
 NotificationManager.prototype.update = function(notification) {
   var args = validator_.validateArgs(arguments, [
-    {name: 'notification', type: types_.PLATFORM_OBJECT, values: StatusNotification}
+    {name: 'notification', type: types_.PLATFORM_OBJECT, values: Notification}
   ]);
 
   if (!arguments.length) {
@@ -118,6 +127,8 @@ NotificationManager.prototype.update = function(notification) {
   }
 
   var data = {
+    //add marker for UserNotification implementation
+    newImpl: (args.notification instanceof tizen.UserNotification),
     notification: args.notification
   };
 
@@ -184,6 +195,36 @@ NotificationManager.prototype.get = function(id) {
   return returnObject;
 };
 
+NotificationManager.prototype.getNotification = function(id) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'id', type: types_.STRING}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  }
+
+  var data = {
+    //add marker for UserNotification implementation
+    newImpl: true,
+    id: args.id
+  };
+
+  var result = native_.callSync('NotificationManager_get', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var n = native_.getResultObject(result);
+
+  _edit.allow();
+  var returnObject = new UserNotification(n.userType, n.title, n);
+  _edit.disallow();
+
+  return returnObject;
+};
+
 NotificationManager.prototype.getAll = function() {
   var result = native_.callSync('NotificationManager_getAll', {});
 
@@ -203,6 +244,28 @@ NotificationManager.prototype.getAll = function() {
   return notifications;
 };
 
+NotificationManager.prototype.getAllNotifications = function() {
+  var result = native_.callSync('NotificationManager_getAll', {
+    //add marker for UserNotification implementation
+    newImpl: true
+    });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var n = native_.getResultObject(result);
+  var notifications = [];
+
+  _edit.allow();
+  for (var i = 0; i < n.length; i++) {
+    notifications.push(new UserNotification(n[i].userType, n[i].title, n[i]));
+  }
+  _edit.disallow();
+
+  return notifications;
+};
+
 /**
  * Plays the custom effect of the service LED that is located to the front of a device.
  *
@@ -242,6 +305,96 @@ NotificationManager.prototype.stopLEDCustomEffect = function() {
   }
 };
 
+NotificationManager.prototype.saveNotificationAsTemplate = function(name, notification) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'name', type: types_.STRING},
+    {name: 'notification', type: types_.PLATFORM_OBJECT, values: Notification}
+  ]);
+
+  //add marker for UserNotification implementation
+  args.newImpl = (args.notification instanceof tizen.UserNotification);
+
+  var result = native_.callSync('NotificationManager_saveNotificationAsTemplate', args);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+NotificationManager.prototype.createNotificationFromTemplate = function(name) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'name', type: types_.STRING}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  }
+
+  var result = native_.callSync('NotificationManager_createNotificationFromTemplate', args);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  var n = native_.getResultObject(result);
+
+  _edit.allow();
+  var returnObject = new UserNotification(n.userType, n.title, n);
+  _edit.disallow();
+
+  return returnObject;
+};
+
+var _checkProgressValue = function(v, _progressType) {
+  if ((_progressType === NotificationProgressType.PERCENTAGE && (v >= 0 && v <= 100))
+          || (_progressType === NotificationProgressType.BYTE &&
+          converter_.toUnsignedLong(v) >= 0)) {
+    return true;
+  }
+  return false;
+};
+
+var _checkDetailInfo = function(v) {
+  if (type_.isNull(v)) {
+    return true;
+  }
+  if (!type_.isArray(v)) {
+    return false;
+  }
+  for (var i = 0; i < v.length; ++i) {
+    if (!(v[i] instanceof tizen.NotificationDetailInfo)) {
+      return false;
+    }
+  }
+  return true;
+};
+
+var _setDetailInfo = function(v) {
+  var _d = [];
+  for (var i = 0; i < v.length; ++i) {
+    _d.push(new tizen.NotificationDetailInfo(v[i].mainText, v[i].subText || null));
+  }
+  return _d;
+};
+
+var _checkStringArray = function(v) {
+  if (type_.isNull(v)) {
+    return true;
+  }
+  if (!type_.isArray(v)) {
+    return false;
+  }
+  for (var i = 0; i < v.length; ++i) {
+    if (!type_.isString(v[i])) {
+      return false;
+    }
+  }
+  return true;
+};
+
+var _isHex = function(v) {
+  return v.length === 7 && v.substr(0, 1) === '#' && (/^([0-9A-Fa-f]{2})+$/).test(v.substr(1, 7));
+};
+
 
 function NotificationInitDict(data) {
   var _iconPath = null;
@@ -251,60 +404,15 @@ function NotificationInitDict(data) {
   var _appId = null;
   var _progressType = NotificationProgressType.PERCENTAGE;
   var _progressValue = null;
-  var checkProgressValue = function(v) {
-    if ((_progressType === NotificationProgressType.PERCENTAGE && (v >= 0 && v <= 100))
-            || (_progressType === NotificationProgressType.BYTE &&
-            converter_.toUnsignedLong(v) >= 0)) {
-      return true;
-    }
-    return false;
-  };
   var _number = null;
   var _subIconPath = null;
   var _detailInfo = [];
-  var checkDetailInfo = function(v) {
-    if (type_.isNull(v)) {
-      return true;
-    }
-    if (!type_.isArray(v)) {
-      return false;
-    }
-    for (var i = 0; i < v.length; ++i) {
-      if (!(v[i] instanceof tizen.NotificationDetailInfo)) {
-        return false;
-      }
-    }
-    return true;
-  };
-  var setDetailInfo = function(v) {
-    var _d = [];
-    for (var i = 0; i < v.length; ++i) {
-      _d.push(new tizen.NotificationDetailInfo(v[i].mainText, v[i].subText || null));
-    }
-    return _d;
-  };
   var _ledColor = null;
-  var isHex = function(v) {
-    return v.length === 7 && v.substr(0, 1) === '#' && (/^([0-9A-Fa-f]{2})+$/).test(v.substr(1, 7));
-  };
   var _ledOnPeriod = 0;
   var _ledOffPeriod = 0;
   var _backgroundImagePath = null;
   var _thumbnails = [];
-  var checkThumbnails = function(v) {
-    if (type_.isNull(v)) {
-      return true;
-    }
-    if (!type_.isArray(v)) {
-      return false;
-    }
-    for (var i = 0; i < v.length; ++i) {
-      if (!type_.isString(v[i])) {
-        return false;
-      }
-    }
-    return true;
-  };
+
 
   Object.defineProperties(this, {
     iconPath: {
@@ -379,7 +487,7 @@ function NotificationInitDict(data) {
           _progressValue = v;
           return;
         }
-        if (checkProgressValue(v)) {
+        if (_checkProgressValue(v, _progressType)) {
           _progressValue = (_progressType === NotificationProgressType.PERCENTAGE)
             ? v / 100
             : converter_.toUnsignedLong(v);
@@ -410,7 +518,7 @@ function NotificationInitDict(data) {
         return _detailInfo;
       },
       set: function(v) {
-        _detailInfo = _edit.canEdit && v ? setDetailInfo(v) : checkDetailInfo(v) ? v : _detailInfo;
+        _detailInfo = _edit.canEdit && v ? _setDetailInfo(v) : _checkDetailInfo(v) ? v : _detailInfo;
       },
       enumerable: true
     },
@@ -419,7 +527,7 @@ function NotificationInitDict(data) {
         return _ledColor;
       },
       set: function(v) {
-        _ledColor = (type_.isString(v) && isHex(v)) || type_.isNull(v) ? v : _ledColor;
+        _ledColor = (type_.isString(v) && _isHex(v)) || type_.isNull(v) ? v : _ledColor;
       },
       enumerable: true
     },
@@ -455,7 +563,7 @@ function NotificationInitDict(data) {
         return _thumbnails;
       },
       set: function(v) {
-        _thumbnails = checkThumbnails(v) ? v : _thumbnails;
+        _thumbnails = _checkStringArray(v) ? v : _thumbnails;
       },
       enumerable: true
     }
@@ -564,7 +672,6 @@ function StatusNotification(statusType, title, notificationInitDict) {
 StatusNotification.prototype = new Notification();
 StatusNotification.prototype.constructor = StatusNotification;
 
-
 function NotificationDetailInfo(mainText, subText) {
   validator_.isConstructorCall(this, NotificationDetailInfo);
 
@@ -593,6 +700,474 @@ function NotificationDetailInfo(mainText, subText) {
   });
 }
 
+function TextContentsInitDict(data) {
+  if (!this) return;
+  var _progressType = NotificationProgressType.PERCENTAGE;
+  var _progressValue = null;
+  var _number = null;
+  var _detailInfo = [];
+  var _buttonsTexts = [];
+  var _contentForOff  = null;
+
+  Object.defineProperties(this, {
+    progressType: {
+      get: function() {
+        return _progressType;
+      },
+      set: function(v) {
+        _progressType = Object.keys(NotificationProgressType).indexOf(v) >= 0 ? v : _progressType;
+      },
+      enumerable: true
+    },
+    progressValue: {
+      get: function() {
+        if (null === _progressValue) {
+          return _progressValue;
+        }
+
+        return (_progressType === NotificationProgressType.PERCENTAGE)
+            ? _progressValue * 100
+            : _progressValue;
+      },
+      set: function(v) {
+        if (type_.isNull(v)) {
+          _progressValue = v;
+          return;
+        }
+        if (_checkProgressValue(v, _progressType)) {
+          _progressValue = (_progressType === NotificationProgressType.PERCENTAGE)
+            ? v / 100
+            : converter_.toUnsignedLong(v);
+        }
+      },
+      enumerable: true
+    },
+    eventsNumber: {
+      get: function() {
+        return _number;
+      },
+      set: function(v) {
+        _number = type_.isNumber(v) || type_.isNull(v) ? v : _number;
+      },
+      enumerable: true
+    },
+    detailInfo: {
+      get: function() {
+        return _detailInfo;
+      },
+      set: function(v) {
+        _detailInfo = _edit.canEdit && v ? _setDetailInfo(v) : _checkDetailInfo(v) ? v : _detailInfo;
+      },
+      enumerable: true
+    },
+    buttonsTexts: {
+      get: function() {
+        return _buttonsTexts;
+      },
+      set: function(v) {
+        _buttonsTexts = _checkStringArray(v) ? v : _buttonsTexts;
+      },
+      enumerable: true
+    },
+    contentForOff: {
+      get: function() {
+        return _contentForOff;
+      },
+      set: function(v) {
+        _contentForOff = type_.isString(v) || type_.isNull(v) ? v : _contentForOff;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    this['progressType'] = data['progressType'];
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function ImagesInitDict(data) {
+  if (!this) return;
+  var _iconPath = null;
+  var _subIconPath = null;
+  var _indicatorIconPath = null;
+  var _lockScreenIconPath = null;
+  var _buttonIconPaths = [];
+  var _backgroundImagePath  = null;
+
+  Object.defineProperties(this, {
+    iconPath: {
+      get: function() {
+        return _iconPath;
+      },
+      set: function(v) {
+        _iconPath = type_.isString(v) || type_.isNull(v) ? v : _iconPath;
+      },
+      enumerable: true
+    },
+    subIconPath: {
+      get: function() {
+        return _subIconPath;
+      },
+      set: function(v) {
+        _subIconPath = type_.isString(v) || type_.isNull(v) ? v : _subIconPath;
+      },
+      enumerable: true
+    },
+    indicatorIconPath: {
+      get: function() {
+        return _indicatorIconPath;
+      },
+      set: function(v) {
+        _indicatorIconPath = type_.isString(v) || type_.isNull(v) ? v : _indicatorIconPath;
+      },
+      enumerable: true
+    },
+    lockScreenIconPath: {
+      get: function() {
+        return _lockScreenIconPath;
+      },
+      set: function(v) {
+        _lockScreenIconPath = type_.isString(v) || type_.isNull(v) ? v : _lockScreenIconPath;
+      },
+      enumerable: true
+    },
+    buttonIconPaths: {
+      get: function() {
+        return _buttonIconPaths;
+      },
+      set: function(v) {
+        _buttonIconPaths = _checkStringArray(v) ? v : _buttonIconPaths;
+      },
+      enumerable: true
+    },
+    backgroundImagePath: {
+      get: function() {
+        return _backgroundImagePath;
+      },
+      set: function(v) {
+        _backgroundImagePath = type_.isString(v) || type_.isNull(v) ? v : _backgroundImagePath;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function ThumbnailsInitDict(data) {
+  if (!this) return;
+  var _lockScreenThumbnailIconPath = null;
+  var _thumbnailIconPath = null;
+  var _thumbnails = [];
+
+  Object.defineProperties(this, {
+    lockScreenThumbnailIconPath: {
+      get: function() {
+        return _lockScreenThumbnailIconPath;
+      },
+      set: function(v) {
+        _lockScreenThumbnailIconPath = type_.isString(v) || type_.isNull(v) ? v : _lockScreenThumbnailIconPath;
+      },
+      enumerable: true
+    },
+    thumbnailIconPath: {
+      get: function() {
+        return _thumbnailIconPath;
+      },
+      set: function(v) {
+        _thumbnailIconPath = type_.isString(v) || type_.isNull(v) ? v : _thumbnailIconPath;
+      },
+      enumerable: true
+    },
+    thumbnails: {
+      get: function() {
+        return _thumbnails;
+      },
+      set: function(v) {
+        _thumbnails = _checkStringArray(v) ? v : _thumbnails;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function ActionsInitDict(data) {
+  if (!this) return;
+  var _soundPath = null;
+  var _vibration = false;
+  var _appControl = null;
+  var _appId = null;
+
+  Object.defineProperties(this, {
+    soundPath: {
+      get: function() {
+        return _soundPath;
+      },
+      set: function(v) {
+        _soundPath = type_.isString(v) || type_.isNull(v) ? v : _soundPath;
+      },
+      enumerable: true
+    },
+    vibration: {
+      get: function() {
+        return _vibration;
+      },
+      set: function(v) {
+        _vibration = type_.isBoolean(v) ? v : _vibration;
+      },
+      enumerable: true
+    },
+    appControl: {
+      get: function() {
+        return _appControl;
+      },
+      set: function(v) {
+        _appControl = _edit.canEdit && v
+            ? new tizen.ApplicationControl(v.operation, v.uri || null, v.mime || null, v.category
+                    || null, v.data || [])
+            : v instanceof tizen.ApplicationControl || type_.isNull(v) ? v : _appControl;
+      },
+      enumerable: true
+    },
+    appId: {
+      get: function() {
+        return _appId;
+      },
+      set: function(v) {
+        _appId = type_.isString(v) && !(/\s/.test(v)) || type_.isNull(v) ? v : _appId;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function GroupContentsInitDict(data) {
+  if (!this) return;
+  var _groupTitle = null;
+  var _groupContent = null;
+  var _groupContentForOff = null;
+
+  Object.defineProperties(this, {
+    groupTitle: {
+      get: function() {
+        return _groupTitle;
+      },
+      set: function(v) {
+        _groupTitle = type_.isString(v) || type_.isNull(v) ? v : _groupTitle;
+      },
+      enumerable: true
+    },
+    groupContent: {
+      get: function() {
+        return _groupContent;
+      },
+      set: function(v) {
+        _groupContent = type_.isString(v) || type_.isNull(v) ? v : _groupContent;
+      },
+      enumerable: true
+    },
+    groupContentForOff: {
+      get: function() {
+        return _groupContentForOff;
+      },
+      set: function(v) {
+        _groupContentForOff = type_.isString(v) || type_.isNull(v) ? v : _groupContentForOff;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function LedsInitDict(data) {
+  if (!this) return;
+  var _ledColor = null;
+  var _ledOnPeriod = 0;
+  var _ledOffPeriod = 0;
+
+  Object.defineProperties(this, {
+    ledColor: {
+      get: function() {
+        return _ledColor;
+      },
+      set: function(v) {
+        _ledColor = (type_.isString(v) && _isHex(v)) || type_.isNull(v) ? v : _ledColor;
+      },
+      enumerable: true
+    },
+    ledOnPeriod: {
+      get: function() {
+        return _ledOnPeriod;
+      },
+      set: function(v) {
+        _ledOnPeriod = type_.isNumber(v) ? v : _ledOnPeriod;
+      },
+      enumerable: true
+    },
+    ledOffPeriod: {
+      get: function() {
+        return _ledOffPeriod;
+      },
+      set: function(v) {
+        _ledOffPeriod = type_.isNumber(v) ? v : _ledOffPeriod;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function UserNotification(userType, title, notificationGroupedInitDict) {
+  validator_.isConstructorCall(this, UserNotification);
+  type_.isObject(notificationGroupedInitDict) ?
+      notificationGroupedInitDict.title = title :
+        notificationGroupedInitDict = {title: title};
+  UserNotificationInitDict.call(this, notificationGroupedInitDict);
+  Notification.call(this, notificationGroupedInitDict);
+
+  this.textContents = new TextContentsInitDict(notificationGroupedInitDict.textContents);
+  this.images = new ImagesInitDict(notificationGroupedInitDict.images);
+  this.thumbnails = new ThumbnailsInitDict(notificationGroupedInitDict.thumbnails);
+  this.actions = new ActionsInitDict(notificationGroupedInitDict.actions);
+  this.leds = new LedsInitDict(notificationGroupedInitDict.leds);
+  this.groupContents = new GroupContentsInitDict(notificationGroupedInitDict.groupContents);
+
+  var _userType = (Object.keys(UserNotificationType)).indexOf(userType) >= 0
+      ? userType : StatusNotificationType.SIMPLE;
+
+  Object.defineProperties(this, {
+    userType: {
+      get: function() {
+        return _userType;
+      },
+      set: function(v) {
+        _userType = (Object.keys(StatusNotificationType)).indexOf(v) >= 0 && _edit.canEdit
+            ? v : _userType;
+      },
+      enumerable: true
+    }
+  });
+}
+
+UserNotification.prototype = new Notification();
+UserNotification.prototype.constructor = UserNotification;
+
+function UserNotificationInitDict(data) {
+  var _textContents = null;
+  var _images = null;
+  var _thumbnails = null;
+  var _actions = null;
+  var _groupContents = null;
+  var _leds = null;
+
+  Object.defineProperties(this, {
+    textContents: {
+      get: function() {
+        return _textContents;
+      },
+      set: function(v) {
+        _textContents = type_.isObject(v) || type_.isNull(v) ? v : _textContents;
+      },
+      enumerable: true
+    },
+    images: {
+      get: function() {
+        return _images;
+      },
+      set: function(v) {
+        _images = type_.isObject(v) || type_.isNull(v) ? v : _images;
+      },
+      enumerable: true
+    },
+    thumbnails: {
+      get: function() {
+        return _thumbnails;
+      },
+      set: function(v) {
+        _thumbnails = type_.isObject(v) || type_.isNull(v) ? v : _thumbnails;
+      },
+      enumerable: true
+    },
+    actions: {
+      get: function() {
+        return _actions;
+      },
+      set: function(v) {
+        _actions = type_.isObject(v) || type_.isNull(v) ? v : _actions;
+      },
+      enumerable: true
+    },
+    groupContents: {
+      get: function() {
+        return _groupContents;
+      },
+      set: function(v) {
+        _groupContents = type_.isObject(v) || type_.isNull(v) ? v : _groupContents;
+      },
+      enumerable: true
+    },
+    leds: {
+      get: function() {
+        return _leds;
+      },
+      set: function(v) {
+        _leds = type_.isObject(v) || type_.isNull(v) ? v : _leds;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
 exports = new NotificationManager();
 tizen.StatusNotification = StatusNotification;
+tizen.UserNotification = UserNotification;
 tizen.NotificationDetailInfo = NotificationDetailInfo;
index 5a86476..2a9495c 100644 (file)
@@ -28,7 +28,8 @@ NotificationExtension::NotificationExtension() {
   SetExtensionName("tizen.notification");
   SetJavaScriptAPI(kSource_notification_api);
 
-  const char* entry_points[] = {"tizen.StatusNotification", "tizen.NotificationDetailInfo", NULL};
+  const char* entry_points[] = {"tizen.StatusNotification", "tizen.UserNotification",
+                                "tizen.NotificationDetailInfo", NULL};
   SetExtraJSEntryPoints(entry_points);
 }
 
index 8e8e356..0c64b26 100644 (file)
@@ -16,8 +16,6 @@
 
 #include "notification/notification_instance.h"
 
-#include <functional>
-
 #include "common/logger.h"
 #include "common/picojson.h"
 #include "common/platform_result.h"
@@ -50,6 +48,9 @@ NotificationInstance::NotificationInstance() {
   REGISTER_SYNC("NotificationManager_removeAll", NotificationManagerRemoveAll);
   REGISTER_SYNC("NotificationManager_playLEDCustomEffect", NotificationManagerPlayLEDCustomEffect);
   REGISTER_SYNC("NotificationManager_stopLEDCustomEffect", NotificationManagerStopLEDCustomEffect);
+  REGISTER_SYNC("NotificationManager_saveNotificationAsTemplate", NotificationManagerSaveTemplate);
+  REGISTER_SYNC("NotificationManager_createNotificationFromTemplate",
+                NotificationManagerCreateFromTemplate);
 #undef REGISTER_SYNC
 
   manager_ = NotificationManager::GetInstance();
@@ -71,7 +72,18 @@ void NotificationInstance::NotificationManagerPost(const picojson::value& args,
 
   LoggerD("Enter");
   picojson::value val{picojson::object{}};
-  PlatformResult status = manager_->Post(args.get<picojson::object>(), val.get<picojson::object>());
+
+  using namespace std::placeholders;
+  std::function<PlatformResult(const picojson::object& args, picojson::object&)> impl{};
+  if (args.contains("newImpl") && args.get("newImpl").get<bool>()) {
+    LoggerD("New implementation");
+    impl = std::bind(&NotificationManager::PostUserNoti, manager_, _1, _2);
+  } else {
+    LoggerW("Deprecated object used");
+    impl = std::bind(&NotificationManager::Post, manager_, _1, _2);
+  }
+
+  PlatformResult status = impl(args.get<picojson::object>(), val.get<picojson::object>());
 
   if (status.IsSuccess()) {
     ReportSuccess(val, out);
@@ -85,7 +97,17 @@ void NotificationInstance::NotificationManagerUpdate(const picojson::value& args
   CHECK_PRIVILEGE_ACCESS(kPrivilegeNotification, &out);
 
   LoggerD("Enter");
-  PlatformResult status = manager_->Update(args.get<picojson::object>());
+  using namespace std::placeholders;
+  std::function<PlatformResult(const picojson::object& args)> impl{};
+  if (args.contains("newImpl") && args.get("newImpl").get<bool>()) {
+    LoggerD("New implementation");
+    impl = std::bind(&NotificationManager::UpdateUserNoti, manager_, _1);
+  } else {
+    LoggerW("Deprecated object used");
+    impl = std::bind(&NotificationManager::Update, manager_, _1);
+  }
+
+  PlatformResult status = impl(args.get<picojson::object>());
 
   if (status.IsSuccess()) {
     ReportSuccess(out);
@@ -127,7 +149,9 @@ void NotificationInstance::NotificationManagerGet(const picojson::value& args,
   LoggerD("Enter");
   picojson::value val{picojson::object{}};
 
-  PlatformResult status = manager_->Get(args.get<picojson::object>(), val.get<picojson::object>());
+  PlatformResult status =
+      manager_->Get(args.get<picojson::object>(), val.get<picojson::object>(),
+                    args.contains("newImpl") && args.get("newImpl").get<bool>());
 
   if (status.IsSuccess()) {
     ReportSuccess(val, out);
@@ -141,7 +165,8 @@ void NotificationInstance::NotificationManagerGetAll(const picojson::value& args
   LoggerD("Enter");
   picojson::value val{picojson::array{}};
 
-  PlatformResult status = manager_->GetAll(val.get<picojson::array>());
+  PlatformResult status = manager_->GetAll(
+      val.get<picojson::array>(), args.contains("newImpl") && args.get("newImpl").get<bool>());
 
   if (status.IsSuccess()) {
     ReportSuccess(val, out);
@@ -178,6 +203,36 @@ void NotificationInstance::NotificationManagerStopLEDCustomEffect(const picojson
   }
 }
 
+void NotificationInstance::NotificationManagerSaveTemplate(const picojson::value& args,
+                                                           picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeNotification, &out);
+
+  PlatformResult status = manager_->SaveTemplate(args.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LogAndReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerCreateFromTemplate(const picojson::value& args,
+                                                                 picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeNotification, &out);
+  picojson::value val{picojson::object{}};
+
+  PlatformResult status =
+      manager_->CreateFromTemplate(args.get<picojson::object>(), val.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(val, out);
+  } else {
+    LogAndReportError(status, &out);
+  }
+}
+
 #undef CHECK_EXIST
 
 }  // namespace notification
index 5e33b04..fa0715f 100644 (file)
@@ -40,6 +40,8 @@ class NotificationInstance : public common::ParsedInstance {
 
   void NotificationManagerPlayLEDCustomEffect(const picojson::value& args, picojson::object& out);
   void NotificationManagerStopLEDCustomEffect(const picojson::value& args, picojson::object& out);
+  void NotificationManagerSaveTemplate(const picojson::value& args, picojson::object& out);
+  void NotificationManagerCreateFromTemplate(const picojson::value& args, picojson::object& out);
 };
 
 }  // namespace notification
index 8af92a8..bc7b9e8 100644 (file)
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <app_common.h>
 #include <app_control_internal.h>
 #include <device/led.h>
 #include <notification_internal.h>
@@ -28,7 +29,9 @@
 #include "common/logger.h"
 #include "common/scope_exit.h"
 
+#include "notification/common_notification.h"
 #include "notification/status_notification.h"
+#include "notification/user_notification.h"
 
 namespace extension {
 namespace notification {
@@ -51,20 +54,31 @@ NotificationManager* NotificationManager::GetInstance() {
 
 PlatformResult NotificationManager::Post(const picojson::object& args, picojson::object& out) {
   LoggerD("Enter");
-  return StatusNotification::FromJson(args, false, &out);
+  return StatusNotification::PostStatusNotification(args, false, &out);
+}
+
+PlatformResult NotificationManager::PostUserNoti(const picojson::object& args,
+                                                 picojson::object& out) {
+  LoggerD("Enter");
+  return UserNotification::PostUserNotification(args, false, &out);
 }
 
 PlatformResult NotificationManager::Update(const picojson::object& args) {
   LoggerD("Enter");
-  return StatusNotification::FromJson(args, true, NULL);
+  return StatusNotification::PostStatusNotification(args, true, nullptr);
+}
+
+PlatformResult NotificationManager::UpdateUserNoti(const picojson::object& args) {
+  LoggerD("Enter");
+  return UserNotification::PostUserNotification(args, true, nullptr);
 }
 
 PlatformResult NotificationManager::Remove(const picojson::object& args) {
   LoggerD("Enter");
   int id = std::stoi(FromJson<std::string>(args, "id"));
 
-  int ret = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NONE, id);
-  if (ret != NOTIFICATION_ERROR_NONE) {
+  int ret = notification_delete_by_priv_id(nullptr, NOTIFICATION_TYPE_NONE, id);
+  if (NOTIFICATION_ERROR_NONE != ret) {
     return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Cannot remove notification error",
                               ("Cannot remove notification error: %d", ret));
   }
@@ -75,13 +89,13 @@ PlatformResult NotificationManager::Remove(const picojson::object& args) {
 PlatformResult NotificationManager::RemoveAll() {
   LoggerD("Enter");
   int ret = notification_delete_all(NOTIFICATION_TYPE_NOTI);
-  if (ret != NOTIFICATION_ERROR_NONE) {
+  if (NOTIFICATION_ERROR_NONE != ret) {
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Notification noti remove all failed",
                               ("Notification remove all failed: %d", ret));
   }
 
   ret = notification_delete_all(NOTIFICATION_TYPE_ONGOING);
-  if (ret != NOTIFICATION_ERROR_NONE) {
+  if (NOTIFICATION_ERROR_NONE != ret) {
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Notification ongoing remove all failed",
                               ("Notification remove all failed: %d", ret));
   }
@@ -89,7 +103,8 @@ PlatformResult NotificationManager::RemoveAll() {
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult NotificationManager::Get(const picojson::object& args, picojson::object& out) {
+PlatformResult NotificationManager::Get(const picojson::object& args, picojson::object& out,
+                                        bool is_new_impl) {
   LoggerD("Enter");
   int id;
   try {
@@ -120,7 +135,12 @@ PlatformResult NotificationManager::Get(const picojson::object& args, picojson::
     LoggerE("Failed: GetAppControl");
     return status;
   }
-  status = StatusNotification::ToJson(id, noti_handle, app_control, &out);
+
+  if (!is_new_impl) {
+    status = StatusNotification::ToJson(id, noti_handle, app_control, &out);
+  } else {
+    status = UserNotification::ToJson(id, noti_handle, app_control, &out);
+  }
   if (status.IsError()) {
     LoggerE("Failed: ToJson");
     return status;
@@ -128,7 +148,7 @@ PlatformResult NotificationManager::Get(const picojson::object& args, picojson::
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult NotificationManager::GetAll(picojson::array& out) {
+PlatformResult NotificationManager::GetAll(picojson::array& out, bool is_new_impl) {
   LoggerD("Enter");
   notification_h noti = nullptr;
   notification_list_h noti_list = nullptr;
@@ -160,7 +180,7 @@ PlatformResult NotificationManager::GetAll(picojson::array& out) {
     noti = notification_list_get_data(noti_list_iter);
     if (nullptr != noti) {
       int noti_priv = -1;
-      ret = notification_get_id(noti, NULL, &noti_priv);
+      ret = notification_get_id(noti, nullptr, &noti_priv);
       if (NOTIFICATION_ERROR_NONE != ret) {
         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot get notification id error",
                                   ("Cannot get notification id, error: %d", ret));
@@ -179,7 +199,11 @@ PlatformResult NotificationManager::GetAll(picojson::array& out) {
 
       picojson::object noti_item = picojson::object();
 
-      status = StatusNotification::ToJson(noti_priv, noti, app_control, &noti_item);
+      if (!is_new_impl) {
+        status = StatusNotification::ToJson(noti_priv, noti, app_control, &noti_item);
+      } else {
+        status = UserNotification::ToJson(noti_priv, noti, app_control, &noti_item);
+      }
       if (status.IsError()) return status;
 
       out.push_back(picojson::value(noti_item));
@@ -202,15 +226,15 @@ PlatformResult NotificationManager::PlayLEDCustomEffect(const picojson::object&
   unsigned int platformFlags = 0;
   for (auto flag : flags) {
     std::string flagStr = JsonCast<std::string>(flag);
-    if (flagStr == "LED_CUSTOM_DEFAULT")
+    if ("LED_CUSTOM_DEFAULT" == flagStr)
       platformFlags |= LED_CUSTOM_DEFAULT;
-    else if (flagStr == "LED_CUSTOM_DUTY_ON")
+    else if ("LED_CUSTOM_DUTY_ON" == flagStr)
       platformFlags |= LED_CUSTOM_DUTY_ON;
   }
 
   int ret;
   ret = device_led_play_custom(timeOn, timeOff, color, platformFlags);
-  if (ret != DEVICE_ERROR_NONE) {
+  if (DEVICE_ERROR_NONE != ret) {
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot play LED custom effect",
                               ("Cannot play LED custom effect: ", ret));
   }
@@ -222,7 +246,7 @@ PlatformResult NotificationManager::StopLEDCustomEffect() {
   LoggerD("Enter");
 
   int ret = device_led_stop_custom();
-  if (ret != DEVICE_ERROR_NONE) {
+  if (DEVICE_ERROR_NONE != ret) {
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot stop LED custom effect",
                               ("Cannot stop LED custom effect: ", ret));
   }
@@ -230,5 +254,68 @@ PlatformResult NotificationManager::StopLEDCustomEffect() {
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+common::PlatformResult NotificationManager::SaveTemplate(const picojson::object& args) {
+  LoggerD("Enter");
+  std::string name = FromJson<std::string>(args, "name");
+  notification_h noti_handle = nullptr;
+  int ret;
+  SCOPE_EXIT {
+    notification_free(noti_handle);
+  };
+
+  PlatformResult status = PlatformResult(ErrorCode::NO_ERROR);
+  const auto& new_impl_it = args.find("newImpl");
+  const auto& noti_val_it = args.find("notification");
+  if (args.end() != new_impl_it && args.end() != noti_val_it && new_impl_it->second.get<bool>()) {
+    status = UserNotification::GetNotiHandleFromJson(noti_val_it->second, false, &noti_handle);
+  } else {
+    status = StatusNotification::GetNotiHandleFromJson(noti_val_it->second, false, &noti_handle);
+  }
+
+  if (status.IsError()) {
+    return status;
+  }
+
+  ret = notification_save_as_template(noti_handle, name.c_str());
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    LoggerD("Error: %d (%s)", ret, get_error_message(ret));
+    if (NOTIFICATION_ERROR_MAX_EXCEEDED == ret) {
+      return LogAndCreateResult(ErrorCode::QUOTA_EXCEEDED_ERR,
+                                "Maximum number of templates exceeded",
+                                ("Maximum number of templates exceeded, error: %d", ret));
+    } else {
+      return LogAndCreateResult(ErrorCode::ABORT_ERR, "Saving template failed",
+                                ("Saving template failed, error: %d", ret));
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult NotificationManager::CreateFromTemplate(const picojson::object& args,
+                                                               picojson::object& out) {
+  LoggerD("Enter");
+  std::string name = FromJson<std::string>(args, "name");
+
+  notification_h noti_handle = nullptr;
+  noti_handle = notification_create_from_template(name.c_str());
+  if (!noti_handle) {
+    return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "The template with given name not found",
+                              ("The template with given name not found, handle is nullptr"));
+  }
+
+  SCOPE_EXIT {
+    notification_free(noti_handle);
+  };
+
+  // This method is designed to return only UserNotification objects
+  PlatformResult status = UserNotification::ToJson(0, noti_handle, nullptr, &out);
+  if (status.IsError()) {
+    LoggerE("Failed: ToJson");
+    return status;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
 }  // namespace notification
 }  // namespace extension
index df76d26..883ee57 100644 (file)
@@ -30,15 +30,22 @@ class NotificationManager {
   static NotificationManager* GetInstance();
 
   common::PlatformResult Post(const picojson::object& args, picojson::object& out);
+  common::PlatformResult PostUserNoti(const picojson::object& args, picojson::object& out);
   common::PlatformResult Update(const picojson::object& args);
+  common::PlatformResult UpdateUserNoti(const picojson::object& args);
   common::PlatformResult Remove(const picojson::object& args);
   common::PlatformResult RemoveAll();
-  common::PlatformResult Get(const picojson::object& args, picojson::object& out);
-  common::PlatformResult GetAll(picojson::array& out);
+  common::PlatformResult Get(const picojson::object& args, picojson::object& out,
+                             bool is_new_impl = false);
+  common::PlatformResult GetAll(picojson::array& out, bool is_new_impl = false);
 
   common::PlatformResult PlayLEDCustomEffect(const picojson::object& args);
   common::PlatformResult StopLEDCustomEffect();
 
+  // TODO needed also below functions for new design?
+  common::PlatformResult SaveTemplate(const picojson::object& args);
+  common::PlatformResult CreateFromTemplate(const picojson::object& args, picojson::object& out);
+
  private:
   NotificationManager();
   virtual ~NotificationManager();
index 3fd3496..cf4eea1 100644 (file)
 
 #include "notification/status_notification.h"
 
-#include <app_control_internal.h>
-#include <notification.h>
-#include <notification_internal.h>
-
 #include "common/converter.h"
 #include "common/filesystem/filesystem_provider.h"
 #include "common/logger.h"
@@ -30,1200 +26,157 @@ namespace notification {
 
 using namespace common;
 
-const std::string kProgressTypePercentage = "PERCENTAGE";
-const std::string kProgressTypeByte = "BYTE";
-
-const InformationEnumMap StatusNotification::info_map_ = {{0, NOTIFICATION_TEXT_TYPE_INFO_1},
-                                                          {1, NOTIFICATION_TEXT_TYPE_INFO_2},
-                                                          {2, NOTIFICATION_TEXT_TYPE_INFO_3}};
-
-const InformationEnumMap StatusNotification::info_sub_map_ = {
-    {0, NOTIFICATION_TEXT_TYPE_INFO_SUB_1},
-    {1, NOTIFICATION_TEXT_TYPE_INFO_SUB_2},
-    {2, NOTIFICATION_TEXT_TYPE_INFO_SUB_3}};
-
-const ImageEnumMap StatusNotification::thumbnails_map_ = {{0, NOTIFICATION_IMAGE_TYPE_LIST_1},
-                                                          {1, NOTIFICATION_IMAGE_TYPE_LIST_2},
-                                                          {2, NOTIFICATION_IMAGE_TYPE_LIST_3},
-                                                          {3, NOTIFICATION_IMAGE_TYPE_LIST_4}};
-
 StatusNotification::StatusNotification() {
 }
 
 StatusNotification::~StatusNotification() {
 }
 
-bool StatusNotification::IsColorFormatNumberic(const std::string& color) {
-  LoggerD("Enter");
-  std::string hexCode = "0123456789abcdef";
-  if (color.length() != 7 || '#' != color[0]) {
-    return false;
-  }
-
-  for (size_t i = 1; i < color.length(); i++) {
-    if (std::string::npos == hexCode.find(color[i])) {
-      return false;
-    }
-  }
-
-  return true;
-}
-
-PlatformResult StatusNotification::SetLayout(notification_h noti_handle,
-                                             const std::string& noti_type) {
-  LoggerD("Enter");
-  notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
-
-  if (noti_type == "SIMPLE") {
-    long number;
-    PlatformResult status = GetNumber(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &number);
-    if (status.IsError()) {
-      LoggerE("Failed: GetNumber");
-      return status;
-    }
-    if (number > 0)
-      noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
-    else
-      noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
-  } else if (noti_type == "THUMBNAIL") {
-    noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
-  }
-  if (noti_type == "ONGOING") {
-    noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
-  } else if (noti_type == "PROGRESS") {
-    noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
-  }
-  int ret = notification_set_layout(noti_handle, noti_layout);
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification layout error",
-                              ("Set notification layout error: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-static bool ServiceExtraDataCb(app_control_h service, const char* key, void* user_data) {
-  LoggerD("Enter");
-  if (nullptr == user_data || nullptr == key) {
-    LoggerE("User data or key not exist");
-    return true;
-  }
-
-  picojson::array* control_data = static_cast<picojson::array*>(user_data);
-
-  int length = 0;
-  char** value = NULL;
-  SCOPE_EXIT {
-    free(value);
-  };
-
-  int ret = app_control_get_extra_data_array(service, key, &value, &length);
-  if (ret != APP_CONTROL_ERROR_NONE) {
-    LoggerE("Get app control extra data error: %d", ret);
-    return true;
-  }
-
-  if (!value || !length) {
-    LoggerE("Get app control extra data value error");
-    return true;
-  }
-
-  picojson::array values = picojson::array();
-  for (int index = 0; index < length; ++index) {
-    values.push_back(picojson::value(value[index]));
-  }
-
-  picojson::object data_control_elem = picojson::object();
-  data_control_elem["key"] = picojson::value(key);
-  data_control_elem["value"] = picojson::value(values);
-
-  control_data->push_back(picojson::value(data_control_elem));
-
-  return true;
-}
-
-PlatformResult StatusNotification::Create(notification_type_e noti_type,
-                                          notification_h* noti_handle) {
-  LoggerD("Enter");
-  *noti_handle = notification_create(noti_type);
-  if (!*noti_handle) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot make new notification object");
-  }
-
-  if (NOTIFICATION_TYPE_ONGOING == noti_type) {
-    int ret =
-        notification_set_display_applist(*noti_handle, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
-                                                           NOTIFICATION_DISPLAY_APP_INDICATOR);
-    if (ret != NOTIFICATION_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot set notification display applist",
-                                ("Cannot make new notification object: %d", ret));
-    }
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::StatusTypeFromPlatform(notification_type_e noti_type,
-                                                          notification_ly_type_e noti_layout,
-                                                          std::string* type) {
-  LoggerD("Enter");
-  if (noti_type == NOTIFICATION_TYPE_NOTI) {
-    if (noti_layout == NOTIFICATION_LY_NOTI_EVENT_SINGLE ||
-        noti_layout == NOTIFICATION_LY_NOTI_EVENT_MULTIPLE) {
-      *type = "SIMPLE";
-    } else if (noti_layout == NOTIFICATION_LY_NOTI_THUMBNAIL) {
-      *type = "THUMBNAIL";
-    }
-  } else if (noti_type == NOTIFICATION_TYPE_ONGOING) {
-    if (noti_layout == NOTIFICATION_LY_ONGOING_EVENT) {
-      *type = "ONGOING";
-    } else if (noti_layout == NOTIFICATION_LY_ONGOING_PROGRESS) {
-      *type = "PROGRESS";
-    }
-  } else {
-    return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Notification type not found");
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::StatusTypeToPlatform(const std::string& type,
-                                                        notification_type_e* noti_type) {
-  LoggerD("Enter");
-  if (type == "SIMPLE" || type == "THUMBNAIL") {
-    *noti_type = NOTIFICATION_TYPE_NOTI;
-  } else if (type == "ONGOING" || type == "PROGRESS") {
-    *noti_type = NOTIFICATION_TYPE_ONGOING;
-  } else {
-    return LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR, "Invalide notification type",
-                              ("Invalide noti type: %s", type.c_str()));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetImage(notification_h noti_handle,
-                                            notification_image_type_e image_type,
-                                            std::string* image_path) {
-  LoggerD("Enter");
-  char* path = NULL;
-
-  *image_path = "";
-
-  if (notification_get_image(noti_handle, image_type, &path) != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification image error",
-                              ("Get notification image error, image_type: %d", image_type));
-  }
-  if (path) {
-    *image_path = path;
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetImage(notification_h noti_handle,
-                                            notification_image_type_e image_type,
-                                            const std::string& image_path) {
-  LoggerD("Enter");
-  int ret = notification_set_image(noti_handle, image_type, image_path.c_str());
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(
-        ErrorCode::UNKNOWN_ERR, "Set notification image error",
-        ("Set notification image error, image_type: %d, error: %d", image_type, ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetText(notification_h noti_handle,
-                                           notification_text_type_e text_type,
-                                           std::string* noti_text) {
-  LoggerD("Enter");
-  char* text = NULL;
-
-  *noti_text = "";
-
-  if (notification_get_text(noti_handle, text_type, &text) != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification text error",
-                              ("Get notification text error, text_type: %d", text_type));
-  }
-
-  if (text) *noti_text = text;
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetText(notification_h noti_handle,
-                                           notification_text_type_e text_type,
-                                           const std::string& noti_text) {
-  LoggerD("Enter");
-  int ret = notification_set_text(noti_handle, text_type, noti_text.c_str(), NULL,
-                                  NOTIFICATION_VARIABLE_TYPE_NONE);
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(
-        ErrorCode::UNKNOWN_ERR, "Set notification text error",
-        ("Set notification text error, text_type: %d, error: %d", text_type, ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetNumber(notification_h noti_handle,
-                                             notification_text_type_e text_type, long* number) {
-  LoggerD("Enter");
-  std::string text;
-  PlatformResult status = GetText(noti_handle, text_type, &text);
-  if (status.IsError()) return status;
-
-  if (text.length())
-    *number = std::stol(text);
-  else
-    *number = -1;
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetDetailInfos(notification_h noti_handle,
-                                                  picojson::array* out) {
-  LoggerD("Enter");
-  if (info_map_.size() != info_sub_map_.size()) {
-    return LogAndCreateResult(ErrorCode::VALIDATION_ERR,
-                              "Different notification information types element size");
-  }
-
-  picojson::value detail_info = picojson::value(picojson::object());
-  picojson::object& detail_info_obj = detail_info.get<picojson::object>();
-
-  std::string text;
-  size_t info_map_size = info_map_.size();
-  for (size_t idx = 0; idx < info_map_size; ++idx) {
-    PlatformResult status = GetText(noti_handle, info_map_.at(idx), &text);
-    if (status.IsError()) return status;
-
-    if (!text.length()) break;
-
-    detail_info_obj["mainText"] = picojson::value(text);
-
-    status = GetText(noti_handle, info_sub_map_.at(idx), &text);
-    if (status.IsError()) return status;
-
-    if (text.length()) {
-      detail_info_obj["subText"] = picojson::value(text);
-    }
-
-    out->push_back(detail_info);
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetDetailInfos(notification_h noti_handle,
-                                                  const picojson::array& value) {
-  LoggerD("Enter");
-  size_t idx = 0;
-
-  size_t info_map_size = info_map_.size();
-  for (auto& item : value) {
-    const picojson::object& obj = JsonCast<picojson::object>(item);
-
-    PlatformResult status =
-        SetText(noti_handle, info_map_.at(idx), common::FromJson<std::string>(obj, "mainText"));
-    if (status.IsError()) return status;
-
-    if (picojson::value(obj).contains("subText") && !IsNull(obj, "subText")) {
-      PlatformResult status = SetText(noti_handle, info_sub_map_.at(idx),
-                                      common::FromJson<std::string>(obj, "subText"));
-      if (status.IsError()) return status;
-    }
-
-    ++idx;
-
-    if (idx > info_map_size) {
-      return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
-                                "Too many values in notification detailInfo array");
-    }
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetLedColor(notification_h noti_handle, std::string* led_color) {
-  LoggerD("Enter");
-  unsigned int color = 0;
-  notification_led_op_e type = NOTIFICATION_LED_OP_ON;
-
-  if (notification_get_led(noti_handle, &type, (int*)&color) != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
-                              "Get notification led displaying option error");
-  }
-
-  *led_color = "";
-  std::stringstream stream;
-
-  if (NOTIFICATION_LED_OP_OFF != type) {
-    color = 0x00FFFFFF & color;
-    stream << std::hex << color;
-    *led_color = "#" + stream.str();
-
-    while (led_color->length() < 7) {
-      led_color->insert(1, "0");
-    }
-
-    std::transform(led_color->begin(), led_color->end(), led_color->begin(), ::tolower);
-  }
-
-  LoggerD("color:%s", (*led_color).c_str());
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetLedColor(notification_h noti_handle,
-                                               const std::string& led_color) {
-  LoggerD("Enter");
-  std::string color_str = led_color;
-  std::transform(color_str.begin(), color_str.end(), color_str.begin(), ::tolower);
-
-  if (!IsColorFormatNumberic(color_str)) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Led color is not numeric value",
-                              ("Led color is not numeric value: %s", color_str.c_str()));
-  }
-
-  std::stringstream stream;
-  unsigned int color = 0;
-  notification_led_op_e type = NOTIFICATION_LED_OP_ON;
-  std::string color_code = color_str.substr(1, color_str.length()).insert(0, "ff");
-
-  stream << std::hex << color_code;
-  stream >> color;
-
-  if (color != 0)
-    type = NOTIFICATION_LED_OP_ON_CUSTOM_COLOR;
-  else
-    type = NOTIFICATION_LED_OP_OFF;
-
-  int ret = notification_set_led(noti_handle, type, static_cast<int>(color));
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification led color eror",
-                              ("Set notification led color eror: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetLedPeriod(notification_h noti_handle,
-                                                unsigned long* on_period,
-                                                unsigned long* off_period) {
-  LoggerD("Enter");
-  int on_time = 0;
-  int off_time = 0;
-
-  if (notification_get_led_time_period(noti_handle, &on_time, &off_time) !=
-      NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification led on/off period error");
-  }
-
-  if (on_period) *on_period = on_time;
-  if (off_period) *off_period = off_time;
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetLedOnPeriod(notification_h noti_handle,
-                                                  unsigned long on_period) {
-  LoggerD("Enter");
-  unsigned long off_period = 0;
-  PlatformResult status = GetLedPeriod(noti_handle, nullptr, &off_period);
-  if (status.IsError()) return status;
-
-  int ret = notification_set_led_time_period(noti_handle, on_period, off_period);
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification led on period error",
-                              ("Set notification led on period error: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetLedOffPeriod(notification_h noti_handle,
-                                                   unsigned long off_period) {
-  LoggerD("Enter");
-  unsigned long on_period = 0;
-  PlatformResult status = GetLedPeriod(noti_handle, &on_period, nullptr);
-  if (status.IsError()) return status;
-
-  int ret = notification_set_led_time_period(noti_handle, on_period, off_period);
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification led off period error",
-                              ("Set notification led off period error: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetThumbnails(notification_h noti_handle, picojson::array* out) {
-  LoggerD("Enter");
-  std::string text;
-  size_t thumbnails_map_size = thumbnails_map_.size();
-  for (size_t idx = 0; idx < thumbnails_map_size; ++idx) {
-    PlatformResult status = GetImage(noti_handle, thumbnails_map_.at(idx), &text);
-    if (status.IsError()) return status;
-
-    if (!text.length()) break;
-
-    // CHECK GetVirtualPath ??
-    out->push_back(picojson::value(common::FilesystemProvider::Create().GetVirtualPath(text)));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetThumbnails(notification_h noti_handle,
-                                                 const picojson::array& value) {
-  LoggerD("Enter");
-  size_t idx = 0;
-
-  size_t thumbnails_map_size = thumbnails_map_.size();
-  for (auto& item : value) {
-    const std::string& text = JsonCast<std::string>(item);
-    std::string real_path = common::FilesystemProvider::Create().GetRealPath(text);
-
-    PlatformResult status = SetImage(noti_handle, thumbnails_map_.at(idx), real_path);
-    if (status.IsError()) return status;
-
-    ++idx;
-
-    if (idx > thumbnails_map_size) {
-      return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR,
-                                "Too many values in notification thumbnail array");
-    }
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetSoundPath(notification_h noti_handle,
-                                                std::string* sound_path) {
-  LoggerD("Enter");
-  *sound_path = "";
-
-  const char* path = NULL;
-  notification_sound_type_e type = NOTIFICATION_SOUND_TYPE_NONE;
-
-  if (notification_get_sound(noti_handle, &type, &path) != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification sound error");
-  }
-
-  LoggerD("Sound type = %d", type);
-
-  if (path && (type == NOTIFICATION_SOUND_TYPE_USER_DATA)) {
-    *sound_path = path;
-  }
-
-  LoggerD("Sound path = %s", sound_path->c_str());
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetSoundPath(notification_h noti_handle,
-                                                const std::string& sound_path) {
-  LoggerD("Enter");
-  int ret =
-      notification_set_sound(noti_handle, NOTIFICATION_SOUND_TYPE_USER_DATA, sound_path.c_str());
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification sound error",
-                              ("Set notification sound error: %d", ret));
-  }
-
-  LoggerD("Sound path = %s", sound_path.c_str());
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetVibration(notification_h noti_handle, bool* vibration) {
-  LoggerD("Enter");
-  notification_vibration_type_e vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
-
-  if (notification_get_vibration(noti_handle, &vib_type, NULL) != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification vibration error");
-  }
-
-  if (NOTIFICATION_VIBRATION_TYPE_DEFAULT == vib_type ||
-      NOTIFICATION_VIBRATION_TYPE_USER_DATA == vib_type) {
-    *vibration = true;
-  } else {
-    *vibration = false;
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetVibration(notification_h noti_handle, bool vibration) {
-  LoggerD("Enter");
-  bool platform_vibration;
-  PlatformResult status = GetVibration(noti_handle, &platform_vibration);
-  if (status.IsError()) return status;
-
-  if (platform_vibration != vibration) {
-    notification_vibration_type_e vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
-
-    if (vibration) {
-      vib_type = NOTIFICATION_VIBRATION_TYPE_DEFAULT;
-    }
-
-    int ret = notification_set_vibration(noti_handle, vib_type, NULL);
-    if (ret != NOTIFICATION_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification vibration error",
-                                ("Set notification vibration error: %d", ret));
-    }
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetApplicationControl(app_control_h app_handle,
-                                                         picojson::object* out_ptr) {
-  LoggerD("Enter");
-  picojson::object& out = *out_ptr;
-
-  char* operation = NULL;
-  char* uri = NULL;
-  char* mime = NULL;
-  char* category = NULL;
-  SCOPE_EXIT {
-    free(operation);
-    free(uri);
-    free(mime);
-    free(category);
-  };
-
-  int ret = app_control_get_operation(app_handle, &operation);
-  if (ret != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control operation error",
-                              ("Get application control operation error: %d", ret));
-  }
-  if (operation) {
-    out["operation"] = picojson::value(operation);
-    LoggerD("operation = %s", operation);
-  }
-
-  if (app_control_get_uri(app_handle, &uri) != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control uri error");
-  }
-  if (uri) {
-    out["uri"] = picojson::value(uri);
-    LoggerD("uri = %s", uri);
-  }
-
-  if (app_control_get_mime(app_handle, &mime) != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control mime error");
-  }
-  if (mime) {
-    out["mime"] = picojson::value(mime);
-    LoggerD("mime = %s", mime);
-  }
-
-  if (app_control_get_category(app_handle, &category) != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control category error");
-  }
-  if (category) {
-    out["category"] = picojson::value(category);
-    LoggerD("category = %s", category);
-  }
-
-  picojson::array app_control_data = picojson::array();
-  if (app_control_foreach_extra_data(app_handle, ServiceExtraDataCb, (void*)&app_control_data) !=
-      APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get application control data error");
-  }
-  out["data"] = picojson::value(app_control_data);
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetApplicationControl(app_control_h app_handle,
-                                                         const picojson::object& app_ctrl) {
-  LoggerD("Enter");
-  picojson::value val(app_ctrl);
-  const std::string& operation = common::FromJson<std::string>(app_ctrl, "operation");
-
-  int ret;
-  if (operation.length()) {
-    ret = app_control_set_operation(app_handle, operation.c_str());
-  } else {
-    ret = app_control_set_operation(app_handle, APP_CONTROL_OPERATION_DEFAULT);
-  }
-  if (ret != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control operation error",
-                              ("Set application control operation error: %d", ret));
-  }
-
-  if (val.contains("uri") && !IsNull(app_ctrl, "uri")) {
-    const std::string& uri = common::FromJson<std::string>(app_ctrl, "uri");
-    ret = app_control_set_uri(app_handle, uri.c_str());
-    if (ret != APP_CONTROL_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control uri error",
-                                ("Set application control uri error: %d", ret));
-    }
-  }
-
-  if (val.contains("mime") && !IsNull(app_ctrl, "mime")) {
-    const std::string& mime = common::FromJson<std::string>(app_ctrl, "mime");
-    ret = app_control_set_mime(app_handle, mime.c_str());
-    if (ret != APP_CONTROL_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control mime error",
-                                ("Set application control mime error: %d", ret));
-    }
-  }
-
-  if (val.contains("category") && !IsNull(app_ctrl, "category")) {
-    const std::string& category = common::FromJson<std::string>(app_ctrl, "category");
-    ret = app_control_set_category(app_handle, category.c_str());
-    if (ret != APP_CONTROL_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control category error",
-                                ("Set application control category error: %d", ret));
-    }
-  }
-
-  if (!picojson::value(app_ctrl).contains("data") || IsNull(app_ctrl, "data")) {
-    return PlatformResult(ErrorCode::NO_ERROR);
-  }
-
-  auto& items = common::FromJson<picojson::array>(app_ctrl, "data");
-
-  int idx = 0;
-
-  for (auto item : items) {
-    const picojson::object& obj = JsonCast<picojson::object>(item);
-    const std::string key = common::FromJson<std::string>(obj, "key");
-    const picojson::array values = common::FromJson<picojson::array>(obj, "value");
-    const char** arrayValue = (const char**)calloc(sizeof(char*), values.size());
-    SCOPE_EXIT {
-      free(arrayValue);
-    };
-    idx = 0;
-    for (auto& item : values) {
-      arrayValue[idx] = JsonCast<std::string>(item).c_str();
-      ++idx;
-    }
-    ret = app_control_add_extra_data_array(app_handle, key.c_str(), arrayValue, values.size());
-    if (ret != APP_CONTROL_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set application control extra data error",
-                                ("Set application control extra data error: %d", ret));
-    }
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetApplicationId(app_control_h app_handle, std::string* app_id) {
-  LoggerD("Enter");
-  char* app_id_str = NULL;
-  SCOPE_EXIT {
-    free(app_id_str);
-  };
-
-  *app_id = "";
-
-  if (app_control_get_app_id(app_handle, &app_id_str) != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get applicaiton ID failed");
-  }
-
-  if (app_id_str != NULL) {
-    *app_id = app_id_str;
-  }
-
-  LoggerD("Get appId = %s", /*(*app_id).c_str()*/ app_id_str);
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetApplicationId(app_control_h app_handle,
-                                                    const std::string& app_id) {
-  LoggerD("Enter");
-  int ret = app_control_set_app_id(app_handle, app_id.c_str());
-  if (ret != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set applicaiton ID error",
-                              ("Set applicaiton ID error: %d", ret));
-  }
-
-  LoggerD("Set appId = %s", app_id.c_str());
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetProgressValue(notification_h noti_handle,
-                                                    const std::string& progess_type,
-                                                    double* progress_value) {
-  LoggerD("Enter");
-  double tmp_progress_value = 0.0;
-
-  if (progess_type == kProgressTypeByte) {
-    if (notification_get_size(noti_handle, &tmp_progress_value) != NOTIFICATION_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification size error");
-    }
-  } else if (progess_type == kProgressTypePercentage) {
-    if (notification_get_progress(noti_handle, &tmp_progress_value) != NOTIFICATION_ERROR_NONE) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification progress error");
-    }
-    // native api uses range 0-1, but webapi expects 0-100, so we need to multiply result with 100
-    tmp_progress_value *= 100;
-  } else {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown notification progress type",
-                              ("Unknown notification progress type: %s ", progess_type.c_str()));
-  }
-
-  LOGGER(DEBUG) << "Progress " << progess_type << " = " << tmp_progress_value;
-
-  *progress_value = tmp_progress_value;
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetProgressValue(notification_h noti_handle,
-                                                    const std::string& progress_type,
-                                                    double progress_value, bool is_update) {
-  LoggerD("Enter");
-  int ret;
-
-  if (progress_type == kProgressTypeByte) {
-    ret = notification_set_size(noti_handle, progress_value);
-
-    if (is_update) {
-      ret = notification_update_size(noti_handle, NOTIFICATION_PRIV_ID_NONE, progress_value);
-    }
-  } else if (progress_type == kProgressTypePercentage) {
-    // native api uses range 0-1, but webapi expects 0-100, so we need to divide by 100
-    ret = notification_set_progress(noti_handle, progress_value / 100);
-
-    if (is_update) {
-      ret = notification_update_progress(noti_handle, NOTIFICATION_PRIV_ID_NONE, progress_value);
-    }
-  } else {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown notification progress type",
-                              ("Unknown notification progress type: %s ", progress_type.c_str()));
-  }
-
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Set notification progress/size error",
-                              ("Set notification progress/size error: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetPostedTime(notification_h noti_handle, time_t* posted_time) {
-  LoggerD("Enter");
-  *posted_time = 0;
-
-  if (notification_get_insert_time(noti_handle, posted_time) != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Get notification posted time error");
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetNotiHandle(int id, notification_h* noti_handle) {
-  LoggerD("Enter");
-  *noti_handle = notification_load(NULL, id);
-  if (NULL == *noti_handle) {
-    return LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Not found or removed notification id");
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::GetAppControl(notification_h noti_handle,
-                                                 app_control_h* app_control) {
-  LoggerD("Enter");
-  int ret = notification_get_launch_option(noti_handle, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL,
-                                           static_cast<void*>(app_control));
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification get launch option error",
-                              ("Notification get launch option error: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::CreateAppControl(app_control_h* app_control) {
-  LoggerD("Enter");
-  int ret = app_control_create(app_control);
-  if (ret != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Application create error",
-                              ("Application create error: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
-PlatformResult StatusNotification::SetAppControl(notification_h noti_handle,
-                                                 app_control_h app_control) {
-  LoggerD("Enter");
-  int ret = notification_set_launch_option(noti_handle, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL,
-                                           static_cast<void*>(app_control));
-  if (ret != APP_CONTROL_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Notification set launch option error",
-                              ("Notification set launch option error: %d", ret));
-  }
-
-  return PlatformResult(ErrorCode::NO_ERROR);
-}
-
 PlatformResult StatusNotification::ToJson(int id, notification_h noti_handle,
                                           app_control_h app_handle, picojson::object* out_ptr) {
   LoggerD("Enter");
   picojson::object& out = *out_ptr;
 
-  out["id"] = picojson::value(std::to_string(id));
-  out["type"] = picojson::value("STATUS");
-
-  // Nitification type
-  notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
-  int ret = notification_get_type(noti_handle, &noti_type);
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Notification get type error",
-                              ("Notification get type error: %d", ret));
-  }
-
-  notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
-  ret = notification_get_layout(noti_handle, &noti_layout);
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Notification get layout error",
-                              ("Notification get layout error: %d", ret));
-  }
+  PlatformResult status = AddCommonMembersToJson(id, noti_handle, out_ptr);
+  CHECK_ERROR(status);
 
   std::string noti_type_str;
-  PlatformResult status = StatusTypeFromPlatform(noti_type, noti_layout, &noti_type_str);
-  if (status.IsError()) return status;
-  out["statusType"] = picojson::value(noti_type_str);
-
-  std::string value_str;
-  status = GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, &value_str);
-  if (status.IsError()) return status;
-  if (value_str.length()) {
-    out["iconPath"] =
-        picojson::value(common::FilesystemProvider::Create().GetVirtualPath(value_str));
-  }
-
-  status = GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_SUB, &value_str);
-  if (status.IsError()) return status;
-  if (value_str.length()) {
-    out["subIconPath"] =
-        picojson::value(common::FilesystemProvider::Create().GetVirtualPath(value_str));
-  }
-
-  long number;
-  status = GetNumber(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &number);
-  if (status.IsError()) return status;
-  if (number >= 0) {
-    out["number"] = picojson::value(static_cast<double>(number));
-  }
-
-  picojson::array detail_infos = picojson::array();
-  status = GetDetailInfos(noti_handle, &detail_infos);
-  if (status.IsError()) return status;
-  if (detail_infos.size()) {
-    out["detailInfo"] = picojson::value(detail_infos);
-  }
-
-  status = GetLedColor(noti_handle, &value_str);
-  if (status.IsError()) return status;
-  if (value_str.length()) {
-    out["ledColor"] = picojson::value(value_str);
-  }
-
-  unsigned long on_period;
-  unsigned long off_period;
-  status = GetLedPeriod(noti_handle, &on_period, &off_period);
-  if (status.IsError()) return status;
-  out["ledOnPeriod"] = picojson::value(static_cast<double>(on_period));
-  out["ledOffPeriod"] = picojson::value(static_cast<double>(off_period));
+  status = AddTypeToJson(noti_handle, "statusType", out_ptr, &noti_type_str);
+  CHECK_ERROR(status);
 
-  status = GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_BACKGROUND, &value_str);
-  if (status.IsError()) return status;
-  if (value_str.length()) {
-    out["backgroundImagePath"] =
-        picojson::value(common::FilesystemProvider::Create().GetVirtualPath(value_str));
-  }
+  // iconPath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, "iconPath", out_ptr);
+  CHECK_ERROR(status);
 
-  picojson::array thumbnails = picojson::array();
-  status = GetThumbnails(noti_handle, &thumbnails);
-  if (status.IsError()) return status;
-  if (thumbnails.size()) {
-    out["thumbnails"] = picojson::value(thumbnails);
-  }
+  // subIconPath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_SUB, "subIconPath", out_ptr);
+  CHECK_ERROR(status);
 
-  status = GetSoundPath(noti_handle, &value_str);
-  if (status.IsError()) return status;
-  if (value_str.length()) {
-    out["soundPath"] =
-        picojson::value(common::FilesystemProvider::Create().GetVirtualPath(value_str));
-  }
+  // eventsNumber
+  status = AddEventsNumberToJson(noti_handle, "number", &out);
+  CHECK_ERROR(status);
 
-  bool vibration;
-  status = GetVibration(noti_handle, &vibration);
-  if (status.IsError()) return status;
-  out["vibration"] = picojson::value(vibration);
+  // detailInfo
+  status = AddDetailInfosToJson(noti_handle, &out);
+  CHECK_ERROR(status);
 
-  picojson::object app_control = picojson::object();
-  status = GetApplicationControl(app_handle, &app_control);
-  if (status.IsError()) return status;
-  if (app_control.size()) {
-    out["appControl"] = picojson::value(app_control);
-  }
+  // ledColor
+  status = AddLedColorToJson(noti_handle, &out);
+  CHECK_ERROR(status);
 
-  status = GetApplicationId(app_handle, &value_str);
-  if (status.IsError()) return status;
-  if (value_str.length()) {
-    out["appId"] = picojson::value(value_str);
-  }
+  // ledOnPeriod, ledOffPeriod
+  status = AddLedOnOffPeriodToJson(noti_handle, &out);
+  CHECK_ERROR(status);
 
-  std::string progress_type;
-  status = GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_LIST_5, &progress_type);
-  if (status.IsError()) return status;
+  // backgroundImagePath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_BACKGROUND, "backgroundImagePath",
+                         out_ptr);
+  CHECK_ERROR(status);
 
-  // push service daemon doesn't set progress type
-  // so use default if notification type is different from "PROGRESS"
-  if ("PROGRESS" != noti_type_str) {
-    progress_type = progress_type == kProgressTypeByte ? progress_type : kProgressTypePercentage;
-  }
-  out["progressType"] = picojson::value(progress_type);
+  // thumbnails
+  status = AddPathsArrayToJson(noti_handle, thumbnails_map_, "thumbnails", out_ptr);
+  CHECK_ERROR(status);
 
-  double progress_value;
-  status = GetProgressValue(noti_handle, progress_type, &progress_value);
-  if (status.IsError()) return status;
-  out["progressValue"] = picojson::value(progress_value);
+  // soundPath
+  status = AddSoundPathToJson(noti_handle, &out);
+  CHECK_ERROR(status);
 
-  time_t posted_time;
-  status = GetPostedTime(noti_handle, &posted_time);
-  if (status.IsError()) return status;
-  out["postedTime"] = picojson::value(static_cast<double>(posted_time) * 1000.0);
+  // vibration
+  status = AddVibrationToJson(noti_handle, &out);
+  CHECK_ERROR(status);
 
-  status = GetText(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, &value_str);
-  if (status.IsError()) return status;
-  out["title"] = picojson::value(value_str);
+  // appControl, appId
+  status = AddAppControlInfoToJson(noti_handle, app_handle, &out);
+  CHECK_ERROR(status);
 
-  status = GetText(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, &value_str);
-  if (status.IsError()) return status;
-  if (value_str.length()) {
-    out["content"] = picojson::value(value_str);
-  }
+  // progressType, progressValue
+  status = AddProgressTypeAndValueToJson(noti_handle, noti_type_str, &out);
+  CHECK_ERROR(status);
 
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult StatusNotification::FromJson(const picojson::object& args, bool is_update,
-                                            picojson::object* out_ptr) {
+PlatformResult StatusNotification::GetNotiHandleFromJson(const picojson::value& noti_val,
+                                                         bool is_update,
+                                                         notification_h* noti_handle) {
   LoggerD("Enter");
-  picojson::object noti_obj = common::FromJson<picojson::object>(args, "notification");
-
-  const std::string& status_type = common::FromJson<std::string>(noti_obj, "statusType");
-
-  notification_type_e noti_type;
-  PlatformResult status = StatusTypeToPlatform(status_type, &noti_type);
-  if (status.IsError()) return status;
-
-  int id = NOTIFICATION_PRIV_ID_NONE;
-  int ret;
-
-  notification_h noti_handle = nullptr;
-  app_control_h app_control = NULL;
-
-  SCOPE_EXIT {
-    if (app_control) {
-      app_control_destroy(app_control);
-    }
-    notification_free(noti_handle);
-  };
-
-  if (is_update) {
-    id = std::stoi(common::FromJson<std::string>(noti_obj, "id"));
-
-    PlatformResult status = GetNotiHandle(id, &noti_handle);
-    if (status.IsError()) return status;
-
-  } else {
-    status = Create(noti_type, &noti_handle);
-    if (status.IsError()) return status;
-  }
-
-  status = SetLayout(noti_handle, status_type);
-  if (status.IsError()) {
-    return status;
-  }
+  picojson::object noti_obj = noti_val.get<picojson::object>();
 
-  picojson::value val(noti_obj);
-  if (val.contains("iconPath") && !IsNull(noti_obj, "iconPath")) {
-    const std::string& value_str = common::FromJson<std::string>(noti_obj, "iconPath");
-    std::string real_path = common::FilesystemProvider::Create().GetRealPath(value_str);
+  notification_h tmp_noti = nullptr;
+  // statusType, id
+  PlatformResult status = InitNotiFromJson(noti_obj, "statusType", is_update, &tmp_noti);
+  CHECK_ERROR(status);
+  std::unique_ptr<std::remove_pointer<notification_h>::type, int (*)(notification_h)> tmp_noti_ptr(
+      tmp_noti, &notification_free);  // automatically release the memory
 
-    status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, real_path);
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // title, content
+  status = SetCommonMembersFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-  if (val.contains("subIconPath") && !IsNull(noti_obj, "subIconPath")) {
-    const std::string& value_str = common::FromJson<std::string>(noti_obj, "subIconPath");
-    std::string real_path = common::FilesystemProvider::Create().GetRealPath(value_str);
+  // iconPath
+  status = SetPathFromJson(noti_val, NOTIFICATION_IMAGE_TYPE_ICON, "iconPath", tmp_noti);
+  CHECK_ERROR(status);
 
-    status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_SUB, real_path);
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // subIconPath
+  status = SetPathFromJson(noti_val, NOTIFICATION_IMAGE_TYPE_ICON_SUB, "subIconPath", tmp_noti);
+  CHECK_ERROR(status);
 
-  if (val.contains("number") && !IsNull(noti_obj, "number")) {
-    long number = (long)common::FromJson<double>(noti_obj, "number");
-    status = SetText(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, std::to_string(number));
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // number
+  status = SetEventsNumberFromJson(noti_val, "number", tmp_noti);
+  CHECK_ERROR(status);
 
-  if (val.contains("detailInfo") && !IsNull(noti_obj, "detailInfo")) {
-    status = SetDetailInfos(noti_handle, common::FromJson<picojson::array>(noti_obj, "detailInfo"));
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // detailInfo
+  status = SetDetailInfosFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-  if (val.contains("ledColor") && !IsNull(noti_obj, "ledColor")) {
-    status = SetLedColor(noti_handle, common::FromJson<std::string>(noti_obj, "ledColor"));
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // ledColor
+  status = SetLedColorFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-  status = SetLedOnPeriod(
-      noti_handle, static_cast<unsigned long>(common::FromJson<double>(noti_obj, "ledOnPeriod")));
-  if (status.IsError()) {
-    return status;
-  }
+  // ledOnPeriod
+  status = SetLedOnPeriodFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-  status = SetLedOffPeriod(
-      noti_handle, static_cast<unsigned long>(common::FromJson<double>(noti_obj, "ledOffPeriod")));
-  if (status.IsError()) {
-    return status;
-  }
+  // ledOffPeriod
+  status = SetLedOffPeriodFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-  if (val.contains("backgroundImagePath") && !IsNull(noti_obj, "backgroundImagePath")) {
-    const std::string& value_str = common::FromJson<std::string>(noti_obj, "backgroundImagePath");
-    std::string real_path = common::FilesystemProvider::Create().GetRealPath(value_str);
+  // backgroundImagePath
+  status = SetPathFromJson(noti_val, NOTIFICATION_IMAGE_TYPE_BACKGROUND, "backgroundImagePath",
+                           tmp_noti);
+  CHECK_ERROR(status);
 
-    status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_BACKGROUND, real_path);
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // thumbnails
+  status = SetPathsArrayFromJson(noti_val, thumbnails_map_, "thumbnails", tmp_noti);
+  CHECK_ERROR(status);
 
-  if (val.contains("thumbnails") && !IsNull(noti_obj, "thumbnails")) {
-    status = SetThumbnails(noti_handle, common::FromJson<picojson::array>(noti_obj, "thumbnails"));
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // soundPath
+  status = SetSoundPathFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-  if (val.contains("soundPath") && !IsNull(noti_obj, "soundPath")) {
-    const std::string& value_str = common::FromJson<std::string>(noti_obj, "soundPath");
-    std::string real_path = common::FilesystemProvider::Create().GetRealPath(value_str);
+  // vibration
+  status = SetVibrationFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-    status = SetSoundPath(noti_handle, real_path);
-    if (status.IsError()) {
-      return status;
-    }
-  }
+  // appControl, appId
+  status = SetAppControlInfoFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
 
-  status = SetVibration(noti_handle, common::FromJson<bool>(noti_obj, "vibration"));
-  if (status.IsError()) {
-    return status;
-  }
+  // progressType, progressValue
+  status = SetProgressTypeAndValueFromJson(noti_val, is_update, tmp_noti);
+  CHECK_ERROR(status);
 
-  status = CreateAppControl(&app_control);
-  if (status.IsError()) {
-    return status;
-  }
-
-  if (val.contains("appControl") && !IsNull(noti_obj, "appControl")) {
-    status = SetApplicationControl(app_control,
-                                   common::FromJson<picojson::object>(noti_obj, "appControl"));
-    if (status.IsError()) {
-      return status;
-    }
-  }
-
-  if (val.contains("appId") && !IsNull(noti_obj, "appId")) {
-    status = SetApplicationId(app_control, common::FromJson<std::string>(noti_obj, "appId"));
-    if (status.IsError()) {
-      return status;
-    }
-  }
-
-  const std::string& progress_type = common::FromJson<std::string>(noti_obj, "progressType");
-  status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_LIST_5, progress_type);
-  if (status.IsError()) {
-    return status;
-  }
-
-  double progressValue;
-  if (val.contains("progressValue") && !IsNull(noti_obj, "progressValue")) {
-    progressValue = common::FromJson<double>(noti_obj, "progressValue");
-  } else {
-    progressValue = -1;
-  }
-
-  status = SetProgressValue(noti_handle, progress_type, progressValue, is_update);
-
-  if (status.IsError()) {
-    return status;
-  }
-
-  status = SetText(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE,
-                   common::FromJson<std::string>(noti_obj, "title"));
-  if (status.IsError()) {
-    return status;
-  }
-
-  if (val.contains("content") && !IsNull(noti_obj, "content")) {
-    status = SetText(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT,
-                     common::FromJson<std::string>(noti_obj, "content"));
-    if (status.IsError()) {
-      return status;
-    }
-  }
-
-  status = SetAppControl(noti_handle, app_control);
-
-  if (is_update) {
-    ret = notification_update(noti_handle);
-
-  } else {
-    ret = notification_insert(noti_handle, &id);
-    if (NOTIFICATION_ERROR_NONE != ret) {
-      return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Cannot insert notification");
-    }
-  }
-  if (ret != NOTIFICATION_ERROR_NONE) {
-    return LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Post/Update notification error",
-                              ("Post/Update notification error: %d", ret));
-  }
-
-  time_t posted_time;
-  status = GetPostedTime(noti_handle, &posted_time);
-  if (status.IsError()) {
-    return status;
-  }
-
-  if (is_update) {
-    return PlatformResult(ErrorCode::NO_ERROR);
-  }
-
-  picojson::object& out = *out_ptr;
-  out["id"] = picojson::value(std::to_string(id));
-  out["postedTime"] = picojson::value(static_cast<double>(posted_time) * 1000.0);
-  out["type"] = picojson::value("STATUS");
+  *noti_handle = tmp_noti_ptr.release();
 
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+PlatformResult StatusNotification::PostStatusNotification(const picojson::object& args,
+                                                          bool is_update,
+                                                          picojson::object* out_ptr) {
+  LoggerD("Enter");
+  return PostNotification(args, is_update, out_ptr, GetNotiHandleFromJson);
+}
+
 }  // namespace notification
 }  // namespace extension
index c86784e..2c50675 100644 (file)
 #include "common/picojson.h"
 #include "common/platform_result.h"
 
+#include "common/XW_Extension.h"
+
+#include "notification/common_notification.h"
+
 namespace extension {
 namespace notification {
 
-typedef std::map<int, notification_text_type_e> InformationEnumMap;
-typedef std::map<int, notification_image_type_e> ImageEnumMap;
-
-class StatusNotification {
+class StatusNotification : public CommonNotification {
  public:
-  static common::PlatformResult ToJson(int id, notification_h noti_handle, app_control_h app_handle,
-                                       picojson::object* out_ptr);
-  static common::PlatformResult FromJson(const picojson::object& args, bool is_update,
-                                         picojson::object* out_ptr);
-  static common::PlatformResult GetAppControl(notification_h noti_handle,
-                                              app_control_h* app_control);
-  static common::PlatformResult GetNotiHandle(int id, notification_h* noti_handle);
+  XW_EXPORT static common::PlatformResult ToJson(int id, notification_h noti_handle,
+                                                 app_control_h app_handle,
+                                                 picojson::object* out_ptr);
+  XW_EXPORT static common::PlatformResult GetNotiHandleFromJson(const picojson::value& noti_val,
+                                                                bool is_update,
+                                                                notification_h* noti_handle);
+  static common::PlatformResult PostStatusNotification(const picojson::object& args, bool is_update,
+                                                       picojson::object* out_ptr);
 
  private:
   StatusNotification();
   virtual ~StatusNotification();
-
-  static const InformationEnumMap info_map_;
-  static const InformationEnumMap info_sub_map_;
-  static const ImageEnumMap thumbnails_map_;
-
-  static common::PlatformResult StatusTypeFromPlatform(notification_type_e noti_type,
-                                                       notification_ly_type_e noti_layout,
-                                                       std::string* type);
-  static common::PlatformResult StatusTypeToPlatform(const std::string& type,
-                                                     notification_type_e* noti_type);
-  static common::PlatformResult Create(notification_type_e noti_type, notification_h* noti_handle);
-  static common::PlatformResult GetImage(notification_h noti_handle,
-                                         notification_image_type_e image_type,
-                                         std::string* image_path);
-  static common::PlatformResult SetImage(notification_h noti_handle,
-                                         notification_image_type_e image_type,
-                                         const std::string& image_path);
-  static common::PlatformResult GetText(notification_h noti_handle,
-                                        notification_text_type_e text_type, std::string* noti_text);
-  static common::PlatformResult SetText(notification_h noti_handle,
-                                        notification_text_type_e text_type,
-                                        const std::string& noti_text);
-  static common::PlatformResult GetNumber(notification_h noti_handle,
-                                          notification_text_type_e text_type, long* number);
-  static common::PlatformResult GetDetailInfos(notification_h noti_handle, picojson::array* out);
-  static common::PlatformResult SetDetailInfos(notification_h noti_handle,
-                                               const picojson::array& value);
-  static common::PlatformResult GetLedColor(notification_h noti_handle, std::string* led_color);
-  static common::PlatformResult SetLedColor(notification_h noti_handle,
-                                            const std::string& led_color);
-  static common::PlatformResult GetLedPeriod(notification_h noti_handle, unsigned long* on_period,
-                                             unsigned long* off_period);
-  static common::PlatformResult SetLedOnPeriod(notification_h noti_handle, unsigned long on_period);
-  static common::PlatformResult SetLedOffPeriod(notification_h noti_handle,
-                                                unsigned long off_period);
-  static common::PlatformResult GetThumbnails(notification_h noti_handle, picojson::array* out);
-  static common::PlatformResult SetThumbnails(notification_h noti_handle,
-                                              const picojson::array& value);
-  static common::PlatformResult GetSoundPath(notification_h noti_handle, std::string* sound_path);
-  static common::PlatformResult SetSoundPath(notification_h noti_handle,
-                                             const std::string& sound_path);
-  static common::PlatformResult GetVibration(notification_h noti_handle, bool* vibration);
-  static common::PlatformResult SetVibration(notification_h noti_handle, bool vibration);
-  static common::PlatformResult GetApplicationControl(app_control_h app_handle,
-                                                      picojson::object* out_ptr);
-  static common::PlatformResult SetApplicationControl(app_control_h app_handle,
-                                                      const picojson::object& app_ctrl);
-  static common::PlatformResult GetApplicationId(app_control_h app_handle, std::string* app_id);
-  static common::PlatformResult SetApplicationId(app_control_h app_handle,
-                                                 const std::string& app_id);
-  static common::PlatformResult GetProgressValue(notification_h noti_handle,
-                                                 const std::string& progess_type,
-                                                 double* progress_value);
-  static common::PlatformResult SetProgressValue(notification_h noti_handle,
-                                                 const std::string& progress_type,
-                                                 double progress_value, bool is_update);
-  static common::PlatformResult GetPostedTime(notification_h noti_handle, time_t* posted_time);
-  static common::PlatformResult SetLayout(notification_h noti_handle, const std::string& noti_type);
-  static common::PlatformResult SetAppControl(notification_h noti_handle,
-                                              app_control_h app_control);
-  static common::PlatformResult CreateAppControl(app_control_h* app_control);
-
-  static bool IsColorFormatNumberic(const std::string& color);
 };
 
 }  // namespace notification
diff --git a/src/notification/user_notification.cc b/src/notification/user_notification.cc
new file mode 100644 (file)
index 0000000..1a73a2f
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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 "notification/user_notification.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+namespace extension {
+namespace notification {
+
+using namespace common;
+
+UserNotification::UserNotification() {
+}
+
+UserNotification::~UserNotification() {
+}
+
+PlatformResult UserNotification::ToJson(int id, notification_h noti_handle,
+                                        app_control_h app_handle, picojson::object* out_ptr) {
+  LoggerD("Enter");
+  PlatformResult ret = AddCommonMembersToJson(id, noti_handle, out_ptr);
+  CHECK_ERROR(ret);
+
+  std::string noti_type_str;
+  ret = AddTypeToJson(noti_handle, "userType", out_ptr, &noti_type_str);
+  CHECK_ERROR(ret);
+
+  ret = AddTextContentsToJson(noti_handle, noti_type_str, out_ptr);
+  CHECK_ERROR(ret);
+
+  ret = AddImagesToJson(noti_handle, out_ptr);
+  CHECK_ERROR(ret);
+
+  ret = AddThumbnailsToJson(noti_handle, out_ptr);
+  CHECK_ERROR(ret);
+
+  ret = AddActionsToJson(noti_handle, app_handle, out_ptr);
+  CHECK_ERROR(ret);
+
+  ret = AddGroupContentsToJson(noti_handle, out_ptr);
+  CHECK_ERROR(ret);
+
+  ret = AddLedsToJson(noti_handle, out_ptr);
+  CHECK_ERROR(ret);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::GetNotiHandleFromJson(const picojson::value& noti_val,
+                                                       bool is_update,
+                                                       notification_h* noti_handle) {
+  LoggerD("Enter");
+  picojson::object noti_obj = noti_val.get<picojson::object>();
+
+  notification_h tmp_noti = nullptr;
+  PlatformResult status = InitNotiFromJson(noti_obj, "userType", is_update, &tmp_noti);
+  CHECK_ERROR(status);
+  std::unique_ptr<std::remove_pointer<notification_h>::type, int (*)(notification_h)> tmp_noti_ptr(
+      tmp_noti, &notification_free);  // automatically release the memory
+
+  status = SetCommonMembersFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
+
+  status = SetTextContentsFromJson(noti_val, is_update, tmp_noti);
+  CHECK_ERROR(status);
+
+  status = SetImagesFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
+
+  status = SetThumbnailsFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
+
+  status = SetActionsFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
+
+  status = SetGroupContentsFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
+
+  status = SetLedsFromJson(noti_val, tmp_noti);
+  CHECK_ERROR(status);
+
+  *noti_handle = tmp_noti_ptr.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::PostUserNotification(const picojson::object& args, bool is_update,
+                                                      picojson::object* out_ptr) {
+  LoggerD("Enter");
+  return PostNotification(args, is_update, out_ptr, GetNotiHandleFromJson);
+}
+
+PlatformResult UserNotification::AddTextContentsToJson(notification_h noti_handle,
+                                                       std::string noti_type_str,
+                                                       picojson::object* out_ptr) {
+  LoggerD("Enter");
+
+  picojson::value text_contents = picojson::value(picojson::object());
+  picojson::object& text_contents_obj = text_contents.get<picojson::object>();
+
+  // progressType, progressValue
+  PlatformResult status =
+      AddProgressTypeAndValueToJson(noti_handle, noti_type_str, &text_contents_obj);
+  CHECK_ERROR(status);
+
+  // eventsNumber
+  status = AddEventsNumberToJson(noti_handle, "eventsNumber", &text_contents_obj);
+  CHECK_ERROR(status);
+
+  // detailInfo
+  status = AddDetailInfosToJson(noti_handle, &text_contents_obj);
+  CHECK_ERROR(status);
+
+  // buttonsTexts
+  status = AddTextsArrayToJson(noti_handle, buttons_texts_map_, "buttonsTexts", &text_contents_obj);
+  CHECK_ERROR(status);
+
+  // contentForOff
+  status = AddTextToJson(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF,
+                         "contentForOff", &text_contents_obj);
+  CHECK_ERROR(status);
+
+  (*out_ptr)["textContents"] = text_contents;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::AddImagesToJson(notification_h noti_handle,
+                                                 picojson::object* out_ptr) {
+  LoggerD("Enter");
+
+  picojson::value images_contents = picojson::value(picojson::object());
+  picojson::object& images_contents_obj = images_contents.get<picojson::object>();
+
+  // iconPath
+  PlatformResult status =
+      AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, "iconPath", &images_contents_obj);
+  CHECK_ERROR(status);
+
+  // subIconPath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_SUB, "subIconPath",
+                         &images_contents_obj);
+  CHECK_ERROR(status);
+
+  // indicatorIconPath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR,
+                         "indicatorIconPath", &images_contents_obj);
+  CHECK_ERROR(status);
+
+  // lockScreenIconPath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_FOR_LOCK, "lockScreenIconPath",
+                         &images_contents_obj);
+  CHECK_ERROR(status);
+
+  // buttonIconPaths
+  status = AddPathsArrayToJson(noti_handle, buttons_icon_paths_map_, "buttonIconPaths",
+                               &images_contents_obj);
+  CHECK_ERROR(status);
+
+  // backgroundImagePath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_BACKGROUND, "backgroundImagePath",
+                         &images_contents_obj);
+  CHECK_ERROR(status);
+
+  (*out_ptr)["images"] = images_contents;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::AddThumbnailsToJson(notification_h noti_handle,
+                                                     picojson::object* out_ptr) {
+  LoggerD("Enter");
+
+  picojson::value thumbnails_contents = picojson::value(picojson::object());
+  picojson::object& thumbnails_contents_obj = thumbnails_contents.get<picojson::object>();
+
+  // lockScreenThumbnailIconPath
+  PlatformResult status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_THUMBNAIL_FOR_LOCK,
+                                        "lockScreenThumbnailIconPath", &thumbnails_contents_obj);
+  CHECK_ERROR(status);
+
+  // thumbnailIconPath
+  status = AddPathToJson(noti_handle, NOTIFICATION_IMAGE_TYPE_THUMBNAIL, "thumbnailIconPath",
+                         &thumbnails_contents_obj);
+  CHECK_ERROR(status);
+
+  // thumbnails
+  status =
+      AddPathsArrayToJson(noti_handle, thumbnails_map_, "thumbnails", &thumbnails_contents_obj);
+  CHECK_ERROR(status);
+
+  (*out_ptr)["thumbnails"] = thumbnails_contents;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::AddActionsToJson(notification_h noti_handle,
+                                                  app_control_h app_handle,
+                                                  picojson::object* out_ptr) {
+  LoggerD("Enter");
+
+  picojson::value actions_contents = picojson::value(picojson::object());
+  picojson::object& actions_contents_obj = actions_contents.get<picojson::object>();
+
+  // soundPath
+  PlatformResult status = AddSoundPathToJson(noti_handle, &actions_contents_obj);
+  CHECK_ERROR(status);
+
+  // vibration
+  status = AddVibrationToJson(noti_handle, &actions_contents_obj);
+  CHECK_ERROR(status);
+
+  // appControl, appId
+  status = AddAppControlInfoToJson(noti_handle, app_handle, &actions_contents_obj);
+  CHECK_ERROR(status);
+
+  (*out_ptr)["actions"] = actions_contents;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::AddGroupContentsToJson(notification_h noti_handle,
+                                                        picojson::object* out_ptr) {
+  LoggerD("Enter");
+
+  picojson::value group_contents = picojson::value(picojson::object());
+  picojson::object& group_contents_obj = group_contents.get<picojson::object>();
+
+  // groupTitle
+  PlatformResult status = AddTextToJson(noti_handle, NOTIFICATION_TEXT_TYPE_GROUP_TITLE,
+                                        "groupTitle", &group_contents_obj);
+  CHECK_ERROR(status);
+
+  // groupContent
+  status = AddTextToJson(noti_handle, NOTIFICATION_TEXT_TYPE_GROUP_CONTENT, "groupContent",
+                         &group_contents_obj);
+  CHECK_ERROR(status);
+
+  // groupContentForOff
+  status =
+      AddTextToJson(noti_handle, NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF,
+                    "groupContentForOff", &group_contents_obj);
+  CHECK_ERROR(status);
+
+  (*out_ptr)["groupContents"] = group_contents;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::AddLedsToJson(notification_h noti_handle,
+                                               picojson::object* out_ptr) {
+  LoggerD("Enter");
+
+  picojson::value leds_contents = picojson::value(picojson::object());
+  picojson::object& leds_contents_obj = leds_contents.get<picojson::object>();
+
+  // ledColor
+  PlatformResult status = AddLedColorToJson(noti_handle, &leds_contents_obj);
+  CHECK_ERROR(status);
+
+  // ledOnPeriod, ledOffPeriod
+  status = AddLedOnOffPeriodToJson(noti_handle, &leds_contents_obj);
+  CHECK_ERROR(status);
+
+  (*out_ptr)["leds"] = leds_contents;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::SetTextContentsFromJson(const picojson::value& noti_value,
+                                                         bool is_update,
+                                                         notification_h noti_handle) {
+  LoggerD("Enter");
+  if (noti_value.contains("textContents") &&
+      noti_value.get("textContents").is<picojson::object>()) {
+    LoggerD("nullable member textContents is present - parsing it");
+    const picojson::value& text_contents_value = noti_value.get("textContents");
+
+    // progressType, progressValue
+    PlatformResult status =
+        SetProgressTypeAndValueFromJson(text_contents_value, is_update, noti_handle);
+    CHECK_ERROR(status);
+
+    // eventsNumber
+    status = SetEventsNumberFromJson(text_contents_value, "eventsNumber", noti_handle);
+    CHECK_ERROR(status);
+
+    // detailInfo
+    status = SetDetailInfosFromJson(text_contents_value, noti_handle);
+    CHECK_ERROR(status);
+
+    // buttonsTexts
+    status =
+        SetTextsArrayFromJson(text_contents_value, buttons_texts_map_, "buttonsTexts", noti_handle);
+    CHECK_ERROR(status);
+
+    // contentForOff
+    status = SetTextFromJson(text_contents_value,
+                             NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF,
+                             "contentForOff", noti_handle);
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::SetImagesFromJson(const picojson::value& noti_value,
+                                                   notification_h noti_handle) {
+  LoggerD("Enter");
+  if (noti_value.contains("images") && noti_value.get("images").is<picojson::object>()) {
+    LoggerD("nullable member images is present - parsing it");
+    const picojson::value& images_value = noti_value.get("images");
+
+    // iconPath
+    PlatformResult status =
+        SetPathFromJson(images_value, NOTIFICATION_IMAGE_TYPE_ICON, "iconPath", noti_handle);
+    CHECK_ERROR(status);
+
+    // subIconPath
+    status =
+        SetPathFromJson(images_value, NOTIFICATION_IMAGE_TYPE_ICON_SUB, "subIconPath", noti_handle);
+    CHECK_ERROR(status);
+
+    // indicatorIconPath
+    status = SetPathFromJson(images_value, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR,
+                             "indicatorIconPath", noti_handle);
+    CHECK_ERROR(status);
+
+    // lockScreenIconPath
+    status = SetPathFromJson(images_value, NOTIFICATION_IMAGE_TYPE_ICON_FOR_LOCK,
+                             "lockScreenIconPath", noti_handle);
+    CHECK_ERROR(status);
+
+    // buttonIconPaths
+    status = SetPathsArrayFromJson(images_value, buttons_icon_paths_map_, "buttonIconPaths",
+                                   noti_handle);
+    CHECK_ERROR(status);
+
+    // backgroundImagePath
+    status = SetPathFromJson(images_value, NOTIFICATION_IMAGE_TYPE_BACKGROUND,
+                             "backgroundImagePath", noti_handle);
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::SetThumbnailsFromJson(const picojson::value& noti_value,
+                                                       notification_h noti_handle) {
+  LoggerD("Enter");
+
+  if (noti_value.contains("thumbnails") && noti_value.get("thumbnails").is<picojson::object>()) {
+    LoggerD("nullable member thumbnails is present - parsing it");
+    const picojson::value& thumbnails_value = noti_value.get("thumbnails");
+
+    // lockScreenThumbnailIconPath
+    PlatformResult status =
+        SetPathFromJson(thumbnails_value, NOTIFICATION_IMAGE_TYPE_THUMBNAIL_FOR_LOCK,
+                        "lockScreenThumbnailIconPath", noti_handle);
+    CHECK_ERROR(status);
+
+    // thumbnailIconPath
+    status = SetPathFromJson(thumbnails_value, NOTIFICATION_IMAGE_TYPE_THUMBNAIL,
+                             "thumbnailIconPath", noti_handle);
+    CHECK_ERROR(status);
+
+    // thumbnails
+    status = SetPathsArrayFromJson(thumbnails_value, thumbnails_map_, "thumbnails", noti_handle);
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::SetActionsFromJson(const picojson::value& noti_value,
+                                                    notification_h noti_handle) {
+  LoggerD("Enter");
+
+  if (noti_value.contains("actions") && noti_value.get("actions").is<picojson::object>()) {
+    LoggerD("nullable member actions is present - parsing it");
+    const picojson::value& actions_value = noti_value.get("actions");
+
+    // soundPath
+    PlatformResult status = SetSoundPathFromJson(actions_value, noti_handle);
+    CHECK_ERROR(status);
+
+    // vibration
+    status = SetVibrationFromJson(actions_value, noti_handle);
+    CHECK_ERROR(status);
+
+    // appControl, appId
+    status = SetAppControlInfoFromJson(actions_value, noti_handle);
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::SetGroupContentsFromJson(const picojson::value& noti_value,
+                                                          notification_h noti_handle) {
+  LoggerD("Enter");
+
+  if (noti_value.contains("groupContents") &&
+      noti_value.get("groupContents").is<picojson::object>()) {
+    LoggerD("nullable member groupContents is present - parsing it");
+    const picojson::value& group_contents_value = noti_value.get("groupContents");
+
+    // groupTitle
+    PlatformResult status = SetTextFromJson(
+        group_contents_value, NOTIFICATION_TEXT_TYPE_GROUP_TITLE, "groupTitle", noti_handle);
+    CHECK_ERROR(status);
+
+    // groupContent
+    status = SetTextFromJson(group_contents_value, NOTIFICATION_TEXT_TYPE_GROUP_CONTENT,
+                             "groupContent", noti_handle);
+    CHECK_ERROR(status);
+
+    // groupContentForOff
+    status = SetTextFromJson(group_contents_value,
+                             NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF,
+                             "groupContentForOff", noti_handle);
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UserNotification::SetLedsFromJson(const picojson::value& noti_value,
+                                                 notification_h noti_handle) {
+  LoggerD("Enter");
+
+  if (noti_value.contains("leds") && noti_value.get("leds").is<picojson::object>()) {
+    LoggerD("nullable member leds is present - parsing it");
+    const picojson::value& leds_value = noti_value.get("leds");
+
+    // ledColor
+    PlatformResult status = SetLedColorFromJson(leds_value, noti_handle);
+    CHECK_ERROR(status);
+
+    // ledOnPeriod
+    status = SetLedOnPeriodFromJson(leds_value, noti_handle);
+    CHECK_ERROR(status);
+
+    // ledOffPeriod
+    status = SetLedOffPeriodFromJson(leds_value, noti_handle);
+    CHECK_ERROR(status);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace notification
+}  // namespace extension
diff --git a/src/notification/user_notification.h b/src/notification/user_notification.h
new file mode 100644 (file)
index 0000000..86f1c9c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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 NOTIFICATION_USER_NOTIFICATION_H_
+#define NOTIFICATION_USER_NOTIFICATION_H_
+
+#include "notification/common_notification.h"
+
+namespace extension {
+namespace notification {
+
+class UserNotification : public CommonNotification {
+ public:
+  XW_EXPORT static common::PlatformResult ToJson(int id, notification_h noti_handle,
+                                                 app_control_h app_handle,
+                                                 picojson::object* out_ptr);
+  XW_EXPORT static common::PlatformResult GetNotiHandleFromJson(const picojson::value& noti_val,
+                                                                bool is_update,
+                                                                notification_h* noti_handle);
+  static common::PlatformResult PostUserNotification(const picojson::object& args, bool is_update,
+                                                     picojson::object* out_ptr);
+
+  static common::PlatformResult AddTextContentsToJson(notification_h noti_handle,
+                                                      std::string noti_type_str,
+                                                      picojson::object* out_ptr);
+  static common::PlatformResult AddImagesToJson(notification_h noti_handle,
+                                                picojson::object* out_ptr);
+  static common::PlatformResult AddThumbnailsToJson(notification_h noti_handle,
+                                                    picojson::object* out_ptr);
+  static common::PlatformResult AddActionsToJson(notification_h noti_handle,
+                                                 app_control_h app_handle,
+                                                 picojson::object* out_ptr);
+  static common::PlatformResult AddGroupContentsToJson(notification_h noti_handle,
+                                                       picojson::object* out_ptr);
+  static common::PlatformResult AddLedsToJson(notification_h noti_handle,
+                                              picojson::object* out_ptr);
+
+  static common::PlatformResult SetTextContentsFromJson(const picojson::value& noti_val,
+                                                        bool is_update, notification_h noti_handle);
+  static common::PlatformResult SetImagesFromJson(const picojson::value& noti_val,
+                                                  notification_h noti_handle);
+  static common::PlatformResult SetThumbnailsFromJson(const picojson::value& noti_val,
+                                                      notification_h noti_handle);
+  static common::PlatformResult SetActionsFromJson(const picojson::value& noti_val,
+                                                   notification_h noti_handle);
+  static common::PlatformResult SetGroupContentsFromJson(const picojson::value& noti_val,
+                                                         notification_h noti_handle);
+  static common::PlatformResult SetLedsFromJson(const picojson::value& noti_val,
+                                                notification_h noti_handle);
+
+ private:
+  UserNotification();
+  virtual ~UserNotification();
+};
+
+}  // namespace notification
+}  // namespace extension
+
+#endif /* NOTIFICATION_USER_NOTIFICATION_H_ */
index 8b6c10f..cb3ff35 100755 (executable)
@@ -25,7 +25,6 @@
           'variables': {
             'packages': [
               'capi-system-device',
-              'deviced',
               'vconf',
             ]
           },
index 0b5161b..eedd0f4 100644 (file)
@@ -22,7 +22,7 @@
         ['tizen == 1', {
           'variables': {
             'packages': [
-              'capi-appfw-application',
+              'capi-appfw-preference',
             ]
           },
         }],
index 5cdb2ad..6028465 100644 (file)
@@ -28,7 +28,7 @@
           'variables': {
             'packages': [
               'push',
-              'capi-appfw-application',
+              'capi-appfw-app-control',
               'libpcrecpp',
             ]
           },
index 8c34e33..fa12d49 100755 (executable)
@@ -33,7 +33,10 @@ var SensorType = {
     GRAVITY : 'GRAVITY',
     GYROSCOPE : 'GYROSCOPE',
     GYROSCOPE_ROTATION_VECTOR : 'GYROSCOPE_ROTATION_VECTOR',
-    LINEAR_ACCELERATION : 'LINEAR_ACCELERATION'
+    LINEAR_ACCELERATION : 'LINEAR_ACCELERATION',
+    MAGNETIC_UNCALIBRATED : 'MAGNETIC_UNCALIBRATED',
+    GYROSCOPE_UNCALIBRATED : 'GYROSCOPE_UNCALIBRATED',
+    ACCELERATION : 'ACCELERATION'
 };
 
 var ProximityState = {
@@ -165,7 +168,10 @@ var _sensorListeners = {
     'GRAVITY'     : {},
     'GYROSCOPE'   : {},
     'GYROSCOPE_ROTATION_VECTOR' : {},
-    'LINEAR_ACCELERATION' : {}
+    'LINEAR_ACCELERATION' : {},
+    'MAGNETIC_UNCALIBRATED' : {},
+    'GYROSCOPE_UNCALIBRATED' : {},
+    'ACCELERATION' : {}
 };
 
 var errorWrapper = function (err) {
@@ -235,6 +241,12 @@ function getDefaultSensor() {
         return new GyroscopeRotationVectorSensor();
     } else if (_supportedSensors[index] === SensorType.LINEAR_ACCELERATION){
         return new LinearAccelerationSensor();
+    } else if (_supportedSensors[index] === SensorType.MAGNETIC_UNCALIBRATED) {
+        return new MagneticUncalibratedSensor();
+    } else if (_supportedSensors[index] === SensorType.GYROSCOPE_UNCALIBRATED) {
+        return new GyroscopeUncalibratedSensor();
+    } else if (_supportedSensors[index] === SensorType.ACCELERATION) {
+        return new AccelerationSensor();
     }
 };
 
@@ -607,6 +619,83 @@ LinearAccelerationSensor.prototype.getLinearAccelerationSensorData = function()
     _sensorListeners[this.sensorType].getData(args.successCallback, errorWrapper.bind(args));
 };
 
+//// MagneticUncalibratedSensor
+var MagneticUncalibratedSensor = function(data) {
+    Sensor.call(this, SensorType.MAGNETIC_UNCALIBRATED);
+};
+
+MagneticUncalibratedSensor.prototype = new Sensor();
+
+MagneticUncalibratedSensor.prototype.constructor = Sensor;
+
+MagneticUncalibratedSensor.prototype.getMagneticUncalibratedSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'successCallback',
+            type : types_.FUNCTION
+        },
+        {
+            name : 'errorCallback',
+            type : types_.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, errorWrapper.bind(args));
+};
+
+//// GyroscopeUncalibratedSensor
+var GyroscopeUncalibratedSensor = function(data) {
+    Sensor.call(this, SensorType.GYROSCOPE_UNCALIBRATED);
+};
+
+GyroscopeUncalibratedSensor.prototype = new Sensor();
+
+GyroscopeUncalibratedSensor.prototype.constructor = Sensor;
+
+GyroscopeUncalibratedSensor.prototype.getGyroscopeUncalibratedSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'successCallback',
+            type : types_.FUNCTION
+        },
+        {
+            name : 'errorCallback',
+            type : types_.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, errorWrapper.bind(args));
+};
+
+//// AccelerationSensor
+var AccelerationSensor = function(data) {
+    Sensor.call(this, SensorType.ACCELERATION);
+};
+
+AccelerationSensor.prototype = new Sensor();
+
+AccelerationSensor.prototype.constructor = Sensor;
+
+AccelerationSensor.prototype.getAccelerationSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, errorWrapper.bind(args));
+};
 
 ////////////////////// Sensor Data classes/////////////////////////////////////////////////////
 ////Base SensorData class
@@ -778,6 +867,63 @@ SensorLinearAccelerationData.prototype.constructor = SensorData;
 _sensorListeners[SensorType.LINEAR_ACCELERATION] = new SensorListener(SensorType.LINEAR_ACCELERATION,
         SensorLinearAccelerationData);
 
+//// SensorMagneticUncalibratedData
+var SensorMagneticUncalibratedData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        x : {value: data.x, writable: false, enumerable: true},
+        y : {value: data.y, writable: false, enumerable: true},
+        z : {value: data.z, writable: false, enumerable: true},
+        xAxisBias : {value: data.xAxisBias, writable: false, enumerable: true},
+        yAxisBias : {value: data.yAxisBias, writable: false, enumerable: true},
+        zAxisBias : {value: data.zAxisBias, writable: false, enumerable: true}
+    });
+};
+
+SensorMagneticUncalibratedData.prototype = new SensorData();
+
+SensorMagneticUncalibratedData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.MAGNETIC_UNCALIBRATED] = new SensorListener(SensorType.MAGNETIC_UNCALIBRATED,
+    SensorMagneticUncalibratedData);
+
+//// SensorGyroscopeUncalibratedData
+var SensorGyroscopeUncalibratedData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        x : {value: data.x, writable: false, enumerable: true},
+        y : {value: data.y, writable: false, enumerable: true},
+        z : {value: data.z, writable: false, enumerable: true},
+        xAxisDrift : {value: data.xAxisDrift, writable: false, enumerable: true},
+        yAxisDrift : {value: data.yAxisDrift, writable: false, enumerable: true},
+        zAxisDrift : {value: data.zAxisDrift, writable: false, enumerable: true}
+    });
+
+};
+
+SensorGyroscopeUncalibratedData.prototype = new SensorData();
+
+SensorGyroscopeUncalibratedData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.GYROSCOPE_UNCALIBRATED] = new SensorListener(SensorType.GYROSCOPE_UNCALIBRATED,
+    SensorGyroscopeUncalibratedData);
+
+//// SensorAccelerationData
+var SensorAccelerationData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        x : {value: data.x, writable: false, enumerable: true},
+        y : {value: data.y, writable: false, enumerable: true},
+        z : {value: data.z, writable: false, enumerable: true},
+    });
+};
+
+SensorAccelerationData.prototype = new SensorData();
+
+SensorAccelerationData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.ACCELERATION] = new SensorListener(SensorType.ACCELERATION,
+        SensorAccelerationData);
 
 //////////////////////SensorHardwareInfo classes//////////////////////////////////////////////////////////
 function SensorHardwareInfo(data) {
index 95ebae2..28a1951 100644 (file)
@@ -128,6 +128,30 @@ void ReportSensorData(sensor_type_e sensor_type, sensor_event_s* sensor_event,
       (*out)["z"] = picojson::value(static_cast<double>(sensor_event->values[2]));
       break;
     }
+    case SENSOR_GEOMAGNETIC_UNCALIBRATED: {
+      (*out)["x"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      (*out)["y"] = picojson::value(static_cast<double>(sensor_event->values[1]));
+      (*out)["z"] = picojson::value(static_cast<double>(sensor_event->values[2]));
+      (*out)["xAxisBias"] = picojson::value(static_cast<double>(sensor_event->values[3]));
+      (*out)["yAxisBias"] = picojson::value(static_cast<double>(sensor_event->values[4]));
+      (*out)["zAxisBias"] = picojson::value(static_cast<double>(sensor_event->values[5]));
+      break;
+    }
+    case SENSOR_GYROSCOPE_UNCALIBRATED: {
+      (*out)["x"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      (*out)["y"] = picojson::value(static_cast<double>(sensor_event->values[1]));
+      (*out)["z"] = picojson::value(static_cast<double>(sensor_event->values[2]));
+      (*out)["xAxisDrift"] = picojson::value(static_cast<double>(sensor_event->values[3]));
+      (*out)["yAxisDrift"] = picojson::value(static_cast<double>(sensor_event->values[4]));
+      (*out)["zAxisDrift"] = picojson::value(static_cast<double>(sensor_event->values[5]));
+      break;
+    }
+    case SENSOR_ACCELEROMETER: {
+      (*out)["x"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      (*out)["y"] = picojson::value(static_cast<double>(sensor_event->values[1]));
+      (*out)["z"] = picojson::value(static_cast<double>(sensor_event->values[2]));
+      break;
+    }
     default: {
       LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unsupported type"), out);
       return;
@@ -816,6 +840,9 @@ SensorService::SensorService(SensorInstance& instance) : instance_(instance) {
   AddSensor(
       new SensorData(instance, SENSOR_GYROSCOPE_ROTATION_VECTOR, "GYROSCOPE_ROTATION_VECTOR", 4));
   AddSensor(new SensorData(instance, SENSOR_LINEAR_ACCELERATION, "LINEAR_ACCELERATION", 3));
+  AddSensor(new SensorData(instance, SENSOR_GEOMAGNETIC_UNCALIBRATED, "MAGNETIC_UNCALIBRATED", 6));
+  AddSensor(new SensorData(instance, SENSOR_GYROSCOPE_UNCALIBRATED, "GYROSCOPE_UNCALIBRATED", 6));
+  AddSensor(new SensorData(instance, SENSOR_ACCELEROMETER, "ACCELERATION", 3));
 }
 
 SensorService::~SensorService() {
index ae9d39f..5822c00 100644 (file)
@@ -47,9 +47,6 @@
             ]
           },
         }],
-        ['tizen_is_emulator == 1', {
-          'defines': ['TIZEN_IS_EMULATOR'],
-        }],
       ],
     },
   ],
index 63b3e5e..90e370f 100644 (file)
@@ -424,6 +424,16 @@ function SystemInfoBattery(data) {
             value : data.isCharging,
             writable : false,
             enumerable : true
+        },
+        timeToDischarge : {
+            value : data.timeToDischarge,
+            writable : false,
+            enumerable : true
+        },
+        timeToFullCharge : {
+            value : data.timeToFullCharge,
+            writable : false,
+            enumerable : true
         }
     });
 }
index ad3a61a..c192912 100644 (file)
@@ -62,6 +62,7 @@ const char* kPlatformCoreSse3 = "sse3";
 const char* kPlatformCoreSsse3 = "ssse3";
 const char* kPlatformCoreVfpv2 = "vfpv2";
 const char* kPlatformCoreVfpv3 = "vfpv3";
+const char* kPlatformCoreVfpv4 = "vfpv4";
 
 /*API feature*/
 /*Network feature*/
@@ -521,6 +522,17 @@ PlatformResult SystemInfoDeviceCapability::GetPlatfomCoreFpuArch(std::string* re
     }
     result += kPlatformCoreVfpv3;
   }
+
+  ret = GetValueBool("tizen.org/feature/platform.core.fpu.arch.vfpv4", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!result.empty()) {
+      result += kPlatformCoreDelimiter;
+    }
+    result += kPlatformCoreVfpv4;
+  }
   if (result.empty()) {
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "platformCoreFpuArch result is empty");
   }
@@ -569,17 +581,40 @@ bool SystemInfoDeviceCapability::IsScreen() {
   return true;
 }
 
+#define MODEL_NAME "http://tizen.org/system/model_name"
+#define MODEL_EMULATOR "Emulator"
+bool _is_emulator(void) {
+  int ret;
+  char* model_name = NULL;
+  static bool emul = false;
+  static int set = 0;
+
+  if (set) return emul;
+
+  ret = system_info_get_platform_string(MODEL_NAME, &model_name);
+  if (ret < 0) {
+    LoggerD("Cannot get model name(%d)", ret);
+    return emul;
+  }
+
+  if (!strncmp(MODEL_EMULATOR, model_name, strlen(model_name) + 1)) emul = true;
+
+  set = 1;
+  free(model_name);
+
+  return emul;
+}
+
 PlatformResult SystemInfoDeviceCapability::GetPlatformCoreCpuFrequency(int* return_value) {
   LoggerD("Entered");
 
   std::string freq;
   std::string file_name;
 
-#ifdef TIZEN_IS_EMULATOR
-  file_name = "/proc/cpuinfo";
-#else
-  file_name = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
-#endif
+  if (_is_emulator())
+    file_name = "/proc/cpuinfo";
+  else
+    file_name = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
 
   std::ifstream cpuinfo_freq(file_name);
   if (!cpuinfo_freq.is_open()) {
@@ -587,24 +622,24 @@ PlatformResult SystemInfoDeviceCapability::GetPlatformCoreCpuFrequency(int* retu
                               ("Failed to get cpu frequency"));
   }
 
-#ifdef TIZEN_IS_EMULATOR
-  // get frequency value from cpuinfo file
-  // example entry for frequency looks like below
-  // cpu MHz   : 3392.046
-  std::size_t found;
-  do {
-    getline(cpuinfo_freq, freq);
-    found = freq.find("cpu MHz");
-  } while (std::string::npos == found && !cpuinfo_freq.eof());
+  if (_is_emulator()) {
+    // get frequency value from cpuinfo file
+    // example entry for frequency looks like below
+    // cpu MHz   : 3392.046
+    std::size_t found;
+    do {
+      getline(cpuinfo_freq, freq);
+      found = freq.find("cpu MHz");
+    } while (std::string::npos == found && !cpuinfo_freq.eof());
 
-  found = freq.find(":");
-  if (std::string::npos != found) {
-    *return_value = std::stoi(freq.substr(found + 2));
+    found = freq.find(":");
+    if (std::string::npos != found) {
+      *return_value = std::stoi(freq.substr(found + 2));
+    }
+  } else {
+    getline(cpuinfo_freq, freq);
+    *return_value = std::stoi(freq) / 1000;  // unit: MHz
   }
-#else
-  getline(cpuinfo_freq, freq);
-  *return_value = std::stoi(freq) / 1000;  // unit: MHz
-#endif
 
   cpuinfo_freq.close();
   LoggerD("cpu frequency : %d", *return_value);
index 5a495b5..ec0218a 100644 (file)
@@ -27,6 +27,7 @@
 #include <vconf-internal-keys.h>
 #include <vconf.h>
 
+#include "common/GDBus/connection.h"
 #include "common/filesystem/filesystem_provider.h"
 #include "common/scope_exit.h"
 #include "systeminfo/systeminfo-utils.h"
@@ -46,6 +47,11 @@ const double kDisplayInchToMillimeter = 25.4;
 // Battery
 const double kRemainingBatteryChargeMax = 100.0;
 const int kVconfErrorNone = 0;
+const char* kBatteryTarget = "org.tizen.resourced";
+const char* kBatteryObject = "/Org/Tizen/ResourceD/Logging";
+const char* kBatteryInterface = "org.tizen.resourced.logging";
+const char* kBatteryGetBatteryChargingTime = "GetBatteryChargingTime";
+const char* kBatteryGetBatteryRemainingTime = "GetBatteryRemainingTime";
 // Display
 const double kDisplayBrightnessDivideValue = 100;
 // Device Orientation
@@ -208,7 +214,51 @@ PlatformResult SysteminfoPropertiesManager::ReportBattery(picojson::object* out)
     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, (log_msg + std::to_string(ret)),
                               ("vconf_get_int error: %d (%s)", ret, get_error_message(ret)));
   }
-  out->insert(std::make_pair("isCharging", picojson::value(0 != value)));
+  bool isCharging = (0 != value);
+  out->insert(std::make_pair("isCharging", picojson::value(isCharging)));
+
+  if (nullptr == common::dbus::Connection::getInstance().getDBus()) {
+    return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "dbus wasn't initialized");
+  }
+
+  GError* error = nullptr;
+  GVariant* variant = nullptr;
+  if (isCharging) {
+    variant = g_dbus_connection_call_sync(common::dbus::Connection::getInstance().getDBus(),
+                                          kBatteryTarget, kBatteryObject, kBatteryInterface,
+                                          kBatteryGetBatteryChargingTime, g_variant_new("()"), NULL,
+                                          G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+  } else {
+    variant = g_dbus_connection_call_sync(common::dbus::Connection::getInstance().getDBus(),
+                                          kBatteryTarget, kBatteryObject, kBatteryInterface,
+                                          kBatteryGetBatteryRemainingTime,
+                                          g_variant_new("(i)", 0),  // 0 - POWER_NORMAL_MODE
+                                          NULL,                     // 1 - POWER_SAVING_MODE
+                                          G_DBUS_CALL_FLAGS_NONE,   // 2 - ULTRA_SAVING_MODE
+                                          -1,                       // for now, only 0 is supported
+                                          NULL, &error);
+  }
+
+  if (!variant || error) {
+    std::string message = error ? error->message : "";
+    g_error_free(error);
+    return LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "DBus returned error",
+        ("Failed to call %s method - %s",
+         isCharging ? "GetBatteryChargingTime" : "GetBatteryRemainingTime", message.c_str()));
+  } else {
+    int time = 0;
+    g_variant_get(variant, "(i)", &time);
+    g_variant_unref(variant);
+    if (isCharging) {
+      out->insert(std::make_pair("timeToFullCharge", picojson::value(static_cast<double>(time))));
+      out->insert(std::make_pair("timeToDischarge", picojson::value()));
+    } else {
+      out->insert(std::make_pair("timeToFullCharge", picojson::value()));
+      out->insert(std::make_pair("timeToDischarge", picojson::value(static_cast<double>(time))));
+    }
+  }
+
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
index 51e9104..07dfedb 100644 (file)
@@ -149,6 +149,8 @@ Utils.prototype.error = console.error.bind(console);
 Utils.prototype.warn = console.warn.bind(console);
 Utils.prototype.log = _enableJsLogs ? console.log.bind(console) : function(){};
 
+Utils.prototype.global = _global;
+
 Utils.prototype.repackFilter = function(filter) {
   if (filter instanceof tizen.AttributeFilter) {
     return {