Tizen 2.1 base
[platform/framework/native/connectivity-service.git] / src / NfcMessagePushDelegate.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Flora License, Version 1.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://floralicense.org/license/
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an AS IS BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file    NfcMessagePushDelegate.cpp
20  * @brief   This is the implementation file for the %NfcMessagePushDelegate class.
21  */
22
23 #include <unique_ptr.h>
24 #include <string.h>
25 #include <vconf-internal-nfc-keys.h>
26 #include <vconf-internal-setting-keys.h>
27 #include <Ecore_Evas.h>
28 #include <Ecore_X.h>
29 #include <app_manager.h>
30 #include <FAppAppControl.h>
31 #include <FAppAppManager.h>
32 #include <FBaseSysLog.h>
33 #include <FBaseByteBuffer.h>
34 #include <FBaseUtilStringUtil.h>
35 #include <FBaseColArrayList.h>
36 #include <FIoFile.h>
37 #include <FIoFileAttributes.h>
38 #include "NfcMessagePushDelegate.h"
39 #include "NfcMessageRegisterService.h"
40
41 using namespace std;
42 using namespace Tizen::Base;
43 using namespace Tizen::Base::Utility;
44 using namespace Tizen::App;
45 using namespace Tizen::Io;
46 using namespace Tizen::Base::Collection;
47
48 const wchar_t* NfcMessagePushDelegate::_NFC_PUSH_UI_AC_PROVIDER_ID = L"http://tizen.org/appcontrol/provider/nfcpushui";
49 const wchar_t* NfcMessagePushDelegate::_NFC_PUSH_UI_AC_OPERATION_ID = L"http://tizen.org/appcontrol/operation/nfc/animation/show";
50
51 struct _CharDeleter
52 {
53         void operator()(char* pChar)
54         {
55                 free(pChar);
56         }
57 };
58
59 NfcMessagePushDelegate::NfcMessagePushDelegate(void)
60         : __isPushEnabled(false)
61         , __p2pTargetHandle(null)
62 {
63         // Checks whether the reserved push feature is enabled or disabled
64         UpdatePushEnabled();
65
66         // set vconf callback about the Reserved Push setting
67         vconf_notify_key_changed(VCONFKEY_NFC_PREDEFINED_ITEM_STATE, OnNfcReservedPushStateChanged, this);
68 }
69
70 NfcMessagePushDelegate::~NfcMessagePushDelegate(void)
71 {
72         Deinitialize();
73     // unset vconf callback
74     vconf_ignore_key_changed(VCONFKEY_NFC_PREDEFINED_ITEM_STATE, OnNfcReservedPushStateChanged);
75 }
76
77 void
78 NfcMessagePushDelegate::Initialize(void)
79 {
80         // set NFC target discovered callback
81         nfc_manager_set_p2p_target_discovered_cb(&OnNfcDeviceDiscovered, this);
82 }
83
84 void
85 NfcMessagePushDelegate::Deinitialize(void)
86 {
87         nfc_manager_unset_p2p_target_discovered_cb();
88 }
89
90 void
91 NfcMessagePushDelegate::UpdatePushEnabled(void)
92 {
93         int vconfRes = -1;
94         int isEnabled = 0;
95
96         // get the value for the predefined item
97         vconfRes = vconf_get_bool(VCONFKEY_NFC_PREDEFINED_ITEM_STATE, &isEnabled);
98         SysTryReturnVoidResult(NID_NET_NFC, vconfRes == 0, E_SYSTEM,
99                         "[E_SYSTEM] Failed to get the vconf - reserved push state - value.");
100
101         __isPushEnabled = (isEnabled == 0) ? false : true;
102
103         SysLog(NID_NET_NFC, "The Reserved Push is %s.", __isPushEnabled ? "enabled" : "disabled");
104 }
105
106 bool
107 NfcMessagePushDelegate::IsHomeScreenAtTopmost(void)
108 {
109 //      unique_ptr<char, _CharDeleter> pHomeScreenId;
110         unique_ptr<char, _CharDeleter> pHomeMenuId;
111         char* pTopmostAppId = 0;
112         Ecore_X_Window activeWin = 0;
113         int winPid = 0;
114         Eina_Bool ecoreRes = EINA_FALSE;
115         int appRes = APP_MANAGER_ERROR_NONE;
116         bool thisRes = false;
117
118         // get the value for the home menu app id
119         pHomeMenuId.reset(vconf_get_str(VCONFKEY_SETAPPL_SELECTED_PACKAGE_NAME));
120         SysTryReturn(NID_NET_NFC, pHomeMenuId != null, false, E_SYSTEM, "[E_SYSTEM] Failed to get the Home Menu App ID.");
121         SysLog(NID_NET_NFC, "Home Menu ID: %s", pHomeMenuId.get());
122
123         // get the value for the home screen app id
124         // TODO: block the below code for preventing build error in RSA because the specified vconf key is not defined in RSA
125 //      pHomeScreenId.reset(vconf_get_str(VCONFKEY_SETAPPL_SELECTED_HOMESCREEN_PACKAGE_NAME));
126 //      SysTryReturn(NID_NET_NFC, pHomeScreenId != null, false, E_SYSTEM, "[E_SYSTEM] Failed to get the Home Screen App ID.");
127 //      SysLog(NID_NET_NFC, "Home Screen ID: %s", pHomeScreenId.get());
128
129         // get the topmost (focused) window
130         activeWin = ecore_x_window_focus_get();
131
132         // get the PID(process ID) of the topmost window
133         ecoreRes = ecore_x_netwm_pid_get(activeWin, &winPid);
134         SysTryReturn(NID_NET_NFC, ecoreRes == EINA_TRUE, false, E_SYSTEM, "[E_SYSTEM] Failed to get the PID of the active window.");
135
136         // get the App ID of the topmost window through PID
137         appRes = app_manager_get_app_id(winPid, &pTopmostAppId);
138         SysTryReturn(NID_NET_NFC, (appRes == APP_MANAGER_ERROR_NONE) && (pTopmostAppId != null), false, E_SYSTEM,
139                         "[E_SYSTEM] Failed to get the topmost app ID.");
140         SysLog(NID_NET_NFC, "Topmost App ID: %s", pTopmostAppId);
141
142         // compare the topmost App ID with the Home screen App ID and the Home menu App ID
143         // TODO: block the below conditions for preventing build error in RSA
144         // if ((strcmp(pHomeScreenId.get(), pTopmostAppId) == 0) || (strcmp(pHomeMenuId.get(), pTopmostAppId) == 0))
145         if (strcmp(pHomeMenuId.get(), pTopmostAppId) == 0)
146         {
147                 SysLog(NID_NET_NFC, "Home screen or Home menu is the topmost running app.");
148                 thisRes = true;
149         }
150
151         free(pTopmostAppId);
152
153         return thisRes;
154 }
155
156 void
157 NfcMessagePushDelegate::SendReservedMessage(nfc_p2p_target_h targetH)
158 {
159         ByteBuffer messageBuffer;
160         int nfcRes = NFC_ERROR_NONE;
161         result r = E_SUCCESS;
162         File msgFile;
163         FileAttributes msgFileAttr;
164         String msgFilePath;
165         nfc_ndef_message_h ndefMessageH = NULL;
166         char* pSelectedItem = null;
167         String selectedItemStr;
168
169         // get the value for the predefined item
170         pSelectedItem = vconf_get_str(VCONFKEY_NFC_PREDEFINED_ITEM);
171         SysTryReturnVoidResult(NID_NET_NFC, pSelectedItem != null, E_SYSTEM,
172                         "[E_SYSTEM] Failed to get the selected item among the item list.");
173
174         selectedItemStr = String(pSelectedItem);
175         free(pSelectedItem);
176         SysLog(NID_NET_NFC, "Try to send the reserved NDEF message (ID: %ls) to the detected peer device...",
177                         selectedItemStr.GetPointer());
178
179         // make the push message file path which consists of the directory path, appId as the name, and "ndef" as the extension.
180         msgFilePath = NfcMessageRegisterService::_PUSH_MESSAGE_DIRECTORY + selectedItemStr +
181                         NfcMessageRegisterService::_PUSH_MESSAGE_EXT_NAME;
182
183         // create a ByteBuffer instance to fill the content of the message file into it.
184         r = File::GetAttributes(msgFilePath, msgFileAttr);
185         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, E_OPERATION_FAILED,
186                         "[E_OPERATION_FAILED] Getting the size of the NDEF message file has failed. (File path: %ls)",
187                         msgFilePath.GetPointer());
188
189         r = messageBuffer.Construct(msgFileAttr.GetFileSize());
190         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, E_OPERATION_FAILED,
191                         "[E_OPERATION_FAILED] Construction of the ByteBuffer for reading has failed.");
192
193         // get NdefMessage from the file
194         r = msgFile.Construct(msgFilePath, L"r");
195         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, E_OPERATION_FAILED,
196                         "[E_OPERATION_FAILED] Construction of the push message file for reading has failed. (File path: %ls)",
197                         msgFilePath.GetPointer());
198
199         r = msgFile.Read(messageBuffer);
200         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, E_OPERATION_FAILED,
201                         "[E_OPERATION_FAILED] Reading the NDEF message file has failed.");
202         messageBuffer.Flip();
203
204         SysLog(NID_NET_NFC, "Reading the reserved NDEF message is successful.");
205
206         // send the reserved NDEF message as a raw format - byte array type.
207         nfcRes = nfc_ndef_message_create_from_rawdata(&ndefMessageH, messageBuffer.GetPointer() + messageBuffer.GetPosition(),
208                         messageBuffer.GetRemaining());
209         SysTryReturnVoidResult(NID_NET_NFC, nfcRes == NFC_ERROR_NONE, E_OPERATION_FAILED,
210                         "[E_OPERATION_FAILED] Failed to convert raw data to NDEF message [0x%08X].", nfcRes);
211
212         nfcRes = nfc_p2p_send(targetH, ndefMessageH, &OnNdefMessageSent, null);
213         nfc_ndef_message_destroy(ndefMessageH); // free the resources. (the result is ignored)
214         SysTryReturnVoidResult(NID_NET_NFC, nfcRes == NFC_ERROR_NONE, E_OPERATION_FAILED,
215                         "[E_OPERATION_FAILED] Failed to send the NDEF message [0x%08X].", nfcRes);
216
217         SysLog(NID_NET_NFC, "Sending the reserved NDEF message is successfully started.");
218 }
219
220 void
221 NfcMessagePushDelegate::InvokeNfcPushUiAppControl(const String& iconPath, const String& appName, const String& description)
222 {
223         result r = E_SUCCESS;
224         std::unique_ptr<ArrayList> pDataList;
225         std::unique_ptr<String> pData1;
226         std::unique_ptr<String> pData2;
227         std::unique_ptr<String> pData3;
228         std::unique_ptr<AppControl> pAc;
229
230         // array list for args
231         pDataList.reset(new (std::nothrow) ArrayList());
232         SysTryReturnVoidResult(NID_NET_NFC, pDataList != null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
233         r = pDataList->Construct();
234         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r, "[%s] An unexpected error has occurred.", GetErrorMessage(r));
235
236         // iconPath
237         pData1.reset(new (std::nothrow) String(L"iconPath:"));
238         SysTryReturnVoidResult(NID_NET_NFC, pData1 != null, E_OUT_OF_MEMORY, "Insufficient memory.");
239         r = pData1->Append(iconPath);
240         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
241                         "[%s] exception occurred. Failed to make a parameter for icon path.", GetErrorMessage(r));
242         r = pDataList->Add(*pData1);
243         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
244                         "[%s] exception occurred. Failed to make a parameter for icon path.", GetErrorMessage(r));
245
246         // appName
247         pData2.reset(new (std::nothrow) String(L"appName:"));
248         SysTryReturnVoidResult(NID_NET_NFC, pData2 != null, E_OUT_OF_MEMORY, "[%s] Insufficient memory.", GetErrorMessage(r));
249         r = pData2->Append(appName);
250         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
251                         "[%s] exception occurred.  Failed to make a parameter for app name.", GetErrorMessage(r));
252         r = pDataList->Add(*pData2);
253         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
254                         "[%s] exception occurred. Failed to make a parameter for app name.", GetErrorMessage(r));
255
256         // description
257         pData3.reset(new (std::nothrow) String(L"description:"));
258         SysTryReturnVoidResult(NID_NET_NFC, pData3 != null, r = E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Insufficient memory.");
259         r = pData3->Append(description);
260         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
261                         "[%s] exception occurred. Failed to make a parameter for description.", GetErrorMessage(r));
262         r = pDataList->Add(*pData3);
263         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
264                         "[%s] exception occurred. Failed to make a parameter for description.", GetErrorMessage(r));
265
266         // find app control
267         pAc.reset(AppManager::FindAppControlN(_NFC_PUSH_UI_AC_PROVIDER_ID, _NFC_PUSH_UI_AC_OPERATION_ID));
268         SysTryReturnVoidResult(NID_NET_NFC, pAc != null, GetLastResult(),
269                         "[%s] exception occurred. Failed to find app control.", GetErrorMessage(GetLastResult()));
270
271         // start app control
272         r = pAc->Start(pDataList.get(), this);
273         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
274                         "[%s] exception occurred. Failed to start app control", GetErrorMessage(r));
275
276         return;
277 }
278
279 void
280 NfcMessagePushDelegate::OnNfcDeviceDiscovered(nfc_discovered_type_e type, nfc_p2p_target_h target, void* pUserData)
281 {
282         NfcMessagePushDelegate* pDelegate = null;
283
284         pDelegate = static_cast<NfcMessagePushDelegate*>(pUserData);
285
286         if(type == NFC_DISCOVERED_TYPE_ATTACHED)
287         {
288                 SysLog(NID_NET_NFC, "NFC peer device is detected. (Reserved Push is %s)",
289                                 pDelegate->__isPushEnabled ? "ENABLED" : "DISABLED");
290                 if ((target != NULL) && pDelegate->__isPushEnabled && pDelegate->IsHomeScreenAtTopmost())
291                 {
292                         // set p2p target handle
293                         pDelegate->__p2pTargetHandle = target;
294
295                         ////////////////////////////////////////////////////////////////////////////////
296                         // TODO. invoke app control. This should uncommented soon.
297                         ////////////////////////////////////////////////////////////////////////////////
298                         // SysLog(NID_NET_NFC, "invoking app control...");
299                         // pDelegate->InvokeNfcPushUiAppControl(L"temporary/icon/path/", L"app name", L"this is app description.");
300                         ////////////////////////////////////////////////////////////////////////////////
301                 }
302         }
303         else if (type == NFC_DISCOVERED_TYPE_DETACHED)
304         {
305                 SysLog(NID_NET_NFC, "NFC peer device is lost.");
306                 pDelegate->__p2pTargetHandle = null;
307         }
308         // ignore other cases
309 }
310
311 //-----------------------------------------------------------------------------------------------------------------------
312 // VCONFKEY_NFC_PREDEFINED_ITEM_STATE  "db/nfc/predefined_item_state    /* Enable or disable the Reserved Push feature */
313 //-----------------------------------------------------------------------------------------------------------------------
314 void
315 NfcMessagePushDelegate::OnNfcReservedPushStateChanged(keynode_t* pKeyNode, void* pUserData)
316 {
317         char* pKeyStr = null;
318         NfcMessagePushDelegate* pDelegate = null;
319
320         SysLog(NID_NET_NFC, "The key changed event (VCONFKEY_NFC_PREDEFINED_ITEM_STATE) is invoked.");
321
322         // check the key name
323         pKeyStr = vconf_keynode_get_name(pKeyNode);
324         SysTryReturnVoidResult(NID_NET_NFC, pKeyStr != null, E_SYSTEM, "[E_SYSTEM] Failed to get the vconf pKeyNode name.");
325         SysTryReturnVoidResult(NID_NET_NFC, strcmp(pKeyStr, VCONFKEY_NFC_PREDEFINED_ITEM_STATE) == 0, E_SYSTEM,
326                         "[E_SYSTEM] the vconf key name is not about the state for Reserved Push.");
327
328         pDelegate = static_cast<NfcMessagePushDelegate*>(pUserData);
329         pDelegate->UpdatePushEnabled();
330 }
331
332 void
333 NfcMessagePushDelegate::OnNdefMessageSent(nfc_error_e res, void* pUserData)
334 {
335         SysTryReturnVoidResult(NID_NET_NFC, res == NFC_ERROR_NONE, E_OPERATION_FAILED,
336                         "[E_OPERATION_FAILED] Sending the NDEF Message has failed [0x%08X].", res);
337
338         SysLog(NID_NET_NFC, "The NDEF Message has successfully sent to the target device.");
339 }
340
341 void
342 NfcMessagePushDelegate::OnAppControlCompleted(const Tizen::Base::String& providerId, const Tizen::Base::String& operationId, const Tizen::Base::Collection::IList* pResultList)
343 {
344         result r = E_SUCCESS;
345         String* pAppControlResult = null;
346
347         if (providerId == _NFC_PUSH_UI_AC_PROVIDER_ID && operationId == _NFC_PUSH_UI_AC_OPERATION_ID)
348         {
349                 SysTryReturnVoidResult(NID_NET_NFC, pResultList != null, E_OPERATION_FAILED,
350                                 "[E_OPERATION_FAILED] NfcPushUi app control completed. But no result come.");
351
352                 pAppControlResult = (Tizen::Base::String*)(pResultList->GetAt(0));
353                 SysTryReturnVoidResult(NID_NET_NFC, pAppControlResult != null, E_OPERATION_FAILED,
354                                 "[E_OPERATION_FAILED] There is no result in the array list.");
355
356                 // check the app control result
357                 if (pAppControlResult->Equals(APPCONTROL_RESULT_SUCCEEDED))
358                 {
359                         SysLog(NID_NET_NFC, "APPCONTROL_RESULT_SUCCEEDED was come.");
360                         SysTryReturnVoidResult(NID_NET_NFC, __p2pTargetHandle != null, E_OPERATION_FAILED,
361                                         "[E_OPERATION_FAILED] There is no attached device.");
362
363                         // send reserved NDEF message
364                         SendReservedMessage(__p2pTargetHandle);
365                         r = GetLastResult();
366                         SysTryReturnVoidResult(NID_NET_NFC, r == E_SUCCESS, r,
367                                         "[%s] Sending of the reserved push message file has failed.", GetErrorMessage(r));
368                 }
369                 else if (pAppControlResult->Equals(APPCONTROL_RESULT_CANCELED))
370                 {
371                         SysLog(NID_NET_NFC, "APPCONTROL_RESULT_CANCELED was come.");
372                 }
373                 else if (pAppControlResult->Equals(APPCONTROL_RESULT_FAILED))
374                 {
375                         SysLog(NID_NET_NFC, "APPCONTROL_RESULT_FAILED was come.");
376                 }
377         }
378 }