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