update the header for Doxygen
[platform/framework/native/bluetooth.git] / src / FNetBt_BluetoothOppClientImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.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://www.apache.org/licenses/LICENSE-2.0
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 // @file    FNetBtBluetoothOppClientImpl.cpp
18 // @brief   This is the implementation file for the _BluetoothOppClientImpl class.
19 //
20
21 #include <FNetBtBluetoothTypes.h>
22 #include <FNetBtBluetoothDevice.h>
23 #include <FNetBtIBluetoothOppClientEventListener.h>
24 #include <FBaseSysLog.h>
25 #include <FIo_FileImpl.h>
26 #include <FApp_AppInfo.h>
27 #include "FNetBt_BluetoothOppClientImpl.h"
28 #include "FNetBt_BluetoothOppSystemAdapter.h"
29 #include "FNetBt_BluetoothGapSystemAdapter.h"
30 #include "FNetBt_BluetoothOppClientEvent.h"
31 #include "FNetBt_BluetoothOppClientEventArg.h"
32
33 using namespace std;
34 using namespace Tizen::App;
35 using namespace Tizen::Base;
36 using namespace Tizen::Base::Runtime;
37
38 namespace Tizen { namespace Net { namespace Bluetooth
39 {
40
41 _BluetoothOppClientImpl::_BluetoothOppClientImpl(void)
42         : __pGapAdapter(null)
43         , __pOppAdapter(null)
44         , __pEvent(null)
45         , __stateMutex()
46         , __currentState(_BT_OPP_CLI_STATE_DISABLED)
47         , __pairingAddress()
48         , __pushedFilePath()
49         , __minProgressInterval(__defaultProgressInterval)
50         , __previousProgress(0)
51 {
52 }
53
54 _BluetoothOppClientImpl::~_BluetoothOppClientImpl(void)
55 {
56         if (__pOppAdapter != null)
57         {
58                 if ((__currentState == _BT_OPP_CLI_STATE_PUSH_READY)
59                         || (__currentState == _BT_OPP_CLI_STATE_ON_TRANSFER))
60                 {
61                         (void) CancelPush();
62                 }
63         }
64
65         if (__pGapAdapter != null)
66         {
67                 __pGapAdapter->UnregisterManagerEventListener(*this);
68                 __pGapAdapter->UnregisterDeviceEventListener(*this);
69         }
70 }
71
72 result
73 _BluetoothOppClientImpl::Construct(IBluetoothOppClientEventListener& listener)
74 {
75         result r = E_SUCCESS;
76         std::unique_ptr<_BluetoothOppClientEvent> pEvent;
77
78         r = __stateMutex.Create();
79         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to create the state mutex.");
80
81         r = __pairingAddress.Construct(_BT_ADDRESS_LENGTH);
82         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to construct the address for pairing.");
83
84         __pGapAdapter = _BluetoothGapSystemAdapter::GetInstance();
85         SysTryReturn(NID_NET_BT, __pGapAdapter != null, E_SYSTEM, E_SYSTEM,
86                                 "[E_SYSTEM] Failed to invoke _BluetoothGapSystemAdapter::GetInstance().");
87
88         __pOppAdapter = _BluetoothOppSystemAdapter::GetInstance();
89
90         pEvent.reset(new (std::nothrow) _BluetoothOppClientEvent());
91         SysTryReturn(NID_NET_BT, pEvent != null, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
92         r = pEvent->Construct();
93         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to construct the event.");
94         // add the IBluetoothOppClientEventListener instance to a new created _BluetoothOppClientEvent.
95         r = pEvent->AddListener(listener, true);
96         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM,
97                         "[%s] Propagating. Failed to add the application listener for OPP client", GetErrorMessage(r));
98
99         // registers this callback listener to the system adapter for activation/deactivation event
100         r = __pGapAdapter->RegisterManagerEventListener(*this, true);
101         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM,
102                            "[E_SYSTEM] Failed to register the callback listener to _BluetoothGapSystemAdapter.");
103
104         // registers this callback listener to the system adapter for paired event
105         r = __pGapAdapter->RegisterDeviceEventListener(*this);
106         if (r != E_SUCCESS)
107         {
108                 __pGapAdapter->UnregisterManagerEventListener(*this);
109         }
110         SysTryReturn(NID_NET_BT, r == E_SUCCESS, E_SYSTEM, E_SYSTEM,
111                            "[E_SYSTEM] Failed to register the callback listener to _BluetoothGapSystemAdapter.");
112
113         // checks whether the Bluetooth is available
114         __stateMutex.Acquire();
115
116         if (__pGapAdapter->IsActivated() == true)
117         {
118                 __currentState = _BT_OPP_CLI_STATE_IDLE;
119         }
120
121         __stateMutex.Release();
122
123         __pEvent = move(pEvent);
124
125         return E_SUCCESS;
126 }
127
128
129 result
130 _BluetoothOppClientImpl::PushFile(const BluetoothDevice& remoteDevice, const Base::String& filePath)
131 {
132         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
133
134         result r = E_FAILURE;
135         String physicalPath;
136
137         __stateMutex.Acquire();
138
139         switch (__currentState)
140         {
141         case _BT_OPP_CLI_STATE_DISABLED:
142                 r = E_INVALID_STATE;
143                 break;
144
145         case _BT_OPP_CLI_STATE_IDLE:
146                 if (_AppInfo::GetApiVersion() == _API_VERSION_2_0 && _AppInfo::IsOspCompat())
147                 {
148                         if (Tizen::Io::_FileImpl::ConvertVirtualToPhysicalPath(filePath, physicalPath) != E_SUCCESS)
149                         {
150                                 r = E_INACCESSIBLE_PATH;
151                                 break;
152                         }
153                 }
154                 else
155                 {
156                         physicalPath = filePath;
157                 }
158
159                 if (__pGapAdapter->IsPaired(*(remoteDevice.GetAddress())) == true)
160                 {
161                         r = __pOppAdapter->PushOppFile(*this, *(remoteDevice.GetAddress()), physicalPath);
162                         if (r == E_SUCCESS)
163                         {
164                                 __currentState = _BT_OPP_CLI_STATE_PUSH_READY;
165                         }
166                 }
167                 else
168                 {
169                         // start the pairing process
170                         if (__pGapAdapter->Pair(*(remoteDevice.GetAddress())) == E_SUCCESS)
171                         {
172                                 // copy the address of the pairing device to the local variable
173                                 __pairingAddress.SetArray(remoteDevice.GetAddress()->GetPointer(), 0, _BT_ADDRESS_LENGTH);
174                                 __pairingAddress.SetPosition(0);
175                                 // copy the file path to the local variable
176                                 __pushedFilePath.Clear();
177                                 __pushedFilePath = physicalPath;
178
179                                 r = E_SUCCESS;
180                                 __currentState = _BT_OPP_CLI_STATE_BONDING;
181                         }
182                         else
183                         {
184                                 r = E_FAILURE;
185                         }
186                 }
187                 break;
188
189         case _BT_OPP_CLI_STATE_BONDING:
190         case _BT_OPP_CLI_STATE_PUSH_READY:
191         case _BT_OPP_CLI_STATE_REQ_CANCELING:   //TODO: this state should return E_INVALID_OPERATION. (Versioning)
192         case _BT_OPP_CLI_STATE_ON_TRANSFER:
193         case _BT_OPP_CLI_STATE_TRANS_CANCELING:   //TODO: this state should return E_INVALID_OPERATION. (Versioning)
194                 r = E_IN_PROGRESS;
195                 break;
196
197         default:
198                 // ignore other cases
199                 break;
200         }
201
202         __stateMutex.Release();
203
204         if (r != E_SUCCESS)
205         {
206                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on pushing a file.", GetErrorMessage(r));
207         }
208
209         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
210
211         return r;
212 }
213
214 result
215 _BluetoothOppClientImpl::CancelPush()
216 {
217         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s]", GetStringOfCurrentState());
218
219         result r = E_FAILURE;
220
221         __stateMutex.Acquire();
222
223         switch (__currentState)
224         {
225         case _BT_OPP_CLI_STATE_DISABLED:
226                 r = E_INVALID_STATE;
227                 break;
228
229         case _BT_OPP_CLI_STATE_IDLE:
230                 r = E_INVALID_OPERATION;
231                 break;
232
233         case _BT_OPP_CLI_STATE_REQ_CANCELING:
234         case _BT_OPP_CLI_STATE_TRANS_CANCELING:
235                 r = E_IN_PROGRESS;
236                 break;
237
238         case _BT_OPP_CLI_STATE_BONDING: //TODO: Versioning check
239                 if (__pGapAdapter->CancelPair() == E_SUCCESS)
240                 {
241                         r = E_SUCCESS;
242                         __currentState = _BT_OPP_CLI_STATE_REQ_CANCELING;
243                 }
244                 // It will be changed to IDLE after receiving the OnBluetoothPaired event.
245                 break;
246
247         case _BT_OPP_CLI_STATE_PUSH_READY:
248                 r = __pOppAdapter->CancelOppPush();
249
250                 if (r == E_SUCCESS)
251                 {
252                         __currentState = _BT_OPP_CLI_STATE_REQ_CANCELING;
253                 }
254                 // It will be changed to IDLE after receiving the OnOppTransferDone event.
255                 break;
256
257         case _BT_OPP_CLI_STATE_ON_TRANSFER:
258                 r = __pOppAdapter->CancelOppPush();
259
260                 if (r == E_SUCCESS)
261                 {
262                         __currentState = _BT_OPP_CLI_STATE_TRANS_CANCELING;
263                 }
264                 // It will be changed to IDLE after receiving the OnOppTransferDone event.
265                 break;
266
267         default:
268                 // ignore other cases
269                 break;
270         }
271
272         __stateMutex.Release();
273
274         if (r != E_SUCCESS)
275         {
276                 SysLogException(NID_NET_BT, r, "[%s] exception occurred on canceling the push.", GetErrorMessage(r));
277         }
278
279         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
280
281         return r;
282 }
283
284 result
285 _BluetoothOppClientImpl::SetMinProgressInterval(int percent)
286 {
287         result r = E_SUCCESS;
288
289         if ((percent < 1) || (percent > 100))
290         {
291                 r = E_OUT_OF_RANGE;
292                 SysLogException(NID_NET_BT, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] The input argument - percent - is outside the valid range.");
293         }
294         else
295         {
296                 __minProgressInterval = percent;
297         }
298
299         return r;
300 }
301
302 void
303 _BluetoothOppClientImpl::OnBluetoothActivated(result r)
304 {
305         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
306
307         __stateMutex.Acquire();
308
309         if ((__currentState == _BT_OPP_CLI_STATE_DISABLED)
310                 && (r == E_SUCCESS))
311         {
312                 __currentState = _BT_OPP_CLI_STATE_IDLE;
313         }
314
315         __stateMutex.Release();
316
317         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s]", GetStringOfCurrentState());
318 }
319
320 void
321 _BluetoothOppClientImpl::OnBluetoothDeactivated(result r)
322 {
323         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
324
325         __stateMutex.Acquire();
326
327         if (r == E_SUCCESS)
328         {
329                 __currentState = _BT_OPP_CLI_STATE_DISABLED;
330         }
331
332         __stateMutex.Release();
333
334         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s]", GetStringOfCurrentState());
335 }
336
337 void
338 _BluetoothOppClientImpl::OnOppPushResponded(result r)
339 {
340         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
341
342         bool isFired = false;
343
344         __stateMutex.Acquire();
345
346         if ((__currentState == _BT_OPP_CLI_STATE_PUSH_READY) || (__currentState == _BT_OPP_CLI_STATE_REQ_CANCELING))
347         {
348                 if (r == E_SUCCESS)
349                 {
350                         __currentState = _BT_OPP_CLI_STATE_ON_TRANSFER;
351                 }
352                 else // including both cases of being canceled by the user and rejected by the remote device
353                 {
354                         __currentState = _BT_OPP_CLI_STATE_IDLE;
355                         SysLogException(NID_NET_BT, r, "[%s] exception occurred on the response of the OPP push request.", GetErrorMessage(r));
356                 }
357
358                 isFired = true;
359         }
360
361         __stateMutex.Release();
362
363         if (isFired)
364         {
365                 _BluetoothOppClientEventArg* pArg = new (std::nothrow) _BluetoothOppClientEventArg(r);
366                 if (pArg == null)
367                 {
368                         SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
369                         isFired = false;
370                 }
371                 else
372                 {
373                         __pEvent->FireAsync(*pArg);
374                 }
375         }
376
377         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [PUSH_RESPONDED_Event:%s]",
378                                 GetStringOfCurrentState(), isFired ? "Fired" : "NotFired");
379 }
380
381 void
382 _BluetoothOppClientImpl::OnOppTransferInProgress(int percent)
383 {
384         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [Progress:%d]", GetStringOfCurrentState(), percent);
385
386         bool isFired = false;
387
388         __stateMutex.Acquire();
389
390         if ((__currentState == _BT_OPP_CLI_STATE_ON_TRANSFER) || (__currentState == _BT_OPP_CLI_STATE_TRANS_CANCELING))
391         {
392                 if (((percent - __previousProgress) >= __minProgressInterval) || (percent >= 100))
393                 {
394                         isFired = true;
395                         __previousProgress = percent;
396                 }
397         }
398
399         __stateMutex.Release();
400
401         if (isFired)
402         {
403                 _BluetoothOppClientEventArg* pArg = new (std::nothrow) _BluetoothOppClientEventArg(percent);
404                 if (pArg == null)
405                 {
406                         SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
407                         isFired = false;
408                 }
409                 else
410                 {
411                         __pEvent->FireAsync(*pArg);
412                 }
413         }
414
415         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [TRANSFER_IN_PROGRESS_Event:%s]",
416                                 GetStringOfCurrentState(), isFired ? "Fired" : "NotFired");
417 }
418
419 void
420 _BluetoothOppClientImpl::OnOppTransferDone(const Tizen::Base::String& filePath, int fileSize, bool isCompleted)
421 {
422         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [filePath:%ls], [fileSize:%d], [%s]",
423                                 GetStringOfCurrentState(), filePath.GetPointer(), fileSize, isCompleted ? "Completed" : "Incompleted");
424
425         bool isFired = false;
426         String pushedFilePath;
427         result r = E_SUCCESS;
428
429         __stateMutex.Acquire();
430
431         if ((__currentState == _BT_OPP_CLI_STATE_ON_TRANSFER) || (__currentState == _BT_OPP_CLI_STATE_TRANS_CANCELING))
432         {
433                 __currentState = _BT_OPP_CLI_STATE_IDLE;
434                 isFired = true;
435                 __previousProgress = 0;        // initialization for the next push transaction
436         }
437
438         __stateMutex.Release();
439
440         if (_AppInfo::GetApiVersion() == _API_VERSION_2_0 && _AppInfo::IsOspCompat())
441         {
442                 r = Tizen::Io::_FileImpl::ConvertPhysicalToVirtualPath(__pushedFilePath, pushedFilePath);
443                 if(r != E_SUCCESS)
444                 {
445                         SysLogException(NID_NET_BT, r, "[%s] exception occurred on converting the file path from physical to virtual.", GetErrorMessage(r));
446                         pushedFilePath = __pushedFilePath;
447                 }
448         }
449         else
450         {
451                 pushedFilePath = __pushedFilePath;
452         }
453
454         if (isFired)
455         {
456                 _BluetoothOppClientEventArg* pArg = new (std::nothrow) _BluetoothOppClientEventArg(pushedFilePath, fileSize, isCompleted);
457                 if (pArg == null)
458                 {
459                         SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
460                         isFired = false;
461                 }
462                 else
463                 {
464                         __pEvent->FireAsync(*pArg);
465                 }
466         }
467
468         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [TRANSFER_DONE_Event:%s]",
469                                 GetStringOfCurrentState(), isFired ? "Fired" : "NotFired");
470 }
471
472 void
473 _BluetoothOppClientImpl::OnBluetoothPaired(const BluetoothDevice* pPairedDevice, result r)
474 {
475         SysLog(NID_NET_BT, "EntryPoint, [CurrentState:%s], [ActionResult:%s]", GetStringOfCurrentState(), GetErrorMessage(r));
476
477         bool isFired = false;
478         result responseResult = E_SYSTEM;
479
480         __stateMutex.Acquire();
481
482         if (pPairedDevice->GetAddress()->Equals(__pairingAddress))
483         {
484                 if (__currentState == _BT_OPP_CLI_STATE_BONDING)
485                 {
486                         if (r == E_SUCCESS)
487                         {
488                                 if (__pOppAdapter->PushOppFile(*this, __pairingAddress, __pushedFilePath) == E_SUCCESS)
489                                 {
490                                         __currentState = _BT_OPP_CLI_STATE_PUSH_READY;
491                                 }
492                                 else
493                                 {
494                                         // callback responded with E_SYSTEM
495                                         isFired = true;
496                                         __currentState = _BT_OPP_CLI_STATE_IDLE;
497                                         responseResult = E_SYSTEM;
498                                 }
499                         }
500                         else
501                         {
502                                 // callback responded with r
503                                 isFired = true;
504                                 __currentState = _BT_OPP_CLI_STATE_IDLE;
505                                 responseResult = r;
506                         }
507
508                         __pairingAddress.Clear();
509                 }
510                 else if (__currentState == _BT_OPP_CLI_STATE_REQ_CANCELING)
511                 {
512                         // callback responded with E_SYSTEM or E_OPERATION_CANCELED
513                         isFired = true;
514                         __currentState = _BT_OPP_CLI_STATE_IDLE;
515                         responseResult = E_SYSTEM;
516                 }
517         }
518         // ignored otherwise
519
520         __stateMutex.Release();
521
522         if (isFired)
523         {
524                 _BluetoothOppClientEventArg* pArg = new (std::nothrow) _BluetoothOppClientEventArg(responseResult);
525                 if (pArg == null)
526                 {
527                         SysLogException(NID_NET_BT, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
528                         isFired = false;
529                 }
530                 else
531                 {
532                         __pEvent->FireAsync(*pArg);
533                 }
534         }
535
536         SysLog(NID_NET_BT, "ExitPoint, [CurrentState:%s], [PUSH_RESPONDED_Event:%s]",
537                                 GetStringOfCurrentState(), isFired ? "Fired" : "NotFired");
538 }
539
540 const char*
541 _BluetoothOppClientImpl::GetStringOfCurrentState(void) const
542 {
543         const char* pStateString = null;
544
545         switch (__currentState)
546         {
547         case _BT_OPP_CLI_STATE_DISABLED:
548                 pStateString = "DISABLED";
549                 break;
550
551         case _BT_OPP_CLI_STATE_IDLE:
552                 pStateString = "IDLE";
553                 break;
554
555         case _BT_OPP_CLI_STATE_BONDING:
556                 pStateString = "BONDING";
557                 break;
558
559         case _BT_OPP_CLI_STATE_PUSH_READY:
560                 pStateString = "PUSH_READY";
561                 break;
562
563         case _BT_OPP_CLI_STATE_REQ_CANCELING:
564                 pStateString = "REQ_CANCELING";
565                 break;
566
567         case _BT_OPP_CLI_STATE_ON_TRANSFER:
568                 pStateString = "ON_TRANSFER";
569                 break;
570
571         case _BT_OPP_CLI_STATE_TRANS_CANCELING:
572                 pStateString = "TRANS_CANCELING";
573                 break;
574
575         default:
576                 pStateString = "Unknown";
577                 break;
578         }
579
580         return pStateString;
581 }
582
583 } } } // Tizen::Net::Bluetooth