686aa4d8a899ed76baf4f5fc16f54b9cb2b76fb0
[platform/framework/native/locations.git] / src / FLoc_LocationManager.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 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
18 /**
19  * @file        FLoc_LocationManager.cpp
20  * @brief       This is the implementation file for the %_LocationManager class.
21  *
22  * This implementation file contains the definitions of the %_LocationManager class.
23  */
24
25 #include <cassert>
26 #include <iostream>
27 #include <pthread.h>
28 #include <unique_ptr.h>
29 #include <FBaseColArrayList.h>
30 #include <FBaseInteger.h>
31 #include <FBaseBoolean.h>
32 #include <FBaseRtMutex.h>
33 #include <FBaseRtTimer.h>
34 #include <FBaseRtMonitor.h>
35 #include <FBaseRtWaitingLoop.h>
36 #include <FBaseSysLog.h>
37 #include <FLocCoordinates.h>
38 #include <FSysSystemTime.h>
39 #include <FSys_PowerManagerImpl.h>
40 #include "FLoc_Config.h"
41 #include "FLoc_LocationImpl.h"
42 #include "FLoc_LocationManager.h"
43 #include "FLoc_LocationMonitor.h"
44 #include "FLoc_LocationRequestInfo.h"
45 #include "FLoc_SyncLocationRequestInfo.h"
46
47 using namespace Tizen::Base;
48 using namespace Tizen::Base::Collection;
49 using namespace Tizen::Base::Runtime;
50 using namespace Tizen::Base::Utility;
51 using namespace Tizen::System;
52 using namespace std;
53
54 namespace Tizen { namespace Locations
55 {
56
57 _LocationManager* _LocationManager::__pUniqueInstance = null;
58
59 _LocationManager::_LocationManager(void)
60         : Tizen::Base::Runtime::EventDrivenThread()
61         , __locMethodRequested(LOC_METHOD_REQUESTED_NONE)
62         , __locationMgrState(LOC_MGR_STATE_IDLE)
63         , __minRequestedAccuracy(LOC_ACCURACY_INVALID)
64         , __timerInterval(0)
65         , __timerTicks(0)
66         , __pLocRequestInfoList(null)
67         , __pSyncLocRequestInfoList(null)
68         , __pLocUpdateTimer(null)
69 {
70 }
71
72 _LocationManager::~_LocationManager(void)
73 {
74 }
75
76 result
77 _LocationManager::StartLocationUpdates(LocationAccuracy accuracy, int interval, _ILocationManagerListener* pListener, RequestId& reqId)
78 {
79         static RequestId nextLocRequestId = 1;
80         const int ARRAY_LIST_CAPACITY = 1;
81
82         std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList());
83         SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
84
85         std::unique_ptr< _LocationRequestInfo > pLocRequestInfo(new (std::nothrow) _LocationRequestInfo(accuracy, interval, pListener, nextLocRequestId));
86         SysTryReturn(NID_LOC, pLocRequestInfo, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
87
88         result r = pArgList->Construct(ARRAY_LIST_CAPACITY);
89         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r));
90         r = pArgList->Add(*pLocRequestInfo);
91         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating", GetErrorMessage(r));
92
93         pLocRequestInfo.release();
94
95         r = SendUserEvent(REQ_ID_START_LOC_UPDATES, pArgList.get());
96         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r));
97
98         reqId = nextLocRequestId;
99         nextLocRequestId++;
100
101         pArgList.release();
102
103         SysLog(NID_LOC, "Request ID (%ld) is assigned for the location request with accuracy (%d) and interval (%d).", reqId, accuracy, interval);
104         return E_SUCCESS;
105 }
106
107 result
108 _LocationManager::StopLocationUpdates(RequestId reqId)
109 {
110         SysLog(NID_LOC, "Location update stop requested for request ID (%d).", reqId);
111         const int ARRAY_LIST_CAPACITY = 1;
112
113         std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList());
114         SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
115
116         std::unique_ptr< Integer > pReqId(new (std::nothrow) Integer(static_cast< int >(reqId)));
117         SysTryReturn(NID_LOC, pReqId, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
118
119         result r = pArgList->Construct(ARRAY_LIST_CAPACITY);
120         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r));
121         r = pArgList->Add(*pReqId);
122         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r));
123
124         pReqId.release();
125
126         r = SendUserEvent(REQ_ID_STOP_LOC_UPDATES, pArgList.get());
127         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r));
128
129         pArgList.release();
130         return E_SUCCESS;
131 }
132
133 result
134 _LocationManager::ChangeUpdateInterval(RequestId reqId, int interval)
135 {
136         SysLog(NID_LOC, "Interval update requested for request ID (%d).", reqId);
137         const int ARRAY_LIST_CAPACITY = 2;
138
139         std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList());
140         SysTryReturn(NID_LOC, pArgList, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
141         result r = pArgList->Construct(ARRAY_LIST_CAPACITY);
142         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r));
143
144         std::unique_ptr< Integer > pReqId(new (std::nothrow) Integer(static_cast< int >(reqId)));
145         SysTryReturn(NID_LOC, pReqId, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
146
147         r = pArgList->Add(*pReqId);
148         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r));
149
150         pReqId.release();
151
152         std::unique_ptr< Integer > pInterval(new (std::nothrow) Integer(interval));
153         SysTryReturn(NID_LOC, pInterval, E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
154
155         r = pArgList->Add(*pInterval);
156         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r));
157
158         pInterval.release();
159
160         r = SendUserEvent(REQ_ID_UPDATE_INTERVAL, pArgList.get());
161         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r));
162
163         pArgList.release();
164         return E_SUCCESS;
165 }
166
167 result
168 _LocationManager::RegisterLocationMonitor(_LocationMonitor* pLocationMonitor)
169 {
170         RequestId reqId;
171         const int ARRAY_LIST_CAPACITY = 1;
172
173         result r = StartLocationUpdates(pLocationMonitor->GetAccuracy(), 1, null, reqId);
174         SysTryReturn(NID_LOC, r == E_SUCCESS, r, r, "[%s] Error to request location updates.", GetErrorMessage(r));
175
176         std::unique_ptr< _SyncLocationRequestInfo > pSyncLocationRequestInfo(new (std::nothrow) _SyncLocationRequestInfo(pLocationMonitor, reqId));
177         std::unique_ptr< Tizen::Base::Collection::ArrayList, Tizen::Base::Collection::AllElementsDeleter > pArgList(new (std::nothrow) ArrayList());
178         SysTryCatch(NID_LOC, pSyncLocationRequestInfo != null && pArgList != null, , E_OUT_OF_MEMORY,
179                                 "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
180
181         r = pArgList->Construct(ARRAY_LIST_CAPACITY);
182         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Array Construct failed. Propogating.", GetErrorMessage(r));
183         r = pArgList->Add(*pSyncLocationRequestInfo.get());
184         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Arraylist addition of an object failed. Propogating.", GetErrorMessage(r));
185
186         pSyncLocationRequestInfo.release();
187
188         r = SendUserEvent(REQ_ID_SYNC_LOC_RETRIEVAL, pArgList.get());
189         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to send the user event. Propagating.", GetErrorMessage(r));
190
191         pArgList.release();
192         return E_SUCCESS;
193
194 CATCH:
195         StopLocationUpdates(reqId);
196         return r;
197 }
198
199 Location
200 _LocationManager::GetLastKnownLocation(void)
201 {
202         Location location = _LocationImpl::GetLocationInstance();
203         Monitor synchronizer;
204         result r = synchronizer.Construct();
205         SysTryReturn(NID_LOC, r == E_SUCCESS, location, r, "[%s] Propogating.", GetErrorMessage(r));
206
207         std::unique_ptr< Tizen::Base::Collection::ArrayList > pArgList(new (std::nothrow) ArrayList());
208         SysTryReturn(NID_LOC, pArgList, location, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
209         r = pArgList->Construct();
210         SysTryReturn(NID_LOC, r == E_SUCCESS, location, r, "[%s] Propogating.", GetErrorMessage(r));
211
212         r = pArgList->Add(location);
213         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r));
214         r = pArgList->Add(synchronizer);
215         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r));
216
217         r = synchronizer.Enter();
218         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r));
219
220         r = SendUserEvent(REQ_ID_GET_LAST_LOCATION, pArgList.get());
221         SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r));
222         pArgList.release();
223
224         SysLog(NID_LOC, "Wait till location manager gets the last location.");
225         r = synchronizer.Wait();
226         SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r));
227         synchronizer.Exit();
228         SysLog(NID_LOC, "Last location(validity: %x, method: %ls) retrieved.", 
229                 location.IsValid(), location.GetExtraInfo(L"location_method").GetPointer());
230
231         return location;
232
233 CATCH:
234         pArgList->RemoveAll(false);
235         return location;
236 }
237
238 LocationAccuracy
239 _LocationManager::GetAccuracyLevel(double horAcc) const
240 {
241         if (horAcc <= 5.0)
242         {
243                 return LOC_ACCURACY_FINEST;
244         }
245         else if (horAcc <= 10.0)
246         {
247                 return LOC_ACCURACY_TEN_METERS;
248         }
249         else if (horAcc <= 100.0)
250         {
251                 return LOC_ACCURACY_HUNDRED_METERS;
252         }
253         else if (horAcc <= 1000.0)
254         {
255                 return LOC_ACCURACY_ONE_KILOMETER;
256         }
257         else if (horAcc <= 10000.0)
258         {
259                 return LOC_ACCURACY_ANY;
260         }
261         else
262         {
263                 return LOC_ACCURACY_INVALID;
264         }
265 }
266
267 bool
268 _LocationManager::IsAppEnabled(void)
269 {
270         SysTryReturn(NID_LOC, __waitLoopListener.GetValue(), false, E_SYSTEM, "[%s] Location manager is not initialized.", GetErrorMessage(E_SYSTEM));
271
272         Boolean enable(false);
273         Monitor synchronizer;
274         result r = synchronizer.Construct();
275         SysTryReturn(NID_LOC, r == E_SUCCESS, false, r, "[%s] Propogating.", GetErrorMessage(r));
276
277         std::unique_ptr< Tizen::Base::Collection::ArrayList > pArgList(new (std::nothrow) ArrayList());
278         SysTryReturn(NID_LOC, pArgList, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
279         r = pArgList->Construct();
280         SysTryReturn(NID_LOC, r == E_SUCCESS, false, r, "[%s] Propogating.", GetErrorMessage(r));
281
282         r = pArgList->Add(enable);
283         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r));
284         r = pArgList->Add(synchronizer);
285         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r));
286
287         r = synchronizer.Enter();
288         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Propogating", GetErrorMessage(r));
289
290         r = SendUserEvent(REQ_ID_GET_APP_ACCESSIBILITY, pArgList.get());
291         SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r));
292         pArgList.release();
293
294         SysLog(NID_LOC, "Wait till location manager checks if the app is allowed to use location.");
295         r = synchronizer.Wait();
296         SysTryCatch(NID_LOC, r == E_SUCCESS, synchronizer.Exit(), r, "[%s] Propogating", GetErrorMessage(r));
297         SysLog(NID_LOC, "Application setting state is '%ls'.", enable.ToString().GetPointer());
298         synchronizer.Exit();
299
300         return enable.ToBool();
301
302 CATCH:
303         return false;
304 }
305
306 _LocationManager*
307 _LocationManager::GetInstance(void)
308 {
309         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
310         if (__pUniqueInstance == null)
311         {
312                 ClearLastResult();
313                 pthread_once(&onceBlock, InitLocationManager);
314
315                 result r = GetLastResult();
316                 if (IsFailed(r))
317                 {
318                         onceBlock = PTHREAD_ONCE_INIT;
319                 }
320         }
321         return __pUniqueInstance;
322 }
323
324 void
325 _LocationManager::AddToLocRequestInfoList(const _LocationRequestInfo* pLocRequestInfo)
326 {
327         std::unique_ptr< _LocationRequestInfo > pNewLocRequestInfo(new (std::nothrow) _LocationRequestInfo(*pLocRequestInfo));
328         SysTryReturnVoidResult(NID_LOC, pNewLocRequestInfo, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
329         __pLocRequestInfoList->Add(*pNewLocRequestInfo.get());
330         pNewLocRequestInfo.release();
331
332         if (__minRequestedAccuracy == LOC_ACCURACY_INVALID)
333         {
334                 result r = _PowerManagerImpl::PowerControl(1, 1);
335                 SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Failed to keep the CPU in awake state.", GetErrorMessage(r));
336         }
337         SysLog(NID_LOC, "Total count of request info is (%d).", __pLocRequestInfoList->GetCount());
338         RestartLocationUpdates();
339         RestartUpdateTimer();
340 }
341
342 void
343 _LocationManager::RemoveFromLocRequestInfoList(RequestId reqId)
344 {
345         const int LIST_COUNT_ZERO = 0;
346         int count = __pLocRequestInfoList->GetCount();
347
348         for (int i = 0; i < count; i++)
349         {
350                 const _LocationRequestInfo* pLocRequestInfo = static_cast< const _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(i));
351                 if (reqId == pLocRequestInfo->GetRequestId())
352                 {
353                         __pLocRequestInfoList->RemoveAt(i);
354                         break;
355                 }
356         }
357         SysLog(NID_LOC, "Total count of request info is (%d).", __pLocRequestInfoList->GetCount());
358         if (__pLocRequestInfoList->GetCount() == LIST_COUNT_ZERO)
359         {
360                 _PowerManagerImpl::PowerControl(1, 0);
361
362                 __pLocUpdateTimer->Cancel();
363                 location_manager_stop(__gpsHandler.handle);
364                 location_manager_stop(__wpsHandler.handle);
365
366                 Reset();
367         }
368         else
369         {
370                 RestartLocationUpdates();
371                 RestartUpdateTimer();
372         }
373 }
374
375 void
376 _LocationManager::AddToSyncLocationRequestInfoList(_SyncLocationRequestInfo& syncLocRequestInfo)
377 {
378         static bool hasRetrievalStarted = false;
379
380         result r = __pSyncLocRequestInfoList->Add(syncLocRequestInfo);
381         SysTryCatch(NID_LOC, r == E_SUCCESS, , r, "[%s] Failed to add the sync request into the list.", GetErrorMessage(r));
382
383         if (hasRetrievalStarted == true)
384         {
385                 SysLog(NID_LOC, "The retrieval under process.");
386                 return;
387         }
388         while (__pSyncLocRequestInfoList->GetCount() != 0)
389         {
390                 hasRetrievalStarted = true;
391                 const int WAIT_TIME = 1000;
392                 WaitingLoop::GetInstance()->Wait(WAIT_TIME);
393
394                 int count = __pSyncLocRequestInfoList->GetCount();
395                 for (int i = 0; i < count; i++)
396                 {
397                         _SyncLocationRequestInfo* pSyncLocRequestInfo = static_cast< _SyncLocationRequestInfo* >(__pSyncLocRequestInfoList->GetAt(i));
398                         if (pSyncLocRequestInfo != null)
399                         {
400                                 SysLog(NID_LOC, "Handle the sync location request with request ID (%ld)", pSyncLocRequestInfo->GetRequestId());
401
402                                 HandleSyncRetrievalTimerExpiry(*pSyncLocRequestInfo);
403                         }
404                 }
405         }
406         hasRetrievalStarted = false;
407         return;
408
409 CATCH:
410         StopLocationUpdates(syncLocRequestInfo.GetRequestId());
411         syncLocRequestInfo.GetLocationMonitor()->Notify();
412         delete &syncLocRequestInfo;
413 }
414
415 void
416 _LocationManager::RemoveSyncLocRetrievalRequest(_SyncLocationRequestInfo& syncLocRequestInfo)
417 {
418         StopLocationUpdates(syncLocRequestInfo.GetRequestId());
419         __pSyncLocRequestInfoList->Remove(syncLocRequestInfo, true);
420 }
421
422 void
423 _LocationManager::RestartLocationUpdates(void)
424 {
425         int count = __pLocRequestInfoList->GetCount();
426         int result = 0;
427         bool isAccuracyChanged = false;
428
429         for (int i = 0; i < count; i++)
430         {
431                 const _LocationRequestInfo* pLocRequestInfo = static_cast< const _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(i));
432                 if (__minRequestedAccuracy > pLocRequestInfo->GetAccuracy() || __minRequestedAccuracy == LOC_ACCURACY_INVALID)
433                 {
434                         __minRequestedAccuracy = pLocRequestInfo->GetAccuracy();
435                         isAccuracyChanged = true;
436                 }
437         }
438         if (!isAccuracyChanged)
439         {
440                 return;
441         }
442         SysLog(NID_LOC, "Location updates are restarted and new minimum requested Accuracy is (%d).", __minRequestedAccuracy);
443
444         switch (__locMethodRequested)
445         {
446         case LOC_METHOD_REQUESTED_NONE:
447         {
448                 SysLog(NID_LOC, "None of the methods running. Start all");
449
450                 result = location_manager_start(__gpsHandler.handle);
451                 SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS.");
452
453                 result = location_manager_start(__wpsHandler.handle);
454                 SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS.");
455         }
456         break;
457
458         case LOC_METHOD_REQUESTED_GPS:
459         {
460                 SysLog(NID_LOC, "GPS Running. Start WPS.");
461
462                 result = location_manager_start(__wpsHandler.handle);
463                 SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for WPS.");
464         }
465         break;
466
467         case LOC_METHOD_REQUESTED_WPS:
468         {
469                 SysLog(NID_LOC, "WPS Running. Start GPS.");
470
471                 result = location_manager_start(__gpsHandler.handle);
472                 SysTryLog(NID_LOC, result == 0, "Failed to start the location updates for GPS.");
473         }
474         break;
475
476         case LOC_METHOD_REQUESTED_ALL:
477         {
478                 SysLog(NID_LOC, "All the providers are already started.");
479         }
480         break;
481         }
482
483         __locationMgrState = LOC_MGR_STATE_FAST_SENSING;
484         __locMethodRequested = LOC_METHOD_REQUESTED_ALL;
485 }
486
487 void
488 _LocationManager::RestartUpdateTimer(void)
489 {
490         int gcd = 1;
491         int count = __pLocRequestInfoList->GetCount();
492
493         __pLocUpdateTimer->Cancel();
494
495         if (count > 0)
496         {
497                 const _LocationRequestInfo* pLocRequestInfo = static_cast< _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(0));
498                 gcd = pLocRequestInfo->GetInterval();
499
500                 for (int i = 1; i < count; i++)
501                 {
502                         pLocRequestInfo = static_cast< const _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(i));
503                         int interval = pLocRequestInfo->GetInterval();
504                         if (gcd != interval)
505                         {
506                                 while (gcd != 0 && interval != 0)
507                                 {
508                                         ((gcd > interval) ? gcd : interval) %= ((gcd > interval) ? interval : gcd);
509                                 }
510                                 gcd += interval;
511                         }
512                 }
513         }
514         __timerInterval = gcd;
515         __timerTicks = 0;
516
517         SysLog(NID_LOC, "Updated Timer interval is (%d).", __timerInterval);
518         result r = __pLocUpdateTimer->Start(__timerInterval * 1000);
519         if (IsFailed(r))
520         {
521                 SysLog(NID_LOC, "Failed to start the Location update timer.");
522         }
523 }
524
525 void
526 _LocationManager::HandleSyncRetrievalTimerExpiry(_SyncLocationRequestInfo& syncLocRequestInfo)
527 {
528         LocationAccuracy accuracy = LOC_ACCURACY_INVALID;
529         DateTime timestamp = DateTime::GetMinValue();
530
531         Location location = GetRecentLocationAvailable();
532         SysLog(NID_LOC, "Location(timestamp: %ls, validity: %x, accuracy: %f) is retrieved.",
533                    location.GetTimestamp().ToString().GetPointer(), location.IsValid(), location.GetHorizontalAccuracy());
534         if (location.IsValid())
535         {
536                 accuracy = GetAccuracyLevel(location.GetHorizontalAccuracy());
537                 timestamp = location.GetTimestamp();
538         }
539
540         bool inTime = syncLocRequestInfo.IsInTime(timestamp);
541         bool accurate = syncLocRequestInfo.IsAccuracySatisfying(accuracy);
542         if (inTime && accurate)
543         {
544                 unique_ptr< Location > pLocation(new (std::nothrow) Location(location));
545                 SysTryCatchLabel(NID_LOC, pLocation != null, , NOTIFY, E_OUT_OF_MEMORY,
546                                                  "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
547                 syncLocRequestInfo.GetLocationMonitor()->SetLocation(pLocation.get());
548                 pLocation.release();
549
550                 goto NOTIFY;
551         }
552         if (syncLocRequestInfo.GetTickCount() > MAX_WAIT_TIME_FOR_SYNC_LOC)
553         {
554                 if (inTime)
555                 {
556                         unique_ptr< Location > pLocation(new (std::nothrow) Location(location));
557                         SysTryCatchLabel(NID_LOC, pLocation != null, , NOTIFY, E_OUT_OF_MEMORY,
558                                                          "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
559                         syncLocRequestInfo.GetLocationMonitor()->SetLocation(pLocation.get());
560                         pLocation.release();
561
562                         goto NOTIFY;
563                 }
564                 else
565                 {
566                         SysLog(NID_LOC, "Unable to fix the current location in %d ticks.", MAX_WAIT_TIME_FOR_SYNC_LOC);
567                         goto NOTIFY;
568                 }
569         }
570
571         SysLog(NID_LOC, "Wait for next location(Tick: %d).", syncLocRequestInfo.GetTickCount());
572         syncLocRequestInfo.IncrementTickCount();
573         return;
574
575 NOTIFY:
576         syncLocRequestInfo.GetLocationMonitor()->Notify();
577         RemoveSyncLocRetrievalRequest(syncLocRequestInfo);
578 }
579
580 result
581 _LocationManager::SetLocationInformation(double latitude, double longitude, double altitude, time_t timestamp, location_method_e locMethod, Location* pLocation)
582 {
583         SysSecureLog(NID_LOC, "Location Information is: Latitude (%lf), Longitude (%lf), Altitude (%lf), TimeStamp (%ld), Location method (%d)", latitude, longitude, altitude, timestamp, locMethod);
584
585         int res = -1;
586         LocationAccuracy requiredAcc;
587         int rangeValue = 0;
588
589         //Accuracy details.
590         location_accuracy_level_e accLevel = LOCATIONS_ACCURACY_NONE;
591         double horAcc = Tizen::Locations::NaN;
592         double verAcc = Tizen::Locations::NaN;
593
594         //Velocity details.
595         double climb = Tizen::Locations::NaN;
596         double direction = Tizen::Locations::NaN;
597         double speed = Tizen::Locations::NaN;
598         time_t time_stamp = 0;
599
600         RequestId requestId;
601         Location locationData = _LocationImpl::GetLocationInstance();
602         _LocationImpl* pLocDataImpl = _LocationImpl::GetInstance(locationData);
603
604         switch (locMethod)
605         {
606         case LOCATIONS_METHOD_GPS:
607         {
608                 res = location_manager_get_accuracy(__gpsHandler.handle, &accLevel, &horAcc, &verAcc);
609                 SysLog(NID_LOC, "Get Accuracy: Result (%d), Horizontal Acc (%lf), Vertical Acc (%lf)", res, horAcc, verAcc);
610                 SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "Invalid accuracy values from Native Location Provider.");
611
612                 res = location_manager_get_velocity(__gpsHandler.handle, &climb, &direction, &speed, &time_stamp);
613                 SysLog(NID_LOC, "Get Velocity: Result (%d), Climb (%lf), Direction (%lf), Speed (%lf), Time stamp (%ld)", res, climb, direction, speed, time_stamp);
614                 SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "Invalid accuracy values from Native Location Provider.");
615
616                 pLocDataImpl->SetExtraInfo(L"location_method", L"gps");
617                 requestId = REQ_ID_SUSTAIN_GPS;
618         }
619         break;
620
621         case LOCATIONS_METHOD_WPS:
622         {
623                 res = location_manager_get_accuracy(__wpsHandler.handle, &accLevel, &horAcc, &verAcc);
624                 SysLog(NID_LOC, "Get Accuracy: Result (%d), Horizontal Acc (%lf), Vertical Acc (%lf)", res, horAcc, verAcc);
625                 SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM, "Invalid accuracy values from Native Location Provider.");
626
627                 res = location_manager_get_velocity(__wpsHandler.handle, &climb, &direction, &speed, &time_stamp);
628                 SysTryLog(NID_LOC, res == 0, "Get Velocity: Result (%d), Climb (%lf), Direction (%lf), Speed (%lf), Time stamp (%ld)", res, climb, direction, speed, time_stamp);
629
630                 pLocDataImpl->SetExtraInfo(L"location_method", L"network");
631                 requestId = REQ_ID_SUSTAIN_WPS;
632         }
633         break;
634
635         default:
636                 SysTryReturn(NID_LOC, false, E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] The location method is not valid");
637         }
638
639         Coordinates coordinates;
640         coordinates.Set(latitude, longitude, altitude);
641         pLocDataImpl->SetCoordinates(coordinates);
642         pLocDataImpl->SetHorizontalAccuracy(horAcc);
643         pLocDataImpl->SetVerticalAccuracy(verAcc);
644         pLocDataImpl->SetTimestamp((long long) timestamp * 1000);
645         pLocDataImpl->SetCourse(direction);
646         pLocDataImpl->SetSpeed(speed);
647         pLocDataImpl->SetValidity(true);
648         *pLocation = locationData;
649
650         requiredAcc = __minRequestedAccuracy;
651         switch (requiredAcc)
652         {
653         case LOC_ACCURACY_FINEST:
654                 rangeValue = ACCURACY_FINEST;
655                 break;
656
657         case LOC_ACCURACY_TEN_METERS:
658                 rangeValue = ACCURACY_TEN_MTRS;
659                 break;
660
661         case LOC_ACCURACY_HUNDRED_METERS:
662                 rangeValue = ACCURACY_HUNDRED_MTRS;
663                 break;
664
665         case LOC_ACCURACY_ONE_KILOMETER:
666                 rangeValue = ACCURACY_ONE_KILOMETER;
667                 break;
668
669         case LOC_ACCURACY_ANY:
670                 rangeValue = ACCURACY_ANY;
671                 break;
672
673         case LOC_ACCURACY_INVALID:
674         // follow through
675         default:
676                 SysAssertf(false, "The Accuracy value is not defined.");
677         }
678
679         if (__locationMgrState == LOC_MGR_STATE_FAST_SENSING && horAcc <= rangeValue)
680         {
681                 SysLog(NID_LOC, "State is LOC_MGR_STATE_FAST_SENSING and accuracy is within range. RequestId is (%d)", requestId);
682                 __locationMgrState = LOC_MGR_STATE_FAST_SENSING_SETTLED;
683                 SendUserEvent(requestId, null);
684         }
685         else if (__locationMgrState == LOC_MGR_STATE_FAST_SENSING_SETTLED && horAcc > rangeValue)
686         {
687                 SysLog(NID_LOC, "State is LOC_MGR_STATE_FAST_SENSING_SETTLED and accuracy is out of range. Restart location updates.");
688                 SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null);
689         }
690         return E_SUCCESS;
691 }
692
693 void
694 _LocationManager::SendLocationCallbacks(void)
695 {
696         bool isAllowed = GetAppAccessibility();
697         const Location* pBestLocation = FindBestLocation();
698
699         SysLog(NID_LOC, "Send location(validity: %x) and accessibility(%x) through the callback.", pBestLocation->IsValid(), isAllowed);
700         unique_ptr< Location > pLocation(new (std::nothrow) Location(*pBestLocation));
701         SysTryReturnVoidResult(NID_LOC, pLocation != null, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
702
703         int interval = __timerTicks * __timerInterval;
704         for (int i = 0; i < __pLocRequestInfoList->GetCount(); i++)
705         {
706                 const _LocationRequestInfo* pLocRequestInfo = static_cast< const _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(i));
707                 if (interval % pLocRequestInfo->GetInterval() == 0 && pLocRequestInfo->GetListener() != null)
708                 {
709                         if (!isAllowed)
710                         {
711                                 _LocationImpl::GetInstance(*pLocation)->TurnOnDeniedFlag();
712                         }
713                         pLocRequestInfo->GetListener()->OnLocationUpdated(pLocRequestInfo->GetRequestId(), *pLocation.get());
714                 }
715         }
716 }
717
718 void
719 _LocationManager::Reset(void)
720 {
721         __locMethodRequested = LOC_METHOD_REQUESTED_NONE;
722         __locationMgrState = LOC_MGR_STATE_IDLE;
723         __minRequestedAccuracy = LOC_ACCURACY_INVALID;
724         __timerInterval = 0;
725         __timerTicks = 0;
726 }
727
728 result
729 _LocationManager::Construct()
730 {
731         return EventDrivenThread::Construct();
732 }
733
734 Location
735 _LocationManager::GetLastKnownLocation(location_method_e nativeLocMethod)
736 {
737         String locationMethod;
738         location_manager_h nativeHandle = null;
739         switch (nativeLocMethod)
740         {
741         case LOCATIONS_METHOD_GPS:
742         {
743                 nativeHandle = __gpsHandler.handle;
744                 locationMethod = L"gps";
745         }
746         break;
747
748         case LOCATIONS_METHOD_WPS:
749         {
750                 nativeHandle = __wpsHandler.handle;
751                 locationMethod = L"network";
752         }
753         break;
754
755         default:
756                 break;
757         }
758         SysLog(NID_LOC, "Last location requested(method: %x, handle: %x).", nativeLocMethod, nativeHandle);
759
760         Location location = _LocationImpl::GetLocationInstance();
761         if (nativeHandle != null)
762         {
763                 _LocationImpl* pLocationImpl = _LocationImpl::GetInstance(location);
764
765                 double altitude = Tizen::Locations::NaN;
766                 double latitude = Tizen::Locations::NaN;
767                 double longitude = Tizen::Locations::NaN;
768                 time_t timestampPosition = 0;
769
770                 int res = location_manager_get_last_position(nativeHandle, &altitude, &latitude, &longitude, &timestampPosition);
771                 SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to fetch last position from nativeHandle(%x).", nativeHandle);
772                 SysSecureLog(NID_LOC, "Last position(latitude: %lf, longitude: %lf, altitude: %lf, timestamp: %ld",
773                         latitude, longitude, altitude, timestampPosition);
774
775                 Coordinates coord;
776                 coord.Set(latitude, longitude, altitude);
777                 pLocationImpl->SetCoordinates(coord);
778
779                 double horAcc = Tizen::Locations::NaN;
780                 double verAcc = Tizen::Locations::NaN;
781                 location_accuracy_level_e level;
782                 res = location_manager_get_last_accuracy(nativeHandle, &level, &horAcc, &verAcc);
783                 if (res == 0)
784                 {
785                         SysLog(NID_LOC, "Last accuracy(horAcc: %lf, vAcc: %lf, level: %x)", horAcc, verAcc, level);
786                         pLocationImpl->SetHorizontalAccuracy(horAcc);
787                         pLocationImpl->SetVerticalAccuracy(verAcc);
788                 }
789
790                 double climb = Tizen::Locations::NaN;
791                 double direction = Tizen::Locations::NaN;
792                 double speed = Tizen::Locations::NaN;
793                 time_t timestampVelocity = 0;
794                 res = location_manager_get_last_velocity(nativeHandle, &climb, &direction, &speed, &timestampVelocity);
795                 if (res == 0)
796                 {
797                         SysLog(NID_LOC, "Last velocity(climb: %lf, direction: %lf, speed: %lf, timestamp: %ld)",
798                                 climb, direction, speed, timestampVelocity);
799                         pLocationImpl->SetCourse(direction);
800                         pLocationImpl->SetSpeed(speed);
801                 }
802
803                 if (nativeLocMethod == LOCATIONS_METHOD_GPS)
804                 {
805                         int satUsedCount = 0;
806                         int satViewCount = 0;
807                         time_t timestampSatellite = 0;
808                         String satInfo = L"";
809                         res = gps_status_get_last_satellite(nativeHandle, &satUsedCount, &satViewCount, &timestampSatellite);
810                         if (res == 0)
811                         {
812                                 long timeDiff = abs(timestampPosition - timestampSatellite);
813                                 res = gps_status_foreach_last_satellites_in_view(nativeHandle, SatelliteInfoUpdated, &satInfo);
814                                 SysLog(NID_LOC, "Last satellite(foreachResult: %d, inUse: %d, inView: %d, timestamp: %ld, timeDiff: %ld)",
815                                         res, satUsedCount, satViewCount, timestampSatellite, timeDiff);
816
817                                 satInfo.Trim();
818                                 SysLog(NID_LOC, "Last satellite(info: %ls)", satInfo.GetPointer());
819                                 pLocationImpl->SetExtraInfo(L"satellite", satInfo);
820                         }
821                 }
822                 pLocationImpl->SetTimestamp(((long long)timestampPosition) * 1000); // in milliseconds
823                 pLocationImpl->SetValidity(true);
824                 pLocationImpl->SetExtraInfo(L"location_method", locationMethod);
825         }
826
827         ClearLastResult();
828         return location;
829
830 CATCH:
831         return location;
832 }
833
834 Location
835 _LocationManager::GetRecentLocationAvailable(void)
836 {
837         long long gpsTimestamp = 0;
838         long long wpsTimestamp = 0;
839
840         Location lastGpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_GPS);
841         if (lastGpsLocation.IsValid())
842         {
843                 gpsTimestamp = _LocationImpl::GetInstance(lastGpsLocation)->GetTimestampInMs();
844         }
845
846         Location lastWpsLocation = GetLastKnownLocation(LOCATIONS_METHOD_WPS);
847         if (lastWpsLocation.IsValid())
848         {
849                 wpsTimestamp = _LocationImpl::GetInstance(lastWpsLocation)->GetTimestampInMs();
850         }
851
852         SysLog(NID_LOC, "Compare timestamp(gps: %lld, wps: %lld) for recent location.", gpsTimestamp, wpsTimestamp);
853         if (gpsTimestamp >= wpsTimestamp)
854         {
855                 return lastGpsLocation;
856         }
857         else
858         {
859                 return lastWpsLocation;
860         }
861 }
862
863 void 
864 _LocationManager::UpdateLocRequestInfoList(RequestId reqId, int interval)
865 {
866         int count = __pLocRequestInfoList->GetCount();
867
868         for (int i = 0; i < count; i++)
869         {
870                 _LocationRequestInfo* pLocRequestInfo = static_cast< _LocationRequestInfo* >(__pLocRequestInfoList->GetAt(i));
871                 if (reqId == pLocRequestInfo->GetRequestId())
872                 {
873                         pLocRequestInfo->SetInterval(interval);
874                         RestartUpdateTimer();
875                         break;
876                 }
877         }
878 }
879
880 const Location*
881 _LocationManager::FindBestLocation(void)
882 {
883         switch (__locMethodRequested)
884         {
885         case LOC_METHOD_REQUESTED_GPS:
886         {
887                 SysLog(NID_LOC, "GPS location provider running.");
888                 return __gpsHandler.pLocation.get();
889         }
890         break;
891
892         case LOC_METHOD_REQUESTED_WPS:
893         {
894                 SysLog(NID_LOC, "WPS location provider running.");
895                 return __wpsHandler.pLocation.get();
896         }
897         break;
898
899         case LOC_METHOD_REQUESTED_ALL:
900         {
901                 SysLog(NID_LOC, "All the methods are running. Get the best location among all the providers.");
902                 long long gpsTimestamp = 0;
903                 long long wpsTimestamp = 0;
904
905                 if (__gpsHandler.pLocation->IsValid() && !_LocationImpl::GetInstance(*__gpsHandler.pLocation)->IsDenied())
906                 {
907                         gpsTimestamp = _LocationImpl::GetInstance(*__gpsHandler.pLocation)->GetTimestampInMs();
908                 }
909                 if (__wpsHandler.pLocation->IsValid() && !_LocationImpl::GetInstance(*__wpsHandler.pLocation)->IsDenied())
910                 {
911                         wpsTimestamp = _LocationImpl::GetInstance(*__wpsHandler.pLocation)->GetTimestampInMs();
912                 }
913
914                 SysLog(NID_LOC, "Compare timestamp(gps: %lld, wps: %lld) of different locations.", gpsTimestamp, wpsTimestamp);
915                 if (gpsTimestamp > wpsTimestamp)
916                 {
917                         SysLog(NID_LOC, "GPS time stamp is greater than WPS.");
918                         return __gpsHandler.pLocation.get();
919                 }
920                 else if (wpsTimestamp > gpsTimestamp)
921                 {
922                         SysLog(NID_LOC, "WPS time stamp is greater than GPS.");
923                         return __wpsHandler.pLocation.get();
924                 }
925                 else if (gpsTimestamp == wpsTimestamp)
926                 {
927                         if (__gpsHandler.pLocation->GetHorizontalAccuracy() <= __wpsHandler.pLocation->GetHorizontalAccuracy())
928                         {
929                                 SysLog(NID_LOC, "GPS time stamp is equal to WPS and GPS accuracy is better than WPS.");
930                                 return __gpsHandler.pLocation.get();
931                         }
932                         else
933                         {
934                                 SysLog(NID_LOC, "WPS time stamp is equal to GPS but WPS accuracy is better than GPS.");
935                                 return __wpsHandler.pLocation.get();
936                         }
937                 }
938         }
939         break;
940
941         case LOC_METHOD_REQUESTED_NONE:
942         // follow through
943         default:
944                 SysLog(NID_LOC, "Location updates not running.");
945                 return null;
946         }
947
948         SysLog(NID_LOC, "Returning null as none of the conditions are satsfied.");
949         return null;
950 }
951
952 result
953 _LocationManager::GetLocation(location_method_e nativeLocMethod)
954 {
955         const int MAX_VALID_TIME_DIFFERENCE = 2000;
956         double altitude = 0.0;
957         double latitude = 0.0;
958         double longitude = 0.0;
959         time_t timestamp;
960         int res = -1;
961         int satellitesInViewCount = 0;
962         int satellitesInUseCount = 0;
963         time_t timestampSatellite = 0;
964         String satInfo = L"";
965         long long timeDiff = 0;
966         location_manager_h nativeHandle = null;
967         Location* pLocation = null;
968
969         switch (nativeLocMethod)
970         {
971         case LOCATIONS_METHOD_GPS:
972         {
973                 nativeHandle = __gpsHandler.handle;
974                 pLocation = __gpsHandler.pLocation.get();
975         }
976         break;
977
978         case LOCATIONS_METHOD_WPS:
979         {
980                 nativeHandle = __wpsHandler.handle;
981                 pLocation = __wpsHandler.pLocation.get();
982         }
983         break;
984
985         default:
986                 break;
987         }
988
989         res = location_manager_get_position(nativeHandle, &altitude, &latitude, &longitude, &timestamp);
990         SysTryReturnResult(NID_LOC, res == 0, E_SYSTEM,  "[E_SYSTEM] Failed to obtain the natvie location information for the method (%x)", nativeLocMethod);
991
992         if (res == 0)
993         {
994                 result r = SetLocationInformation(latitude, longitude, altitude, timestamp, nativeLocMethod, pLocation);
995                 if (r != E_SUCCESS)
996                 {
997                         SysLog(NID_LOC, "Failed to set the location information");
998                 }
999
1000                 if (nativeLocMethod == LOCATIONS_METHOD_GPS)
1001                 {
1002                         res = gps_status_get_satellite(__gpsHandler.handle, &satellitesInUseCount, &satellitesInViewCount, &timestampSatellite);
1003
1004                         timeDiff = abs(timestamp - timestampSatellite);
1005                         timeDiff = timeDiff * 1000;
1006                         SysLog(NID_LOC, "Result (%d), Satellites in Use (%d), Satellites in View (%d), Time stamp (%ld), Time Difference (Loc and Sat) (%ld)",
1007                                    res, satellitesInUseCount, satellitesInViewCount, timestampSatellite, timeDiff);
1008                         if (res == 0 && timeDiff <= MAX_VALID_TIME_DIFFERENCE)
1009                         {
1010                                 res = gps_status_foreach_satellites_in_view(__gpsHandler.handle, SatelliteInfoUpdated, &satInfo);
1011                         }
1012                         satInfo.Trim();
1013                         SysLog(NID_LOC, "Result of get satellite is (%d) and satelliteInfo string representation is (%ls)", res, satInfo.GetPointer());
1014                         _LocationImpl::GetInstance(*__gpsHandler.pLocation.get())->SetExtraInfo(L"satellite", satInfo);
1015                 }
1016         }
1017
1018         return E_SUCCESS;
1019 }
1020
1021 bool
1022 _LocationManager::OnStart(void)
1023 {
1024         int res = -1;
1025
1026         std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pLocInfoRequestList(new (std::nothrow) ArrayList());
1027         SysTryReturn(NID_LOC, pLocInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1028         result r = pLocInfoRequestList->Construct();
1029         SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the Location Request list.");
1030
1031         std::unique_ptr< Tizen::Base::Collection::ArrayList, AllElementsDeleter > pSyncLocInfoRequestList(new (std::nothrow) ArrayList());
1032         SysTryReturn(NID_LOC, pSyncLocInfoRequestList != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1033         r = pSyncLocInfoRequestList->Construct();
1034         SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the Sync Location Request list.");
1035
1036         unique_ptr< Tizen::Locations::Location > pGpsLocation(_LocationImpl::GetLocationInstanceN());
1037         SysTryReturn(NID_LOC, pGpsLocation != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1038         unique_ptr< Tizen::Locations::Location > pWpsLocation(_LocationImpl::GetLocationInstanceN());
1039         SysTryReturn(NID_LOC, pWpsLocation != null, false, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1040
1041         std::unique_ptr< Tizen::Base::Runtime::Timer > pLocUpdateTimer(new (std::nothrow) Timer());
1042         r = pLocUpdateTimer->Construct(*this);
1043         SysTryReturn(NID_LOC, r == E_SUCCESS, false, E_SYSTEM, "[E_SYSTEM] Failed to construct the location timer.");
1044
1045         res = location_manager_create(LOCATIONS_METHOD_GPS, &__gpsHandler.handle);
1046         SysTryReturn(NID_LOC, res == 0, false, E_SYSTEM, "[E_SYSTEM] Failed to create Native GPS Location provider.");
1047         res = location_manager_set_service_state_changed_cb(__gpsHandler.handle, GpsServiceUpdateCallback, this);
1048         SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native GPS Location provider.");
1049
1050         res = location_manager_create(LOCATIONS_METHOD_WPS, &__wpsHandler.handle);
1051         SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to create Native WPS Location provider.");
1052         res = location_manager_set_service_state_changed_cb(__wpsHandler.handle, WpsServiceUpdateCallback, this);
1053         SysTryCatch(NID_LOC, res == 0, , E_SYSTEM, "[E_SYSTEM] Failed to register service callback for Native WPS Location provider.");
1054
1055         __pLocRequestInfoList = std::move(pLocInfoRequestList);
1056         __pSyncLocRequestInfoList = std::move(pSyncLocInfoRequestList);
1057         __pLocUpdateTimer = std::move(pLocUpdateTimer);
1058         __gpsHandler.pLocation= std::move(pGpsLocation);
1059         __wpsHandler.pLocation= std::move(pWpsLocation);
1060
1061         __waitLoopListener.SetValue(true);
1062         SysLog(NID_LOC, "All the resources for location manager successfully created.");
1063         return true;
1064
1065 CATCH:
1066         if (__gpsHandler.handle)
1067         {
1068                 location_manager_destroy(__gpsHandler.handle);
1069         }
1070
1071         if (__wpsHandler.handle)
1072         {
1073                 location_manager_destroy(__wpsHandler.handle);
1074         }
1075         return false;
1076 }
1077
1078 void
1079 _LocationManager::OnStop(void)
1080 {
1081         __waitLoopListener.SetValue(false);
1082
1083         if (__gpsHandler.handle)
1084         {
1085                 location_manager_destroy(__gpsHandler.handle);
1086         }
1087         if (__wpsHandler.handle)
1088         {
1089                 location_manager_destroy(__wpsHandler.handle);
1090         }
1091 }
1092
1093 void
1094 _LocationManager::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
1095 {
1096         const int ARRAY_LIST_CAPACITY = 1;
1097
1098         switch (requestId)
1099         {
1100         case REQ_ID_START_LOC_UPDATES:
1101         {
1102                 SysLog(NID_LOC, "REQ_ID_START_LOC_UPDATES");
1103                 SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored.");
1104                 _LocationRequestInfo* pLocRequestInfo = null;
1105                 SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_CAPACITY, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1106                 pLocRequestInfo = static_cast< _LocationRequestInfo* >(pArgs->GetAt(0));
1107                 SysTryCatch(NID_LOC, pLocRequestInfo, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1108
1109                 AddToLocRequestInfoList(pLocRequestInfo);
1110         }
1111         break;
1112
1113         case REQ_ID_STOP_LOC_UPDATES:
1114         {
1115                 SysLog(NID_LOC, "REQ_ID_STOP_LOC_UPDATES");
1116                 SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored.");
1117                 Integer* pReqId = null;
1118                 SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_CAPACITY, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1119                 pReqId = static_cast< Integer* >(pArgs->GetAt(0));
1120                 SysTryCatch(NID_LOC, pReqId, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1121
1122                 RemoveFromLocRequestInfoList(static_cast< long >(pReqId->ToInt()));
1123         }
1124         break;
1125
1126         case REQ_ID_RESTART_LOC_UPDATES:
1127         {
1128                 SysLog(NID_LOC, "REQ_ID_RESTART_LOC_UPDATES.");
1129                 RestartLocationUpdates();
1130         }
1131         break;
1132
1133         case REQ_ID_SUSTAIN_GPS:
1134         {
1135                 SysLog(NID_LOC, "REQ_ID_SUSTAIN_GPS.");
1136                 location_manager_stop(__wpsHandler.handle);
1137                 __locMethodRequested = LOC_METHOD_REQUESTED_GPS;
1138         }
1139         break;
1140
1141         case REQ_ID_SUSTAIN_WPS:
1142         {
1143                 SysLog(NID_LOC, "REQ_ID_SUSTAIN_WPS.");
1144                 location_manager_stop(__gpsHandler.handle);
1145                 __locMethodRequested = LOC_METHOD_REQUESTED_WPS;
1146         }
1147         break;
1148
1149         case REQ_ID_SYNC_LOC_RETRIEVAL:
1150         {
1151                 SysLog(NID_LOC, "REQ_ID_SYNC_LOC_RETRIEVAL.");
1152                 SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored.");
1153                 _SyncLocationRequestInfo* pSyncLocRequestInfo = null;
1154                 SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_CAPACITY, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1155                 pSyncLocRequestInfo = static_cast< _SyncLocationRequestInfo* >(pArgs->GetAt(0));
1156                 SysTryCatch(NID_LOC, pSyncLocRequestInfo, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1157
1158                 AddToSyncLocationRequestInfoList(*pSyncLocRequestInfo);
1159                 pArgs->RemoveAt(0);
1160         }
1161         break;
1162
1163         case REQ_ID_GET_APP_ACCESSIBILITY:
1164         {
1165                 SysLog(NID_LOC, "REQ_ID_GET_APP_ACCESSIBILITY");
1166                 SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored.");
1167
1168                 Boolean* pEnabled = static_cast< Boolean* >(pArgs->GetAt(0));
1169                 Monitor* pMonitor = static_cast< Monitor* >(pArgs->GetAt(1));
1170                 SysAssertf(pEnabled != null && pMonitor != null, "Invalid request has been made on the location manager.");
1171                 if (pMonitor != null)
1172                 {
1173                         pMonitor->Enter();
1174                         if (pEnabled != null)
1175                         {
1176                                 pEnabled->value = GetAppAccessibility();
1177                         }
1178                         pMonitor->Notify();
1179                         pMonitor->Exit();
1180                 }
1181                 pArgs->RemoveAt(1);
1182                 pArgs->RemoveAt(0);
1183         }
1184         break;
1185
1186         case REQ_ID_GET_LAST_LOCATION:
1187         {
1188                 SysLog(NID_LOC, "REQ_ID_GET_LAST_LOCATION");
1189                 SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored.");
1190
1191                 Location* pLocation = static_cast< Location* >(pArgs->GetAt(0));
1192                 Monitor* pMonitor = static_cast< Monitor* >(pArgs->GetAt(1));
1193                 SysAssertf(pLocation != null && pMonitor != null, "Invalid request has been made on the location manager.");
1194                 if (pMonitor != null)
1195                 {
1196                         pMonitor->Enter();
1197                         if (pLocation != null)
1198                         {
1199                                 *pLocation = GetRecentLocationAvailable();
1200                         }
1201                         pMonitor->Notify();
1202                         pMonitor->Exit();
1203                 }
1204                 pArgs->RemoveAt(1);
1205                 pArgs->RemoveAt(0);
1206         }
1207         break;
1208
1209         case REQ_ID_UPDATE_INTERVAL:
1210         {
1211                 const int ARRAY_LIST_LENGTH = 2;
1212
1213                 SysLog(NID_LOC, "REQ_ID_UPDATE_INTERVAL");
1214                 SysTryReturnVoidResult(NID_LOC, pArgs, E_INVALID_ARG, "[E_INVALID_ARG] Null argument encountered. Ignored.");
1215                 SysTryCatch(NID_LOC, pArgs->GetCount() == ARRAY_LIST_LENGTH, pArgs->RemoveAll(true), E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1216
1217                 Integer* pReqId = null;
1218                 pReqId = static_cast< Integer* >(pArgs->GetAt(0));
1219                 SysTryCatch(NID_LOC, pReqId, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1220
1221                 Integer* pInterval = null;
1222                 pInterval = static_cast< Integer* >(pArgs->GetAt(1));
1223                 SysTryCatch(NID_LOC, pInterval, , E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument encountered. Ignored.");
1224
1225                 UpdateLocRequestInfoList(static_cast< long >(pReqId->ToInt()), pInterval->ToInt());
1226         }
1227         break;
1228
1229         }
1230
1231         if (pArgs)
1232         {
1233                 pArgs->RemoveAll(true);
1234                 delete pArgs;
1235         }
1236
1237         return;
1238
1239 CATCH:
1240         pArgs->RemoveAll(true);
1241         delete pArgs;
1242 }
1243
1244 void
1245 _LocationManager::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
1246 {
1247         if (__pLocUpdateTimer->Equals(timer))
1248         {
1249                 __timerTicks++;
1250                 SysLog(NID_LOC, "LocationManager update timer expired. Timer Tick value is (%d).", __timerTicks);
1251                 result r = E_SUCCESS;
1252
1253                 switch (__locMethodRequested)
1254                 {
1255                 case LOC_METHOD_REQUESTED_GPS:
1256                 {
1257                         r = GetLocation(LOCATIONS_METHOD_GPS);
1258                         SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information");
1259                         if (IsFailed(r))
1260                         {
1261                                 SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null);
1262                         }
1263                 }
1264                 break;
1265
1266                 case LOC_METHOD_REQUESTED_WPS:
1267                 {
1268                         r = GetLocation(LOCATIONS_METHOD_WPS);
1269                         SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the WPS location information");
1270                         if (IsFailed(r))
1271                         {
1272                                 SendUserEvent(REQ_ID_RESTART_LOC_UPDATES, null);
1273                         }
1274                 }
1275                 break;
1276
1277                 case LOC_METHOD_REQUESTED_ALL:
1278                 {
1279                         if (__wpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED)
1280                         {
1281                                 r = GetLocation(LOCATIONS_METHOD_WPS);
1282                                 SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the WPS location information");
1283                         }
1284                         else
1285                         {
1286                                 SysLog(NID_LOC, "WPS Location not available at the Native side.");
1287                         }
1288
1289                         if (__gpsHandler.serviceState == LOCATIONS_SERVICE_ENABLED)
1290                         {
1291                                 r = GetLocation(LOCATIONS_METHOD_GPS);
1292                                 SysTryLog(NID_LOC, r == E_SUCCESS, "[E_SYSTEM] Failed to obtain the GPS location information");
1293                         }
1294                         else
1295                         {
1296                                 SysLog(NID_LOC, "GPS Location not available at the Native side.");
1297                         }
1298                 }
1299                 break;
1300
1301                 case LOC_METHOD_REQUESTED_NONE:
1302                 // follow through
1303                 default:
1304                         SysLog(NID_LOC, "Timer expired when no location update is called.");
1305                         return;
1306                 }
1307
1308                 __pLocUpdateTimer->Start(__timerInterval * 1000);
1309                 SendLocationCallbacks();
1310         }
1311
1312         return;
1313 }
1314
1315 bool
1316 _LocationManager::SatelliteInfoUpdated(unsigned int azimuth, unsigned int elevation, unsigned int prn, int snr, bool is_active, void* user_data)
1317 {
1318
1319         if (user_data == null)
1320         {
1321                 SysLog(NID_LOC, "User data Null. Return.");
1322                 return true;
1323         }
1324
1325         String* pSatInfo = static_cast< String* >(user_data);
1326         SysLog(NID_LOC, "GPS Position Satellite Info: SatID (%d), Used (%d), Elevation (%d), Azimuth (%d), Snr (%d).", prn, is_active, elevation, azimuth, snr);
1327
1328         pSatInfo->Append(static_cast< int >(prn));
1329         pSatInfo->Append(", ");
1330         pSatInfo->Append(static_cast< int >(elevation));
1331         pSatInfo->Append(", ");
1332         pSatInfo->Append(static_cast< int >(azimuth));
1333         pSatInfo->Append(", ");
1334         pSatInfo->Append(snr);
1335         pSatInfo->Append(", ");
1336         pSatInfo->Append(is_active);
1337         pSatInfo->Append("; ");
1338
1339         return true;
1340 }
1341
1342 void
1343 _LocationManager::GpsServiceUpdateCallback(location_service_state_e state, void* user_data)
1344 {
1345         SysLog(NID_LOC, "Updated State is (%d).", state);
1346         if (user_data == null)
1347         {
1348                 SysLog(NID_LOC, "User data is null. Return");
1349                 return;
1350         }
1351
1352         _LocationManager* pThis = static_cast< _LocationManager* >(user_data);
1353         pThis->__gpsHandler.serviceState = state;
1354 }
1355
1356 void
1357 _LocationManager::WpsServiceUpdateCallback(location_service_state_e state, void* user_data)
1358 {
1359         SysLog(NID_LOC, "Updated State is (%d).", state);
1360         if (user_data == null)
1361         {
1362                 SysLog(NID_LOC, "User data is null. Return");
1363                 return;
1364         }
1365
1366         _LocationManager* pThis = static_cast< _LocationManager* >(user_data);
1367         pThis->__wpsHandler.serviceState = state;
1368 }
1369
1370 void
1371 _LocationManager::InitLocationManager(void)
1372 {
1373         SysLog(NID_LOC, "Creating the first location manager instance.");
1374
1375         unique_ptr< _LocationManager > pLocMgr(new (std::nothrow) _LocationManager());
1376         SysTryReturnVoidResult(NID_LOC, pLocMgr, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(E_OUT_OF_MEMORY));
1377         result r = pLocMgr->Construct();
1378         SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Falied to construct the Location Manager. Propagating.", GetErrorMessage(r));
1379         r = pLocMgr->Start();
1380         SysTryReturnVoidResult(NID_LOC, r == E_SUCCESS, r, "[%s] Falied to start the Location Manager. Propagating.", GetErrorMessage(r));
1381
1382         WaitingLoop::GetInstance()->Wait(*pLocMgr->GetWaitLoopListener());
1383
1384         __pUniqueInstance = pLocMgr.release();
1385         std::atexit(DestroyLocationManager);
1386 }
1387
1388 void
1389 _LocationManager::DestroyLocationManager(void)
1390 {
1391         delete __pUniqueInstance;
1392 }
1393
1394 bool
1395 _LocationManager::GetAppAccessibility(void)
1396 {
1397         int res = 0;
1398         static bool appRegistered = false;
1399         if (!appRegistered)
1400         {
1401                 static const char COMMAND_REGISTER_APP[] = "ADD_APPLIST";
1402                 if (location_manager_send_command(COMMAND_REGISTER_APP) == LOCATIONS_ERROR_NONE)
1403                 {
1404                         static const char COMMAND_ENABLE_APP[] = "ACCESSIBILITY:1";
1405                         res = location_manager_send_command(COMMAND_ENABLE_APP);
1406                         SysTryReturn(NID_LOC, res == 0, false, E_SYSTEM,
1407                                                  "[%s] Failed to register the application.", GetErrorMessage(E_SYSTEM));
1408                         appRegistered = true;
1409                 }
1410         }
1411
1412         location_accessibility_state_e accessState;
1413         res = location_manager_get_accessibility_state(&accessState);
1414         SysTryReturn(NID_LOC, res == 0, false, E_SYSTEM,
1415                                  "[%s] Failed to get the application location setting.", GetErrorMessage(E_SYSTEM));
1416
1417         return (accessState == LOCATIONS_ACCESS_STATE_ALLOWED) ? true : false;
1418 }
1419 }}