move provider state to state of _AppContext [Nabi 45218]
[framework/osp/appwidget-service.git] / src / FShell_AppWidgetContext.cpp
1 //
2 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.1 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file        FShell_AppWidgetContext.cpp
19  * @brief       This is the implementation for the _AppWidgetContext class.
20  */
21
22 #include <provider.h>
23 #include <unique_ptr.h>
24
25 #include <FBaseSysLog.h>
26 #include <FBaseInteger.h>
27 #include <FBaseDouble.h>
28 #include <FBaseColHashMap.h>
29 #include <FBaseColAllElementsDeleter.h>
30 #include <FSysSystemTime.h>
31 #include <FAppAppManager.h>
32
33 #include <FBase_StringConverter.h>
34 #include "FShell_AppWidgetManagerService.h"
35 #include "FShell_AppWidgetPopupContext.h"
36 #include "FShell_AppWidgetContext.h"
37 #include "FShell_AppWidgetContextHelper.h"
38
39 namespace Tizen { namespace Shell  { namespace App
40 {
41
42 using namespace std;
43 using namespace Tizen::App;
44 using namespace Tizen::Base;
45 using namespace Tizen::Base::Collection;
46 using namespace Tizen::System;
47
48 const String APPWIDGET_ON_ADD = L"http://tizen.org/appcontrol/appwidget/add";
49 const String APPWIDGET_ON_REMOVE = L"http://tizen.org/appcontrol/appwidget/remove";
50 const String APPWIDGET_ON_UPDATE = L"http://tizen.org/appcontrol/appwidget/update";
51 const String APPWIDGET_ON_RESIZE = L"http://tizen.org/appcontrol/appwidget/resize";
52 const String APPWIDGET_ON_TOUCH = L"http://tizen.org/appcontrol/appwidget/touch";
53
54 const int UPDATE_PERIOD_MSEC_MIN = 1800000;     // 30min
55
56 _AppWidgetContext::_AppWidgetContext(_AppContext* pAppContext, const String& info, const String& providerId, const String& instanceId, int width, int height, int period, int priority)
57         :_AppWidgetContextBase(TYPE_LB, info, providerId, instanceId, width, height, priority)
58         ,__pAppWidgetPopup(null)
59         ,__updateMillis(period)
60         ,__lastUpdatedTime(0)
61         ,__pPendingTouchEventList(null)
62         ,__hasPendingRequest(false)
63         ,__pAppContext(pAppContext)
64         ,__pPendingEventList(null)
65 {
66         // for updating period
67         if (__updateMillis > 0)
68         {
69                 __updateMillis = (__updateMillis > UPDATE_PERIOD_MSEC_MIN) ? __updateMillis : UPDATE_PERIOD_MSEC_MIN;
70                 SysLog(NID_SHELL, "period(%d)", __updateMillis);
71
72                 SystemTime::GetTicks(this->__lastUpdatedTime);
73
74                 __updateTimer.Construct(*this);
75                 __updateTimer.StartAsRepeatable(__updateMillis);
76         }
77
78         __pPendingTouchEventList = new (nothrow) ArrayListT<PendingTouchEvent*>();
79         __pPendingTouchEventList->Construct();
80
81         __pPendingEventList = new (nothrow) ArrayListT<PendingEvent*>();
82         __pPendingEventList->Construct();
83 }
84
85 _AppWidgetContext::~_AppWidgetContext(void)
86 {
87         SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), GetHeight(), GetPriority());
88
89         __updateTimer.Cancel();
90
91         if (__pAppWidgetPopup)
92         {
93                 SysLog(NID_SHELL, "Destroying dangling AppWidgetPopup instance..");
94                 __pAppWidgetPopup->OnPopupDestoyed();
95                 delete __pAppWidgetPopup;
96         }
97
98         if (__pPendingTouchEventList)
99         {
100                 for (int i = 0; i < __pPendingTouchEventList->GetCount(); i++)
101                 {
102                         PendingTouchEvent* pTouchEvent = null;
103                         __pPendingTouchEventList->GetAt(i, pTouchEvent);
104                         delete pTouchEvent;
105                 }
106                 __pPendingTouchEventList->RemoveAll();
107                 delete __pPendingTouchEventList;
108         }
109
110         if (__pPendingEventList)
111         {
112                 for (int i = 0; i < __pPendingEventList->GetCount(); i++)
113                 {
114                         PendingEvent* pEvent = null;
115                         __pPendingEventList->GetAt(i, pEvent);
116                         delete pEvent;
117                 }
118                 __pPendingEventList->RemoveAll();
119                 delete __pPendingEventList;
120         }
121 }
122
123 _AppContext*
124 _AppWidgetContext::GetAppContext(void) const
125 {
126         return __pAppContext;
127 }
128
129 _AppWidgetPopupContext*
130 _AppWidgetContext::GetAppWidgetPopup(void) const
131 {
132         return __pAppWidgetPopup;
133 }
134
135 void
136 _AppWidgetContext::OnAdded(void)
137 {
138         SendAddRequest(GetWidth(), GetHeight());
139 }
140
141 result
142 _AppWidgetContext::OnRemoved(void)
143 {
144         return SendRemoveRequest();
145 }
146
147 void
148 _AppWidgetContext::OnUpdate(const String& argument)
149 {
150         ClearLastResult();
151
152         AppWidgetManagerService* pMgrService = AppWidgetManagerService::GetInstance();
153         SysTryReturnVoidResult(NID_SHELL, pMgrService, E_SYSTEM, "[E_SYSTEM] Failed to get an instance of AppWidgetManagerService.");
154
155         // Queueing the pointer of paused context.
156         if (this->IsPaused())
157         {
158                 // Saving the data
159                 if (!argument.IsEmpty())
160                 {
161                         __pendingArgument = argument;
162                 }
163
164                 __hasPendingRequest = true;
165                 SysLog(NID_SHELL, "Update is requested but the %ls is paused.", (this->GetAppId()).GetPointer());
166         }
167         else
168         {
169                 result r = this->SendUpdateRequest(GetWidth(), GetHeight(), argument);
170                 SysTryLog(NID_SHELL, !IsFailed(r), "Failed to execute SendUpdateRequest.");
171
172                 SystemTime::GetTicks(this->__lastUpdatedTime);
173                 SysLog(NID_SHELL, "The last updated time is %lld.", this->__lastUpdatedTime);
174
175                 __hasPendingRequest = false;
176                 __pendingArgument.Clear();
177         }
178 }
179
180 void
181 _AppWidgetContext::OnResize(int width, int height)
182 {
183         SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), GetHeight(), GetPriority());
184
185         SetWidth(width);
186         SetHeight(height);
187
188         SendResizeRequest(width, height);
189 }
190
191 result
192 _AppWidgetContext::RequestUpdate(const String& argument)
193 {
194         AppWidgetManagerService* pMgrService = AppWidgetManagerService::GetInstance();
195         SysTryReturnResult(NID_SHELL, pMgrService, E_SYSTEM, "[E_SYSTEM] Failed to get an instance of AppWidgetManagerService.");
196
197         result r = pMgrService->RequestUpdate(this, argument);
198         SysTryReturnResult(NID_SHELL, !IsFailed(r), r, "Failed to request update.");
199
200         return r;
201 }
202
203 void
204 _AppWidgetContext::OnForeground(void)
205 {
206         SysLog(NID_SHELL, "I");
207
208         if (!IsPaused())
209         {
210                 SysLog(NID_SHELL, "%ls is already resumed.", (this->GetAppId()).GetPointer());
211                 return;
212         }
213
214         this->SetForeground(true);
215
216         if (__hasPendingRequest == true)
217         {
218                 RequestUpdate(__pendingArgument);
219         }
220         else
221         {
222                 if (this->GetPeriod() > 0)
223                 {
224                         long long currentTicks = 0;
225                         SystemTime::GetTicks(currentTicks);
226
227                         SysLog(NID_SHELL, "current[%lld] - updatedTime[%lld] = [%lld], period[%d]",
228                                         currentTicks, this->GetLastUpdatedTime(), currentTicks - this->GetLastUpdatedTime(), this->GetPeriod());
229
230                         bool isPeriodExpired = (currentTicks - this->GetLastUpdatedTime()) >= (this->GetPeriod());
231                         if (isPeriodExpired)
232                         {
233                                 SysLog(NID_SHELL, "The period is expired.");
234                                 RequestUpdate(L"");
235                         }
236                 }
237         }
238
239         SysLog(NID_SHELL, "O");
240 }
241
242 void
243 _AppWidgetContext::OnBackground(void)
244 {
245         SysLog(NID_SHELL, "OnBackground");
246
247         if (IsPaused())
248         {
249                 SysLog(NID_SHELL, "%ls is already paused.", (this->GetAppId()).GetPointer());
250                 return;
251         }
252         SetForeground(false);
253 }
254
255 bool
256 _AppWidgetContext::IsPaused(void) const
257 {
258         return IsForeground() ? false : true;
259 }
260
261 void
262 _AppWidgetContext::OnPopupCreated(double x, double y, int width, int height)
263 {
264         __pAppWidgetPopup = new (nothrow) _AppWidgetPopupContext(GetUserInfo(), GetProviderId(), GetInstanceId(), GetWidth(), GetHeight(), GetPriority(), this);
265         __pAppWidgetPopup->OnPopupCreated(x, y, width, height);
266 }
267
268 void
269 _AppWidgetContext::OnPopupDestoyed(void)
270 {
271         SysLog(NID_SHELL, "");
272
273         if (__pAppWidgetPopup)
274         {
275                 __pAppWidgetPopup->OnPopupDestoyed();
276                 delete __pAppWidgetPopup;
277                 __pAppWidgetPopup = null;
278         }
279 }
280
281 result
282 _AppWidgetContext::SendAddRequest(int width, int height)
283 {
284         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
285
286         return SendRequestToApp(GetAppId(), APPWIDGET_ON_ADD, pArgs.release());
287 }
288
289 result
290 _AppWidgetContext::SendUpdateRequest(int width, int height, const String& argument)
291 {
292         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
293
294         pArgs->Add(new (nothrow) String(ARG_KEY_ARGUMENT), new (nothrow) String(argument));
295
296         return SendRequestToApp(GetAppId(), APPWIDGET_ON_UPDATE, pArgs.release());
297 }
298
299 result
300 _AppWidgetContext::SendResizeRequest(int width, int height)
301 {
302         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
303
304         return SendRequestToApp(GetAppId(), APPWIDGET_ON_RESIZE, pArgs.release());
305 }
306
307 result
308 _AppWidgetContext::SendRemoveRequest(void)
309 {
310         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
311
312         return SendRequestToApp(GetAppId(), APPWIDGET_ON_REMOVE, pArgs.release());
313 }
314
315 result
316 _AppWidgetContext::SendPendingEvent(void)
317 {
318         SysTryReturnResult(NID_SHELL, __pPendingEventList->GetCount() > 0 , E_DATA_NOT_FOUND, "There is no pending event.");
319
320         result r = E_SUCCESS;
321         PendingEvent* pEvent = null;
322         __pPendingEventList->GetAt(0, pEvent);
323
324         if (pEvent != null)
325         {
326                 SysLog(NID_SHELL, "SendPendingEvent by IPC [%d existed.]", __pPendingEventList->GetCount());
327                 r = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), pEvent->operation, pEvent->pArg);
328
329                 result r1 = __pPendingEventList->RemoveAt(0);
330                 SysTryLog(NID_SHELL, !IsFailed(r1), "Failed to remove the context.");
331                 delete pEvent;
332
333                 SysTryReturnResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "SendIpcRequest failed.");
334         }
335         else
336         {
337                 SysLog(NID_SHELL, "SendPendingEvent by IPC [0 existed.]");
338                 r = E_OBJ_NOT_FOUND;
339         }
340
341         return r;
342 }
343
344 void
345 _AppWidgetContext::SendPendingTouchEvent(void)
346 {
347         for (int i =0; i< __pPendingTouchEventList->GetCount(); i++)
348         {
349                 PendingTouchEvent* pTouchEvent = null;
350                 __pPendingTouchEventList->GetAt(i, pTouchEvent);
351                 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), pTouchEvent->eventType, pTouchEvent->timeStamp, pTouchEvent->x, pTouchEvent->y);
352                 delete pTouchEvent;
353         }
354         __pPendingTouchEventList->RemoveAll();
355 }
356
357 result
358 _AppWidgetContext::SendTouchEvent(buffer_event eventType, double timeStamp, double x, double y)
359 {
360         if (__pAppContext->GetConnectionState() == _AppContext::CONNECTED && IsRemoteBufferCreated())
361         {
362                 SysAssert(IsSharedMemCreated() == true);
363                 SysLog(NID_SHELL, "%d, %f, %f", eventType, x, y);
364                 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), eventType, timeStamp, x, y);
365         }
366         else
367         {
368                 __pPendingTouchEventList->Add(new (nothrow) PendingTouchEvent(eventType, timeStamp, x, y));
369
370                 if( AppManager::GetInstance()->IsRunning(this->GetAppId() ) == false)
371                 {
372                         SysLog(NID_SHELL, "request to start AppControl");
373                         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
374
375                         // TODO: consider to remove these unused args.
376                         pArgs->Add(new (nothrow) String(ARG_KEY_EVENT_TYPE), new (nothrow) String(Integer::ToString(eventType)));
377                         pArgs->Add(new (nothrow) String(ARG_KEY_TIME_STAMP), new (nothrow) String(Double::ToString(timeStamp)));
378                         pArgs->Add(new (nothrow) String(ARG_KEY_X), new (nothrow) String(Double::ToString(x)));
379                         pArgs->Add(new (nothrow) String(ARG_KEY_Y), new (nothrow) String(Double::ToString(y)));
380
381                         return SendRequestToApp(GetAppId(), APPWIDGET_ON_TOUCH, pArgs.get());
382                 }
383         }
384         return E_SUCCESS;
385 }
386
387 result
388 _AppWidgetContext::SendRequestToApp(const AppId& appId, const String& operation, HashMap* pArgs)
389 {
390         result r = E_SUCCESS;
391
392         if ( __pAppContext->GetConnectionState() == _AppContext::NONE || __pAppContext->GetConnectionState() == _AppContext::DISCONNECTED)
393         {
394                 SysLog(NID_SHELL, "The application is not running.");
395                 result r = _AppWidgetContextBase::SendRequestToApp(appId, operation, pArgs);
396                 SysTryReturn(NID_SHELL, !IsFailed(r), r, r, "[%s] Failed to SendRequestToApp", GetErrorMessage(r));
397
398                 __pAppContext->__isWaitingResult = true;
399                 __pAppContext->SetConnectionState(_AppContext::CONNECTING);
400         }
401         else
402         {
403                 if ( __pAppContext->GetConnectionState() == _AppContext::CONNECTING || __pAppContext->__isWaitingResult == true)
404                 {
405                         SysLog(NID_SHELL, "The application is running but IPC is not connected yet.");
406                         __pPendingEventList->Add(new (nothrow) PendingEvent(operation, pArgs));
407                 }
408                 else
409                 {
410                         SysLog(NID_SHELL, "The application is running and IPC is connected.");
411                         r  = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), operation, pArgs);
412
413                         pArgs->RemoveAll(true);
414                         delete pArgs;
415                         __pAppContext->__isWaitingResult = true;
416                 }
417         }
418
419         return E_SUCCESS;
420 }
421
422 result
423 _AppWidgetContext::RequestUpdateRemote(int width, int height)
424 {
425         std::unique_ptr<char[]> packageName(_StringConverter::CopyToCharArrayN(GetProviderId()));
426         std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
427         std::unique_ptr<char[]> content_info(_StringConverter::CopyToCharArrayN(GetUserInfo()));
428
429         int ret = provider_send_updated(packageName.get(), id.get(), width, height, GetPriority(), content_info.get(), null);
430         SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "[E_SYSTEM] failed to provider_send_updated");
431
432         SendPendingTouchEvent();
433         SysLog(NID_SHELL, "Done");
434         return E_SUCCESS;
435 }
436
437 result
438 _AppWidgetContext::SendAccessStatus(int accessStatus)
439 {
440         std::unique_ptr<char[]> packageName(_StringConverter::CopyToCharArrayN(GetProviderId()));
441         std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
442
443         int ret = provider_send_access_status(packageName.get(), id.get(), accessStatus);
444         SysLog(NID_SHELL, "[LB_ACCESS] provider_send_access_status is called. : ret = %d, status = %d", ret, accessStatus);
445         SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "[E_SYSTEM] failed to provider_send_access_status");
446
447         return E_SUCCESS;
448 }
449
450 Tizen::Base::Collection::HashMap*
451 _AppWidgetContext::CreateRequestArgsN(void)
452 {
453         HashMap* pArgs = new (nothrow) HashMap(SingleObjectDeleter);
454         pArgs->Construct();
455
456         pArgs->Add(new (nothrow) String(ARG_KEY_INSTANCE_ID), new (nothrow) String(GetInstanceId()));
457         pArgs->Add(new (nothrow) String(ARG_KEY_PROVIDER_NAME), new (nothrow) String(GetProviderName()));
458         pArgs->Add(new (nothrow) String(ARG_KEY_USER_INFO), new (nothrow) String(GetUserInfo()));
459         pArgs->Add(new (nothrow) String(ARG_KEY_WIDTH), new (nothrow) String(Integer::ToString(GetWidth())));
460         pArgs->Add(new (nothrow) String(ARG_KEY_HEIGHT), new (nothrow) String(Integer::ToString(GetHeight())));
461
462         return pArgs;
463 }
464
465 int
466 _AppWidgetContext::GetPeriod(void) const
467 {
468         SysLog(NID_SHELL, "GetPeriod[%d]", __updateMillis);
469         return __updateMillis;
470 }
471
472 long long
473 _AppWidgetContext::GetLastUpdatedTime(void) const
474 {
475         return __lastUpdatedTime;
476 }
477
478 int
479 _AppWidgetContext::GetClientId(void) const
480 {
481         return GetAppContext()->GetClientId();
482 }
483
484 void
485 _AppWidgetContext::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
486 {
487         if (&timer == &__updateTimer)
488         {
489                 SysLog(NID_SHELL, "update timer is expired for appWidget app(%ls).", GetProviderId().GetPointer());
490                 OnUpdate(L"");
491         }
492 }
493
494 }}}  // Tizen::Shell::App