add new features
[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
38 namespace Tizen { namespace Shell  { namespace App
39 {
40
41 using namespace Tizen::App;
42 using namespace Tizen::Base;
43 using namespace Tizen::Base::Collection;
44 using namespace Tizen::System;
45
46 const String APPWIDGET_ON_ADD = L"http://tizen.org/appcontrol/appwidget/add";
47 const String APPWIDGET_ON_REMOVE = L"http://tizen.org/appcontrol/appwidget/remove";
48 const String APPWIDGET_ON_UPDATE = L"http://tizen.org/appcontrol/appwidget/update";
49 const String APPWIDGET_ON_RESIZE = L"http://tizen.org/appcontrol/appwidget/resize";
50 const String APPWIDGET_ON_TOUCH = L"http://tizen.org/appcontrol/appwidget/touch";
51
52 const int UPDATE_PERIOD_MSEC_MIN = 1800000;     // 30min
53
54 _AppWidgetContext::_AppWidgetContext(const String& info, const String& providerId, const String& instanceId, int width, int height, int period, int priority)
55         :_AppWidgetContextBase(TYPE_LB, info, providerId, instanceId, width, height, priority)
56         ,__pAppWidgetPopup(null)
57         ,__updateMillis(period)
58         ,__lastUpdatedTime(0)
59         ,__pPendingTouchEventList(null)
60         ,__pPendingEventList(null)
61         , __hasPendingRequest(false)
62 {
63         if (__updateMillis > 0)
64         {
65                 __updateMillis = (__updateMillis > UPDATE_PERIOD_MSEC_MIN) ? __updateMillis : UPDATE_PERIOD_MSEC_MIN;
66                 SysLog(NID_SHELL, "period(%d)", __updateMillis);
67
68                 SystemTime::GetTicks(this->__lastUpdatedTime);
69
70                 __updateTimer.Construct(*this);
71                 __updateTimer.StartAsRepeatable(__updateMillis);
72         }
73
74         __pPendingTouchEventList = new ArrayListT<PendingTouchEvent*>();
75         __pPendingTouchEventList->Construct();
76
77         __pPendingEventList = new ArrayListT<PendingEvent*>();
78         __pPendingEventList->Construct();
79
80
81 }
82
83 _AppWidgetContext::~_AppWidgetContext(void)
84 {
85         SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), GetHeight(), GetPriority());
86
87         __updateTimer.Cancel();
88
89         if (__pAppWidgetPopup)
90         {
91                 SysLog(NID_SHELL, "Destroying dangling AppWidgetPopup instance..");
92                 __pAppWidgetPopup->OnPopupDestoyed();
93                 delete __pAppWidgetPopup;
94         }
95
96         if (__pPendingTouchEventList)
97         {
98                 for (int i = 0; i < __pPendingTouchEventList->GetCount(); i++)
99                 {
100                         PendingTouchEvent* pTouchEvent = null;
101                         __pPendingTouchEventList->GetAt(i, pTouchEvent);
102                         delete pTouchEvent;
103                 }
104                 __pPendingTouchEventList->RemoveAll();
105                 delete __pPendingTouchEventList;
106         }
107
108         if (__pPendingEventList)
109         {
110                 for (int i = 0; i < __pPendingEventList->GetCount(); i++)
111                 {
112                         PendingEvent* pEvent = null;
113                         __pPendingEventList->GetAt(i, pEvent);
114                         delete pEvent;
115                 }
116                 __pPendingEventList->RemoveAll();
117                 delete __pPendingEventList;
118         }
119 }
120
121 _AppWidgetPopupContext*
122 _AppWidgetContext::GetAppWidgetPopup(void) const
123 {
124         return __pAppWidgetPopup;
125 }
126
127 void
128 _AppWidgetContext::OnAdded(void)
129 {
130         SendAddRequest(GetWidth(), GetHeight());
131 }
132
133 result
134 _AppWidgetContext::OnRemoved(void)
135 {
136         return SendRemoveRequest();
137 }
138
139 void
140 _AppWidgetContext::OnUpdate(const String& argument)
141 {
142         ClearLastResult();
143
144         AppWidgetManagerService* pMgrService = AppWidgetManagerService::GetInstance();
145         SysTryReturnVoidResult(NID_SHELL, pMgrService, E_SYSTEM, "[E_SYSTEM] Failed to get an instance of AppWidgetManagerService.");
146
147         // Queueing the pointer of paused context.
148         if (this->IsPaused())
149         {
150                 // Saving the data
151                 if (!argument.IsEmpty())
152                 {
153                         __pendingArgument = argument;
154                 }
155
156                 __hasPendingRequest = true;
157                 SysLog(NID_SHELL, "Update is requested but the %ls is paused.", (this->GetAppId()).GetPointer());
158         }
159         else
160         {
161                 result r = this->SendUpdateRequest(GetWidth(), GetHeight(), argument);
162                 SysTryLog(NID_SHELL, !IsFailed(r), "Failed to execute SendUpdateRequest.");
163
164                 SystemTime::GetTicks(this->__lastUpdatedTime);
165                 SysLog(NID_SHELL, "The last updated time is %lld.", this->__lastUpdatedTime);
166
167                 __hasPendingRequest = false;
168                 __pendingArgument.Clear();
169         }
170 }
171
172 void
173 _AppWidgetContext::OnResize(int width, int height)
174 {
175         SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), GetHeight(), GetPriority());
176
177         SetWidth(width);
178         SetHeight(height);
179
180         SendResizeRequest(width, height);
181 }
182
183 result
184 _AppWidgetContext::RequestUpdate(const String& argument)
185 {
186         AppWidgetManagerService* pMgrService = AppWidgetManagerService::GetInstance();
187         SysTryReturnResult(NID_SHELL, pMgrService, E_SYSTEM, "[E_SYSTEM] Failed to get an instance of AppWidgetManagerService.");
188
189         result r = pMgrService->RequestUpdate(this, argument);
190         SysTryReturnResult(NID_SHELL, !IsFailed(r), r, "Failed to request update.");
191
192         return r;
193 }
194
195 void
196 _AppWidgetContext::OnForeground(void)
197 {
198         SysLog(NID_SHELL, "I");
199
200         if (!IsPaused())
201         {
202                 SysLog(NID_SHELL, "%ls is already resumed.", (this->GetAppId()).GetPointer());
203                 return;
204         }
205
206         this->SetForeground(true);
207
208         if (__hasPendingRequest == true)
209         {
210                 RequestUpdate(__pendingArgument);
211         }
212         else
213         {
214                 if (this->GetPeriod() > 0)
215                 {
216                         long long currentTicks = 0;
217                         SystemTime::GetTicks(currentTicks);
218
219                         SysLog(NID_SHELL, "current[%lld] - updatedTime[%lld] = [%lld], period[%d]",
220                                         currentTicks, this->GetLastUpdatedTime(), currentTicks - this->GetLastUpdatedTime(), this->GetPeriod());
221
222                         bool isPeriodExpired = (currentTicks - this->GetLastUpdatedTime()) >= (this->GetPeriod());
223                         if (isPeriodExpired)
224                         {
225                                 SysLog(NID_SHELL, "The period is expired.");
226                                 RequestUpdate(L"");
227                         }
228                 }
229         }
230
231         SysLog(NID_SHELL, "O");
232 }
233
234 void
235 _AppWidgetContext::OnBackground(void)
236 {
237         SysLog(NID_SHELL, "OnBackground");
238
239         if (IsPaused())
240         {
241                 SysLog(NID_SHELL, "%ls is already paused.", (this->GetAppId()).GetPointer());
242                 return;
243         }
244         SetForeground(false);
245 }
246
247 bool
248 _AppWidgetContext::IsPaused(void) const
249 {
250         return IsForeground() ? false : true;
251 }
252
253 void
254 _AppWidgetContext::OnPopupCreated(double x, double y, int width, int height)
255 {
256         __pAppWidgetPopup = new (std::nothrow) _AppWidgetPopupContext(GetUserInfo(), GetProviderId(), GetInstanceId(), GetWidth(), GetHeight(), GetPriority(), this);
257         __pAppWidgetPopup->SetIpcClientId(GetClientId());
258         __pAppWidgetPopup->OnPopupCreated(x, y, width, height);
259 }
260
261 void
262 _AppWidgetContext::OnPopupDestoyed(void)
263 {
264         SysLog(NID_SHELL, "");
265
266         if (__pAppWidgetPopup)
267         {
268                 __pAppWidgetPopup->OnPopupDestoyed();
269                 delete __pAppWidgetPopup;
270                 __pAppWidgetPopup = null;
271         }
272 }
273
274 result
275 _AppWidgetContext::SendAddRequest(int width, int height)
276 {
277         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
278
279         return SendRequestToApp(GetAppId(), APPWIDGET_ON_ADD, pArgs.release());
280 }
281
282 result
283 _AppWidgetContext::SendUpdateRequest(int width, int height, const String& argument)
284 {
285         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
286
287         pArgs->Add(new String(ARG_KEY_ARGUMENT), new String(argument));
288
289         return SendRequestToApp(GetAppId(), APPWIDGET_ON_UPDATE, pArgs.release());
290 }
291
292 result
293 _AppWidgetContext::SendResizeRequest(int width, int height)
294 {
295         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
296
297         return SendRequestToApp(GetAppId(), APPWIDGET_ON_RESIZE, pArgs.release());
298 }
299
300 result
301 _AppWidgetContext::SendRemoveRequest(void)
302 {
303         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
304
305         return SendRequestToApp(GetAppId(), APPWIDGET_ON_REMOVE, pArgs.release());
306 }
307
308 result
309 _AppWidgetContext::SendPendingEvent(void)
310 {
311         SysTryReturnResult(NID_SHELL, __pPendingEventList->GetCount() > 0 , E_SUCCESS, "There is no pending event.");
312
313         PendingEvent* pEvent = null;
314         __pPendingEventList->GetAt(0, pEvent);
315
316         if (pEvent != null)
317         {
318                 SysLog(NID_SHELL, "SendPendingEvent by IPC [%d existed.]", __pPendingEventList->GetCount());
319                 _AppWidgetRequestHelper::SendRequestToApp(GetClientId(), pEvent->operation, pEvent->pArg);
320                 __pPendingEventList->RemoveAt(0);
321         }
322         else
323         {
324                 SysLog(NID_SHELL, "SendPendingEvent by IPC [0 existed.]");
325         }
326
327         return E_SUCCESS;
328 }
329
330 void
331 _AppWidgetContext::SendPendingTouchEvent(void)
332 {
333         for (int i =0; i< __pPendingTouchEventList->GetCount(); i++)
334         {
335                 PendingTouchEvent* pTouchEvent = null;
336                 __pPendingTouchEventList->GetAt(i, pTouchEvent);
337                 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), pTouchEvent->eventType, pTouchEvent->timeStamp, pTouchEvent->x, pTouchEvent->y);
338                 delete pTouchEvent;
339         }
340         __pPendingTouchEventList->RemoveAll();
341 }
342
343 result
344 _AppWidgetContext::SendTouchEvent(buffer_event eventType, double timeStamp, double x, double y)
345 {
346         if (HasValidClientId() && IsRunning())
347         {
348                 SysAssert(IsSharedMemCreated() == true);
349                 SysLog(NID_SHELL, "%d, %f, %f", eventType, x, y);
350                 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), eventType, timeStamp, x, y);
351         }
352         else
353         {
354                 __pPendingTouchEventList->Add(new PendingTouchEvent(eventType, timeStamp, x, y));
355
356                 if( AppManager::GetInstance()->IsRunning(this->GetAppId() ) == false)
357                 {
358                         SysLog(NID_SHELL, "request to start AppControl");
359                         std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
360
361                         // TODO: consider to remove these unused args.
362                         pArgs->Add(new String(ARG_KEY_EVENT_TYPE), new String(Integer::ToString(eventType)));
363                         pArgs->Add(new String(ARG_KEY_TIME_STAMP), new String(Double::ToString(timeStamp)));
364                         pArgs->Add(new String(ARG_KEY_X), new String(Double::ToString(x)));
365                         pArgs->Add(new String(ARG_KEY_Y), new String(Double::ToString(y)));
366
367                         return SendRequestToApp(GetAppId(), APPWIDGET_ON_TOUCH, pArgs.get());
368                 }
369         }
370         return E_SUCCESS;
371 }
372
373 result
374 _AppWidgetContext::SendRequestToApp(const AppId& appId, const String& operation, HashMap* pArgs)
375 {
376         result r = E_SUCCESS;
377
378         if (AppManager::GetInstance()->IsRunning(appId) == false)
379         {
380                 SysLog(NID_SHELL, "The application is not running.");
381                 return _AppWidgetContextBase::SendRequestToApp(appId, operation, pArgs);
382         }
383         else
384         {
385                 if(!HasValidClientId())
386                 {
387                         SysLog(NID_SHELL, "The application is running but IPC is not connected yet.");
388                         __pPendingEventList->Add(new PendingEvent(*new String(GetInstanceId()), *new String(operation), pArgs));
389                 }
390                 else
391                 {
392                         SysLog(NID_SHELL, "The application is running and IPC is connected.");
393                         r  = _AppWidgetRequestHelper::SendRequestToApp(GetClientId(), operation, pArgs);
394
395 //                      pArgs->RemoveAll(true);
396 //                      delete pArgs;
397                 }
398         }
399
400         return E_SUCCESS;
401 }
402
403 result
404 _AppWidgetContext::RequestUpdateRemote(int width, int height)
405 {
406         std::unique_ptr<char[]> packageName(_StringConverter::CopyToCharArrayN(GetProviderId()));
407         std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
408         std::unique_ptr<char[]> content_info(_StringConverter::CopyToCharArrayN(GetUserInfo()));
409
410         int ret = provider_send_updated(packageName.get(), id.get(), width, height, GetPriority(), content_info.get(), null);
411         SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "[E_SYSTEM] failed to provider_send_updated");
412
413         SendPendingTouchEvent();
414         SysLog(NID_SHELL, "Done");
415         return E_SUCCESS;
416 }
417
418 Tizen::Base::Collection::HashMap*
419 _AppWidgetContext::CreateRequestArgsN(void)
420 {
421         HashMap* pArgs = new (std::nothrow) HashMap(SingleObjectDeleter);
422         pArgs->Construct();
423
424         pArgs->Add(new String(ARG_KEY_INSTANCE_ID), new String(GetInstanceId()));
425         pArgs->Add(new String(ARG_KEY_PROVIDER_NAME), new String(GetProviderName()));
426         pArgs->Add(new String(ARG_KEY_USER_INFO), new String(GetUserInfo()));
427         pArgs->Add(new String(ARG_KEY_WIDTH), new String(Integer::ToString(GetWidth())));
428         pArgs->Add(new String(ARG_KEY_HEIGHT), new String(Integer::ToString(GetHeight())));
429
430         return pArgs;
431 }
432
433 int
434 _AppWidgetContext::GetPeriod(void) const
435 {
436         SysLog(NID_SHELL, "GetPeriod[%d]", __updateMillis);
437         return __updateMillis;
438 }
439
440 long long
441 _AppWidgetContext::GetLastUpdatedTime(void) const
442 {
443         return __lastUpdatedTime;
444 }
445
446 void
447 _AppWidgetContext::SetIpcClientId(int clientId)
448 {
449         _AppWidgetContextBase::SetIpcClientId(clientId);
450 }
451
452 void
453 _AppWidgetContext::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
454 {
455         if (&timer == &__updateTimer)
456         {
457                 SysLog(NID_SHELL, "update timer is expired for appWidget app(%ls).", GetProviderId().GetPointer());
458                 OnUpdate(L"");
459         }
460 }
461
462 }}}  // Tizen::Shell::App