2 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
8 // http://floralicense.org/license/
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.
18 * @file FShell_AppWidgetContext.cpp
19 * @brief This is the implementation for the _AppWidgetContext class.
23 #include <unique_ptr.h>
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>
33 #include <FBase_StringConverter.h>
34 #include "FShell_AppWidgetManagerImpl.h"
35 #include "FShell_AppWidgetManagerService.h"
36 #include "FShell_AppWidgetPopupContext.h"
37 #include "FShell_AppWidgetContext.h"
38 #include "FShell_AppWidgetContextHelper.h"
39 #include "FShell_AppWidgetRemoteBuffer.h"
41 namespace Tizen { namespace Shell { namespace App
45 using namespace Tizen::App;
46 using namespace Tizen::Base;
47 using namespace Tizen::Base::Collection;
48 using namespace Tizen::System;
50 const wchar_t ARG_KEY_INSTANCE_ID[] = L"_InstanceId";
51 const wchar_t ARG_KEY_PROVIDER_NAME[] = L"_ProviderName";
52 const wchar_t ARG_KEY_USER_INFO[] = L"_UserInfo";
53 const wchar_t ARG_KEY_X[] = L"_X";
54 const wchar_t ARG_KEY_Y[] = L"_Y";
55 const wchar_t ARG_KEY_WIDTH[] = L"_Width";
56 const wchar_t ARG_KEY_HEIGHT[] = L"_Height";
57 const wchar_t ARG_KEY_POPUP_WIDTH[] = L"_PopupWidth";
58 const wchar_t ARG_KEY_POPUP_HEIGHT[] = L"_PopupHeight";
59 const wchar_t ARG_KEY_ARGUMENT[] = L"_Argument";
60 const wchar_t ARG_KEY_EVENT_TYPE[] = L"_EventType";
61 const wchar_t ARG_KEY_TIME_STAMP[] = L"_TimeStamp";
63 const wchar_t APPWIDGET_ON_ADD[] = L"http://tizen.org/appcontrol/appwidget/add";
64 const wchar_t APPWIDGET_ON_REMOVE[] = L"http://tizen.org/appcontrol/appwidget/remove";
65 const wchar_t APPWIDGET_ON_UPDATE[] = L"http://tizen.org/appcontrol/appwidget/update";
66 const wchar_t APPWIDGET_ON_RESIZE[] = L"http://tizen.org/appcontrol/appwidget/resize";
67 const wchar_t APPWIDGET_ON_TOUCH[] = L"http://tizen.org/appcontrol/appwidget/touch";
69 const int UPDATE_PERIOD_MSEC_MIN = 1800000; // 30min
71 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
73 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
74 _AppContext::_AppContext(void)
75 :__isWaitingResult(false)
77 ,__connectionState(CONNECTION_STATE_NONE)
82 _AppContext::~_AppContext(void)
88 _AppContext::GetConnectionState(void) const
90 return __connectionState;
94 _AppContext::SetConnectionState(_ConnectionState state)
96 __connectionState = state;
100 _AppContext::GetClientId(void) const
102 return __ipcClientId;
106 _AppContext::SetClientId(int clientId)
108 __ipcClientId = clientId;
112 _AppContext::SetWaitingStatus(bool status)
114 __isWaitingResult = status;
118 _AppContext::GetWaitingStatus(void) const
120 return __isWaitingResult;
123 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
124 // _AppWidgetContext class
125 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126 _AppWidgetContext::_AppWidgetContext(_AppContext* pAppContext, const String& userInfo, const String& providerId, const String& instanceId, int width, int height, int period, int priority)
127 :__isTouchAvailable(false)
128 ,__hasPendingRequest(false)
129 ,__isForeground(true)
132 ,__priority(priority)
134 ,__updateMillis(period)
135 ,__lastUpdatedTime(0)
136 ,__userInfo(userInfo)
137 ,__providerId(providerId)
138 ,__instanceId(instanceId)
139 ,__pAppContext(pAppContext)
140 ,__pAppWidgetPopup(null)
141 ,__pAppWidgetRemoteBuffer(null)
142 ,__pPendingTouchEventList(null)
143 ,__pPendingEventList(null)
145 _AppWidgetManagerImpl::ExtractAppIdAndProviderName(providerId, __appId, __providerName);
146 SysSecureLog(NID_SHELL, "appId(%ls), providerId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", __appId.GetPointer(), __providerId.GetPointer(), __instanceId.GetPointer(), __width, __height, __priority);
148 // for updating period
149 if (__updateMillis > 0)
151 __updateMillis = (__updateMillis > UPDATE_PERIOD_MSEC_MIN) ? __updateMillis : UPDATE_PERIOD_MSEC_MIN;
152 SysLog(NID_SHELL, "period(%d)", __updateMillis);
154 SystemTime::GetTicks(this->__lastUpdatedTime);
156 result r = __updateTimer.Construct(*this);
157 SysTryReturnVoidResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "");
159 r = __updateTimer.StartAsRepeatable(__updateMillis);
160 SysTryReturnVoidResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "");
163 __pPendingTouchEventList = new (nothrow) ArrayListT<PendingTouchEvent*>();
164 SysTryReturnVoidResult(NID_SHELL, __pPendingTouchEventList, E_OUT_OF_MEMORY, "");
165 __pPendingTouchEventList->Construct();
167 __pPendingEventList = new (nothrow) ArrayListT<PendingEvent*>();
168 SysTryReturnVoidResult(NID_SHELL, __pPendingEventList, E_OUT_OF_MEMORY, "");
169 __pPendingEventList->Construct();
171 __pAppWidgetRemoteBuffer = new (nothrow) _AppWidgetRemoteBuffer(providerId, instanceId, TYPE_LB, this);
172 SysTryReturnVoidResult(NID_SHELL, __pAppWidgetRemoteBuffer, E_OUT_OF_MEMORY, "");
175 _AppWidgetContext::~_AppWidgetContext(void)
177 SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), GetHeight(), GetPriority());
179 __updateTimer.Cancel();
181 if (__pAppWidgetPopup)
183 SysLog(NID_SHELL, "Destroying dangling AppWidgetPopup instance..");
184 delete __pAppWidgetPopup;
187 if (__pPendingTouchEventList)
189 for (int i = 0; i < __pPendingTouchEventList->GetCount(); i++)
191 PendingTouchEvent* pTouchEvent = null;
192 __pPendingTouchEventList->GetAt(i, pTouchEvent);
195 __pPendingTouchEventList->RemoveAll();
196 delete __pPendingTouchEventList;
199 if (__pPendingEventList)
201 for (int i = 0; i < __pPendingEventList->GetCount(); i++)
203 PendingEvent* pEvent = null;
204 __pPendingEventList->GetAt(i, pEvent);
207 __pPendingEventList->RemoveAll();
208 delete __pPendingEventList;
211 if (__pAppWidgetRemoteBuffer)
213 delete __pAppWidgetRemoteBuffer;
218 _AppWidgetContext::GetAppContext(void) const
220 return __pAppContext;
223 _AppWidgetPopupContext*
224 _AppWidgetContext::GetAppWidgetPopup(void) const
226 return __pAppWidgetPopup;
230 _AppWidgetContext::OnAdded(void)
232 SendAddRequest(GetWidth(), GetHeight());
236 _AppWidgetContext::OnRemoved(void)
238 return SendRemoveRequest();
242 _AppWidgetContext::OnUpdate(const String& argument)
244 SysLog(NID_SHELL, "argument(%ls)", argument.GetPointer());
248 AppWidgetManagerService* pMgrService = AppWidgetManagerService::GetInstance();
249 SysTryReturnVoidResult(NID_SHELL, pMgrService, E_SYSTEM, "[E_SYSTEM] Failed to get an instance of AppWidgetManagerService.");
251 // Queueing the pointer of background context.
252 if (!this->IsForeground())
255 if (!argument.IsEmpty())
257 __pendingArgument = argument;
260 __hasPendingRequest = true;
261 SysLog(NID_SHELL, "Update is requested but the %ls is background.", (this->GetAppId()).GetPointer());
265 result r = this->SendUpdateRequest(GetWidth(), GetHeight(), argument);
266 SysTryLog(NID_SHELL, !IsFailed(r), "Failed to execute SendUpdateRequest.");
268 SystemTime::GetTicks(this->__lastUpdatedTime);
269 SysLog(NID_SHELL, "The last updated time is %lld.", this->__lastUpdatedTime);
271 __hasPendingRequest = false;
272 __pendingArgument.Clear();
277 _AppWidgetContext::OnResize(int width, int height)
279 SysSecureLog(NID_SHELL, "appId(%ls), instanceId(%ls), width(%d), height(%d), priority(%d)", GetProviderId().GetPointer(), GetInstanceId().GetPointer(), GetWidth(), GetHeight(), GetPriority());
284 SendResizeRequest(width, height);
288 _AppWidgetContext::RequestUpdate(const String& argument)
290 AppWidgetManagerService* pMgrService = AppWidgetManagerService::GetInstance();
291 SysTryReturnResult(NID_SHELL, pMgrService, E_SYSTEM, "Failed to get an instance of AppWidgetManagerService.");
293 result r = pMgrService->RequestUpdate(this, argument);
294 SysTryReturnResult(NID_SHELL, !IsFailed(r), r, "Failed to request update.");
300 _AppWidgetContext::OnForeground(void)
304 SysLog(NID_SHELL, "%ls is already foreground.", (this->GetAppId()).GetPointer());
308 this->SetForeground(true);
310 if (__hasPendingRequest == true)
312 RequestUpdate(__pendingArgument);
316 if (this->GetPeriod() > 0)
318 long long currentTicks = 0;
319 SystemTime::GetTicks(currentTicks);
321 SysLog(NID_SHELL, "current[%lld] - updatedTime[%lld] = [%lld], period[%d]",
322 currentTicks, this->GetLastUpdatedTime(), currentTicks - this->GetLastUpdatedTime(), this->GetPeriod());
324 bool isPeriodExpired = (currentTicks - this->GetLastUpdatedTime()) >= (this->GetPeriod());
327 SysLog(NID_SHELL, "The period is expired.");
335 _AppWidgetContext::OnBackground(void)
337 SysLog(NID_SHELL, "OnBackground");
341 SysLog(NID_SHELL, "%ls is already background.", (this->GetAppId()).GetPointer());
344 SetForeground(false);
348 _AppWidgetContext::OnPopupCreated(double x, double y, int width, int height)
350 __pAppWidgetPopup = new (nothrow) _AppWidgetPopupContext(this);
351 SysTryReturnVoidResult(NID_SHELL, __pAppWidgetPopup, E_OUT_OF_MEMORY, "");
353 __pAppWidgetPopup->OnPopupCreated(x, y, width, height);
357 _AppWidgetContext::OnPopupDestoyed(void)
359 SysLog(NID_SHELL, "");
361 if (__pAppWidgetPopup)
363 // __pAppWidgetPopup->OnPopupDestoyed();
364 delete __pAppWidgetPopup;
365 __pAppWidgetPopup = null;
370 _AppWidgetContext::SendAddRequest(int width, int height)
372 std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
374 return SendRequestToApp(GetAppId(), APPWIDGET_ON_ADD, pArgs.release());
378 _AppWidgetContext::SendUpdateRequest(int width, int height, const String& argument)
380 std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
382 pArgs->Add(new (nothrow) String(ARG_KEY_ARGUMENT), new (nothrow) String(argument));
384 return SendRequestToApp(GetAppId(), APPWIDGET_ON_UPDATE, pArgs.release());
388 _AppWidgetContext::SendResizeRequest(int width, int height)
390 std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
392 return SendRequestToApp(GetAppId(), APPWIDGET_ON_RESIZE, pArgs.release());
396 _AppWidgetContext::SendRemoveRequest(void)
398 std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN());
400 return SendRequestToApp(GetAppId(), APPWIDGET_ON_REMOVE, pArgs.release());
404 _AppWidgetContext::SendPendingEvent(void)
406 GetAppContext()->SetWaitingStatus(false);
407 TryReturn(__pPendingEventList->GetCount() > 0, E_DATA_NOT_FOUND, "This context has no pending event. Please find next pending event context.");
409 PendingEvent* pEvent = null;
410 __pPendingEventList->GetAt(0, pEvent);
411 SysTryReturnResult(NID_SHELL, pEvent != null, E_SYSTEM, "__pPendingEventList has (%d) items, but failed to GetAt(0)", __pPendingEventList->GetCount());
413 __pPendingEventList->RemoveAt(0);
414 SysLog(NID_SHELL, "(%d) Remains in __pPendingEventList.", __pPendingEventList->GetCount());
416 result r = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), pEvent->operation, pEvent->pArg);
418 SysTryReturnResult(NID_SHELL, !IsFailed(r), E_SYSTEM, "SendIpcRequest failed.");
424 _AppWidgetContext::SendPendingTouchEvent(void)
426 for (int i =0; i< __pPendingTouchEventList->GetCount(); i++)
428 PendingTouchEvent* pTouchEvent = null;
429 __pPendingTouchEventList->GetAt(i, pTouchEvent);
430 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), pTouchEvent->eventType, pTouchEvent->timeStamp, pTouchEvent->x, pTouchEvent->y);
433 __pPendingTouchEventList->RemoveAll();
437 _AppWidgetContext::OnTouchEventReceived(buffer_event event, double timestamp, double x, double y)
439 if (__pAppContext->GetConnectionState() == CONNECTION_STATE_CONNECTED && __isTouchAvailable)
441 SysLog(NID_SHELL, "%d, %f, %f", event, x, y);
442 AppWidgetManagerService::GetInstance()->SendTouchEvent(GetClientId(), GetInstanceId(), event, timestamp, x, y);
446 __pPendingTouchEventList->Add(new (nothrow) PendingTouchEvent(event, timestamp, x, y));
448 if( AppManager::GetInstance()->IsRunning(this->GetAppId() ) == false)
450 SysLog(NID_SHELL, "request to start AppControl");
451 std::unique_ptr<HashMap, AllElementsDeleter> pArgs (CreateRequestArgsN() );
453 // TODO: consider to remove these unused args.
454 pArgs->Add(new (nothrow) String(ARG_KEY_EVENT_TYPE), new (nothrow) String(Integer::ToString(event)));
455 pArgs->Add(new (nothrow) String(ARG_KEY_TIME_STAMP), new (nothrow) String(Double::ToString(timestamp)));
456 pArgs->Add(new (nothrow) String(ARG_KEY_X), new (nothrow) String(Double::ToString(x)));
457 pArgs->Add(new (nothrow) String(ARG_KEY_Y), new (nothrow) String(Double::ToString(y)));
459 SendRequestToApp(GetAppId(), APPWIDGET_ON_TOUCH, pArgs.get());
465 _AppWidgetContext::SendRequestToApp(const AppId& appId, const String& operation, HashMap* pArgs)
467 result r = E_SUCCESS;
469 if ( __pAppContext->GetConnectionState() == CONNECTION_STATE_NONE || __pAppContext->GetConnectionState() == CONNECTION_STATE_DISCONNECTED)
471 SysLog(NID_SHELL, "The application is not running.");
472 result r = _AppWidgetRequestHelper::SendAppControlRequest(appId, operation, pArgs);
473 SysTryReturn(NID_SHELL, !IsFailed(r), r, r, "[%s] Failed to SendRequestToApp", GetErrorMessage(r));
475 __pAppContext->SetWaitingStatus(true);
476 __pAppContext->SetConnectionState(CONNECTION_STATE_CONNECTING);
480 if ( __pAppContext->GetConnectionState() == CONNECTION_STATE_CONNECTING || __pAppContext->GetWaitingStatus() == true)
482 SysLog(NID_SHELL, "The application is running but IPC is not connected yet.");
483 __pPendingEventList->Add(new (nothrow) PendingEvent(operation, pArgs));
487 SysLog(NID_SHELL, "The application is running and IPC is connected.");
488 r = _AppWidgetRequestHelper::SendIpcRequest(GetClientId(), operation, pArgs);
490 pArgs->RemoveAll(true);
492 __pAppContext->SetWaitingStatus(true);
500 _AppWidgetContext::SendPopupRequestToApp(const AppId& appId, const String& operation, HashMap* pArgs) const
502 return _AppWidgetRequestHelper::SendAppControlRequest(appId, operation, pArgs);;
506 _AppWidgetContext::SyncRemoteBuffer(int width, int height)
508 std::unique_ptr<char[]> providerId(_StringConverter::CopyToCharArrayN(GetProviderId()));
509 std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
510 std::unique_ptr<char[]> content_info(_StringConverter::CopyToCharArrayN(GetUserInfo()));
512 int ret = provider_send_updated(providerId.get(), id.get(), width, height, GetPriority(), content_info.get(), null);
513 SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "[E_SYSTEM] failed to provider_send_updated");
515 SendPendingTouchEvent();
516 SysLog(NID_SHELL, "Done");
521 _AppWidgetContext::SendAccessStatus(int accessStatus) const
523 std::unique_ptr<char[]> providerId(_StringConverter::CopyToCharArrayN(GetProviderId()));
524 std::unique_ptr<char[]> id(_StringConverter::CopyToCharArrayN(GetInstanceId()));
526 int ret = provider_send_access_status(providerId.get(), id.get(), accessStatus);
527 SysTryReturnResult(NID_SHELL, ret >= 0 , E_SYSTEM, "[E_SYSTEM] failed to provider_send_access_status");
532 Tizen::Base::Collection::HashMap*
533 _AppWidgetContext::CreateRequestArgsN(void) const
535 HashMap* pArgs = new (nothrow) HashMap(SingleObjectDeleter);
538 pArgs->Add(new (nothrow) String(ARG_KEY_INSTANCE_ID), new (nothrow) String(GetInstanceId()));
539 pArgs->Add(new (nothrow) String(ARG_KEY_PROVIDER_NAME), new (nothrow) String(GetProviderName()));
540 pArgs->Add(new (nothrow) String(ARG_KEY_USER_INFO), new (nothrow) String(GetUserInfo()));
541 pArgs->Add(new (nothrow) String(ARG_KEY_WIDTH), new (nothrow) String(Integer::ToString(GetWidth())));
542 pArgs->Add(new (nothrow) String(ARG_KEY_HEIGHT), new (nothrow) String(Integer::ToString(GetHeight())));
548 _AppWidgetContext::GetPeriod(void) const
550 return __updateMillis;
554 _AppWidgetContext::GetLastUpdatedTime(void) const
556 return __lastUpdatedTime;
560 _AppWidgetContext::GetClientId(void) const
562 return GetAppContext()->GetClientId();
566 _AppWidgetContext::GetWidth(void) const
572 _AppWidgetContext::SetWidth(int width)
578 _AppWidgetContext::GetHeight(void) const
584 _AppWidgetContext::SetHeight(int height)
590 _AppWidgetContext::GetProviderId(void) const
596 _AppWidgetContext::SetProviderId(const String& providerId)
598 __providerId = providerId;
602 _AppWidgetContext::GetAppId(void) const
608 _AppWidgetContext::GetPriority(void) const
614 _AppWidgetContext::SetPriority(int priority)
616 __priority = priority;
620 _AppWidgetContext::GetProviderName(void) const
622 return __providerName;
626 _AppWidgetContext::SetForeground(bool foreground)
628 __isForeground = foreground;
632 _AppWidgetContext::IsForeground(void) const
634 return __isForeground;
638 _AppWidgetContext::GetUserInfo(void) const
644 _AppWidgetContext::SetUserInfo(const String& userInfo)
646 __userInfo = userInfo;
650 _AppWidgetContext::GetInstanceId(void) const
656 _AppWidgetContext::OnTimerExpired(Tizen::Base::Runtime::Timer& timer)
658 if (&timer == &__updateTimer)
660 SysLog(NID_SHELL, "update timer is expired for appWidget app(%ls).", GetProviderId().GetPointer());
666 _AppWidgetContext::OnDisconnected(void)
668 SysSecureLog(NID_SHELL, "%ls, %ls", GetInstanceId().GetPointer(), GetProviderId().GetPointer());
670 __isTouchAvailable = false;
671 if (GetAppWidgetPopup())
678 _AppWidgetContext::AcquireRemoteBuffer(int w, int h) const
680 int id = __pAppWidgetRemoteBuffer->Acquire(w, h);
683 __isTouchAvailable = true;
688 }}} // Tizen::Shell::App