55#include " platform_channel.h"
66
77#include < app.h>
8+ #include < feedback.h>
89
910#include < map>
1011
@@ -28,6 +29,146 @@ PlatformChannel::PlatformChannel(flutter::BinaryMessenger* messenger,
2829
2930PlatformChannel::~PlatformChannel () {}
3031
32+ namespace {
33+
34+ class FeedbackManager {
35+ public:
36+ enum class ResultCode {
37+ kOk ,
38+ kNotSupportedError ,
39+ kPermissionDeniedError ,
40+ kUnknownError
41+ };
42+
43+ static std::string GetVibrateVariantName (const char * haptic_feedback_type) {
44+ FT_LOGD (
45+ " Enter FeedbackManager::GetVibrateVariantName(): haptic_feedback_type: "
46+ " (%s)" ,
47+ haptic_feedback_type);
48+
49+ if (!haptic_feedback_type) {
50+ return " HapticFeedback.vibrate" ;
51+ }
52+
53+ const size_t kPrefixToRemoveLen = strlen (" HapticFeedbackType." );
54+
55+ assert (strlen (haptic_feedback_type) >= kPrefixToRemoveLen );
56+
57+ const std::string kHapticFeedbackPrefix = " HapticFeedback." ;
58+
59+ return kHapticFeedbackPrefix +
60+ std::string{haptic_feedback_type + kPrefixToRemoveLen };
61+ }
62+
63+ static std::string GetErrorMessage (const std::string& method_name,
64+ ResultCode result_code) {
65+ FT_LOGD (
66+ " Enter FeedbackManager::GetErrorMessage(): method_name: (%s), "
67+ " result_code: [%d]" ,
68+ method_name.c_str (), static_cast <int >(result_code));
69+
70+ switch (result_code) {
71+ case ResultCode::kNotSupportedError :
72+ return method_name + " () is not supported" ;
73+ case ResultCode::kPermissionDeniedError :
74+ return std::string{" No permission to run " } + method_name +
75+ " (). Add "
76+ " \" http://tizen.org/privilege/feedback\" privilege to "
77+ " tizen-manifest.xml "
78+ " to use this method" ;
79+ case ResultCode::kUnknownError :
80+ default :
81+ return std::string{" An unknown error on " } + method_name + " () call" ;
82+ }
83+ }
84+
85+ #if defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
86+
87+ static FeedbackManager& GetInstance () {
88+ FT_LOGD (" Enter FeedbackManager::GetInstance()" );
89+
90+ static FeedbackManager instance;
91+ return instance;
92+ }
93+
94+ FeedbackManager (const FeedbackManager&) = delete;
95+ FeedbackManager& operator =(const FeedbackManager&) = delete ;
96+
97+ ResultCode Vibrate () {
98+ FT_LOGD (" Enter FeedbackManager::Vibrate()" );
99+
100+ if (ResultCode::kOk != initialization_status_) {
101+ FT_LOGE (" Cannot run Vibrate(): initialization_status_: [%d]" ,
102+ static_cast <int >(initialization_status_));
103+ return initialization_status_;
104+ }
105+
106+ auto ret =
107+ feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
108+ if (FEEDBACK_ERROR_NONE == ret) {
109+ FT_LOGD (" feedback_play_type() succeeded" );
110+ return ResultCode::kOk ;
111+ }
112+ FT_LOGE (" feedback_play_type() failed with error: [%d] (%s)" , ret,
113+ get_error_message (ret));
114+
115+ return NativeErrorToResultCode (ret);
116+ }
117+
118+ private:
119+ static ResultCode NativeErrorToResultCode (int native_error_code) {
120+ FT_LOGD (" Enter NativeErrorToResultCode: native_error_code: [%d]" ,
121+ native_error_code);
122+
123+ switch (native_error_code) {
124+ case FEEDBACK_ERROR_NONE:
125+ return ResultCode::kOk ;
126+ case FEEDBACK_ERROR_NOT_SUPPORTED:
127+ return ResultCode::kNotSupportedError ;
128+ case FEEDBACK_ERROR_PERMISSION_DENIED:
129+ return ResultCode::kPermissionDeniedError ;
130+ case FEEDBACK_ERROR_OPERATION_FAILED:
131+ case FEEDBACK_ERROR_INVALID_PARAMETER:
132+ case FEEDBACK_ERROR_NOT_INITIALIZED:
133+ default :
134+ return ResultCode::kUnknownError ;
135+ }
136+ }
137+
138+ FeedbackManager () {
139+ FT_LOGD (" Enter FeedbackManager::FeedbackManager()" );
140+
141+ auto ret = feedback_initialize ();
142+ if (FEEDBACK_ERROR_NONE != ret) {
143+ FT_LOGE (" feedback_initialize() failed with error: [%d] (%s)" , ret,
144+ get_error_message (ret));
145+ initialization_status_ = NativeErrorToResultCode (ret);
146+ return ;
147+ }
148+ FT_LOGD (" feedback_initialize() succeeded" );
149+
150+ initialization_status_ = ResultCode::kOk ;
151+ }
152+
153+ ~FeedbackManager () {
154+ FT_LOGD (" Enter FeedbackManager::~FeedbackManager" );
155+
156+ auto ret = feedback_deinitialize ();
157+ if (FEEDBACK_ERROR_NONE != ret) {
158+ FT_LOGE (" feedback_deinitialize() failed with error: [%d] (%s)" , ret,
159+ get_error_message (ret));
160+ return ;
161+ }
162+ FT_LOGD (" feedback_deinitialize() succeeded" );
163+ }
164+
165+ ResultCode initialization_status_ = ResultCode::kUnknownError ;
166+
167+ #endif // defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
168+ };
169+
170+ } // namespace
171+
31172void PlatformChannel::HandleMethodCall (
32173 const flutter::MethodCall<rapidjson::Document>& call,
33174 std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
@@ -39,7 +180,39 @@ void PlatformChannel::HandleMethodCall(
39180 } else if (method == " SystemSound.play" ) {
40181 result->NotImplemented ();
41182 } else if (method == " HapticFeedback.vibrate" ) {
42- result->NotImplemented ();
183+ FT_LOGD (" HapticFeedback.vibrate() call received" );
184+
185+ const std::string error_message = " Could not vibrate" ;
186+
187+ #if defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
188+ /*
189+ * We use a single type of vibration (FEEDBACK_PATTERN_SIP) to implement
190+ * HapticFeedback's vibrate, lightImpact, mediumImpact, heavyImpact
191+ * and selectionClick methods, because Tizen's "feedback" module
192+ * has no dedicated vibration types for them.
193+ * Thus, we ignore the "arguments" contents for "HapticFeedback.vibrate"
194+ * calls.
195+ */
196+
197+ auto ret = FeedbackManager::GetInstance ().Vibrate ();
198+ if (FeedbackManager::ResultCode::kOk == ret) {
199+ result->Success ();
200+ return ;
201+ }
202+
203+ const auto vibrate_variant_name =
204+ FeedbackManager::GetVibrateVariantName (call.arguments ()[0 ].GetString ());
205+ const auto error_cause =
206+ FeedbackManager::GetErrorMessage (vibrate_variant_name, ret);
207+ FT_LOGE (" %s: %s" , error_cause.c_str (), error_message.c_str ());
208+ #else
209+ const auto vibrate_variant_name =
210+ FeedbackManager::GetVibrateVariantName (call.arguments ()[0 ].GetString ());
211+ const auto error_cause = FeedbackManager::GetErrorMessage (
212+ vibrate_variant_name, FeedbackManager::ResultCode::kNotSupportedError );
213+ #endif // defined(MOBILE_PROFILE) || defined(WEARABLE_PROFILE)
214+
215+ result->Error (error_cause, error_message);
43216 } else if (method == " Clipboard.getData" ) {
44217 result->NotImplemented ();
45218 } else if (method == " Clipboard.setData" ) {
0 commit comments