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