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