Bug fix: TIVI-1996.
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / CicoSCServer.cpp
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 //==========================================================================
11 /**
12  *  @file   CicoSCServer.cpp
13  *
14  *  @brief  This file implementation of CicoSCServer class
15  */
16 //==========================================================================
17
18 #include <sstream>
19 using namespace std;
20
21 #include "CicoSCServer.h"
22 #include "CicoSCCommand.h"
23 #include "CicoSCMessage.h"
24 #include "CicoLog.h"
25 #include "ico_syc_error.h"
26 #include "ico_syc_msg_cmd_def.h"
27 #include "CicoSCWindowController.h"
28 #include "CicoSCInputController.h"
29 #include "CicoSCUserManager.h"
30 #include "CicoSCUser.h"
31 #include "CicoSCResourceManager.h"
32 #include "CicoSCPolicyManager.h"
33
34 class CicoSCUwsHandler
35 {
36 public:
37     CicoSCUwsHandler()
38         : uwsContext(NULL), id(NULL), fd(-1), serviceFlag(false),
39           ecoreFdHandler(NULL), appid("") {}
40     void dump(void) const {
41         ICO_DBG("uwsContext=0x%08x fd=%d service=%s "
42                 "ecoreFdHandler=0x%08x appid=%s",
43                 uwsContext, fd, serviceFlag ? "true" : "false",
44                 ecoreFdHandler, appid.c_str());
45     }
46     struct ico_uws_context *uwsContext;
47     void*  id;
48     int    fd;
49     bool   serviceFlag;
50     Ecore_Fd_Handler *ecoreFdHandler;
51     string appid;
52 };
53
54 //==========================================================================    
55 //  private static variable
56 //==========================================================================    
57 CicoSCServer* CicoSCServer::ms_myInstance = NULL;
58
59 //--------------------------------------------------------------------------
60 /**
61  *  @brief  default constructor
62  */
63 //--------------------------------------------------------------------------
64 CicoSCServer::CicoSCServer()
65     : m_uwsContext(NULL), m_windowCtrl(NULL),
66       m_inputCtrl(NULL) , m_userMgr(NULL), m_resourceMgr(NULL),
67       m_policyMgr(NULL), m_dispatchProcessing(false)
68 {
69 }
70
71 //--------------------------------------------------------------------------
72 /**
73  *  @brief  destructor
74  */
75 //--------------------------------------------------------------------------
76 CicoSCServer::~CicoSCServer()
77 {
78     // TODO
79 }
80
81 //--------------------------------------------------------------------------
82 /**
83  *  @brief   get CicoSCServer instance
84  *
85  *  @return CicoSCServer instance
86  */
87 //--------------------------------------------------------------------------
88 CicoSCServer*
89 CicoSCServer::getInstance(void)
90 {
91     if (NULL == ms_myInstance) {
92         ms_myInstance = new CicoSCServer();
93     }
94
95     return ms_myInstance;
96 }
97
98 //--------------------------------------------------------------------------
99 /**
100  *  @brief   set window controller instance
101  *
102  *  @param [in] windowCtrl  controller instance
103  */
104 //--------------------------------------------------------------------------
105 void
106 CicoSCServer::setWindowCtrl(CicoSCWindowController *windowCtrl)
107 {
108     m_windowCtrl = windowCtrl;
109 }
110
111 //--------------------------------------------------------------------------
112 /**
113  *  @brief   set input controller instance
114  *
115  *  @param [in] inputCtrl   controller instance
116  */
117 //--------------------------------------------------------------------------
118 void
119 CicoSCServer::setInputCtrl(CicoSCInputController *inputCtrl)
120 {
121     m_inputCtrl= inputCtrl;
122 }
123
124 //--------------------------------------------------------------------------
125 /**
126  *  @brief   set user manager
127  *
128  *  @param [in] userMgr     user manager instance
129  */
130 //--------------------------------------------------------------------------
131 void
132 CicoSCServer::setUserMgr(CicoSCUserManager *userMgr)
133 {
134     m_userMgr = userMgr;
135 }
136
137 //--------------------------------------------------------------------------
138 /**
139  *  @brief   set resource manager instance
140  *
141  *  @param [in] resourceMgr resouce manager instance
142  */
143 //--------------------------------------------------------------------------
144 void
145 CicoSCServer::setResourceMgr(CicoSCResourceManager *resourceMgr)
146 {
147     m_resourceMgr = resourceMgr;
148 }
149
150 //--------------------------------------------------------------------------
151 /**
152  *  @brief   set policy manager instance
153  *
154  *  @param [in] policyMgr policy manager instance
155  */
156 //--------------------------------------------------------------------------
157 void
158 CicoSCServer::setPolicyMgr(CicoSCPolicyManager *policyMgr)
159 {
160     m_policyMgr = policyMgr;
161 }
162
163 //--------------------------------------------------------------------------
164 /**
165  *  @brief   startup server
166  *
167  *  @param [in] port        websocket port
168  *  @param [in] protocol    websocket protocol name
169  *
170  *  @return ICO_SYC_EOK on success, other on error
171  *  @retval ICO_SYC_EOK     success
172  *  @retval ICO_SYC_ENOSYS  error(connection fail)
173  */
174 //--------------------------------------------------------------------------
175 int
176 CicoSCServer::startup(int port, const char *protocol)
177 {
178     /* create uir string ":PORT" */
179     stringstream uri;
180     uri << ":" << port;
181
182     /* create context */
183     ICO_DBG("called: ico_uws_create_context(port=%s protocol=%s)",
184             uri.str().c_str(), protocol);
185     m_uwsContext = ico_uws_create_context(uri.str().c_str(), protocol);
186     if (NULL == m_uwsContext) {
187         ICO_ERR("ico_uws_create_context() failed.");
188         return ICO_SYC_ENOSYS;
189     }
190     ico_uws_service(m_uwsContext);
191
192     /* set callback */
193     int ret = ico_uws_set_event_cb(m_uwsContext, uwsReceiveEventCB,
194                                    (void *)this);
195     if (ret != ICO_UWS_ERR_NONE) {
196         ICO_ERR("ico_uws_set_event_cb() failed(%d).", ret);
197         return ICO_SYC_ENOSYS;
198     }
199     ico_uws_service(m_uwsContext);
200
201     return ICO_SYC_EOK;
202 }
203
204 //--------------------------------------------------------------------------
205 /**
206  *  @brief   add poll websocket file destructor
207  *
208  *  @param [in] handler  websocket handler
209  */
210 //--------------------------------------------------------------------------
211 void
212 CicoSCServer::addPollFd(CicoSCUwsHandler *handler)
213 {
214     ICO_DBG("CicoSCServer::addPollFd Enter(fd=%d)", handler->fd);
215     Ecore_Fd_Handler_Flags flags;
216     flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
217
218     handler->ecoreFdHandler = ecore_main_fd_handler_add(handler->fd, flags,
219                                                        ecoreFdCallback,
220                                                        this, NULL, NULL);
221
222     ICO_DBG("Enqueue uwsHandler(0x%08x)", handler);
223     m_uwsHandlerList.push_back(handler);
224
225     ICO_DBG("CicoSCServer::addPollFd Leave");
226 }
227
228 //--------------------------------------------------------------------------
229 /**
230  *  @brief   delete poll websocket file destructor
231  *
232  *  @param [in] handler  websocket handler
233  */
234 //--------------------------------------------------------------------------
235 void
236 CicoSCServer::delPollFd(CicoSCUwsHandler *handler)
237 {
238     ICO_DBG("CicoSCServer::delPollFd Enter");
239
240     ecore_main_fd_handler_del(handler->ecoreFdHandler);
241     handler->ecoreFdHandler = NULL;
242
243     list<CicoSCUwsHandler*>::iterator itr;
244     itr = m_uwsHandlerList.begin();
245     for (; itr != m_uwsHandlerList.end(); ++itr) {
246         if (*itr == handler) {
247             ICO_DBG("Dequeue uwsHandler(0x%08x)", *itr);
248             m_uwsHandlerList.erase(itr);
249             break;
250         }
251     }
252     delete handler;
253
254     ICO_DBG("CicoSCServer::delPollFd Enter");
255 }
256
257 //--------------------------------------------------------------------------
258 /**
259  *  @brief   dispatch receive message process and send message process
260  *
261  *  @param [in] handler  websocket handler
262  *
263  *  @return websocket handler instance on find, NULL on not found
264  */
265 //--------------------------------------------------------------------------
266 void
267 CicoSCServer::dispatch(const CicoSCUwsHandler *handler)
268 {
269 //    ICO_DBG("CicoSCServer::dispatch Enter(handler=0x%08x)", handler);
270
271     if (NULL == handler) {
272         ICO_WRN("handler is null");
273         ICO_DBG("CicoSCServer::dispatch Leave");
274         return;
275     }
276
277     ico_uws_service(handler->uwsContext);
278
279     // There is a possibility that after calling ico_uws_service function,
280     // the file is deleted.  Check whether handler not the disabled.
281     if (false == isExistUwsHandler(handler)) {
282         ICO_DBG("CicoSCServer::dispatch Leave");
283         return;
284     }
285
286     if (true == m_dispatchProcessing) {
287         ICO_DBG("CicoSCServer::dispatch Leave(disptch processing)");
288         return;
289     }
290
291     m_dispatchProcessing = true;
292     list<CicoSCCommand*>::iterator itr;
293     itr = m_recvCmdQueue.begin();
294     while(itr != m_recvCmdQueue.end()) {
295         ICO_DBG("Dequeue command(0x%08x)", (*itr)->cmdid);
296         CicoSCCommand *cmd = *itr;
297         itr = m_recvCmdQueue.erase(itr);
298         switch (cmd->cmdid & MSG_CMD_TYPE_MASK) {
299         case MSG_CMD_TYPE_WINCTRL:
300             //ICO_DBG("command : MSG_CMD_TYPE_WINCTRL");
301             m_windowCtrl->handleCommand(cmd);
302             break;
303         case MSG_CMD_TYPE_INPUTCTRL:
304             //ICO_DBG("command : MSG_CMD_TYPE_INPUTCTRL");
305             m_inputCtrl->handleCommand(cmd);
306             break;
307         case MSG_CMD_TYPE_USERMGR:
308             //ICO_DBG("command : MSG_CMD_TYPE_USERMGR");
309             m_userMgr->handleCommand(cmd);
310             break;
311         case MSG_CMD_TYPE_RESOURCEMGR:
312             //ICO_DBG("command : MSG_CMD_TYPE_RESOURCEMGR");
313             m_resourceMgr->handleCommand(*cmd);
314             break;
315         case MSG_CMD_TYPE_INPUTDEVSETTING:
316             //ICO_DBG("command : MSG_CMD_TYPE_INPUTDEVSETTING");
317             m_inputCtrl->handleCommand(cmd);
318             break;
319         default:
320             ICO_WRN("command: Unknown type");
321             break;
322         }
323         delete cmd;
324     }
325     m_dispatchProcessing = false;
326
327     if (NULL == handler->ecoreFdHandler) {
328         ICO_ERR("ecoreFdHandler is null");
329         ICO_DBG("CicoSCServer::dispatch Leave");
330         return;
331     }
332
333     Eina_Bool flag = ecore_main_fd_handler_active_get(handler->ecoreFdHandler,
334                                                       ECORE_FD_WRITE);
335     if (EINA_TRUE == flag) {
336 //        ICO_DBG("start send message");
337         list<CicoSCMessage*>::iterator send_itr;
338         send_itr = m_sendMsgQueue.begin();
339         while (send_itr != m_sendMsgQueue.end()) {
340 //            ICO_DBG("m_sendMsgQueue.size=%d", m_sendMsgQueue.size());
341             CicoSCMessage* msg = *send_itr;
342             CicoSCUwsHandler *sendHandler = findUwsHandler(msg->getSendToAppid());
343             if (handler != sendHandler) {
344                 ++send_itr;
345                 continue;
346             }
347             send_itr = m_sendMsgQueue.erase(send_itr);
348             ICO_DBG("Dequeue Message(id=%d)", msg->getId());
349             if ((NULL != sendHandler) && (true == sendHandler->serviceFlag)) {
350                 ICO_DBG("<<<SEND appid=%s id=0x%08x msg=%s",
351                         sendHandler->appid.c_str(), sendHandler->id, msg->getData());
352 //                ICO_DBG("called: ico_usw_send called(context=0x%08x id=0x%08x)",
353 //                        sendHandler->uwsContext, sendHandler->id);
354                 ico_uws_send(sendHandler->uwsContext, sendHandler->id,
355                              (unsigned char *)msg->getData(),
356                              strlen(msg->getData()));
357
358                 delete msg;
359
360                 usleep(200);
361             }
362         }
363
364         Ecore_Fd_Handler_Flags flags;;
365         flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR);
366
367         ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
368     }
369
370 //    ICO_DBG("CicoSCServer::dispatch Leave");
371 }
372
373 //--------------------------------------------------------------------------
374 /**
375  *  @brief   send message to application client
376  *
377  *  @param [in] appid   application id of destination
378  *  @param [in] msg     message
379  *
380  *  @return ICO_SYC_EOK on success, other on error
381  */
382 //--------------------------------------------------------------------------
383 int
384 CicoSCServer::sendMessage(const string & appid, CicoSCMessage* msg)
385 {
386     ICO_DBG("CicoSCServer::sendMessage Enter(appid=%s, msg=%s)",
387             appid.c_str(), msg->getData());
388
389     msg->setSendToAppid(appid);
390     ICO_DBG("Enqueue Message(id=%d)", msg->getId());
391     m_sendMsgQueue.push_back(msg);
392
393     CicoSCUwsHandler *handler = findUwsHandler(appid);
394     if (NULL != handler) {
395         Ecore_Fd_Handler_Flags flags;
396         flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ  |
397                                          ECORE_FD_WRITE |
398                                          ECORE_FD_ERROR);
399
400         ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
401
402         dispatch(handler);
403     }
404
405     ICO_DBG("CicoSCServer::sendMessage Leave(EOK)");
406     return ICO_SYC_EOK;
407 }
408
409 //--------------------------------------------------------------------------
410 /**
411  *  @brief   send message to homescreen
412  *
413  *  @param [in] msg     message
414  *
415  *  @return ICO_SYC_EOK on success, other on error
416  */
417 //--------------------------------------------------------------------------
418 int
419 CicoSCServer::sendMessageToHomeScreen(CicoSCMessage* msg)
420 {
421     const CicoSCUser *loginUser = m_userMgr->getLoginUser();
422     if (NULL == loginUser) {
423         ICO_WRN("homescreen unknown");
424         return ICO_SYC_ENOENT;
425     }
426     return sendMessage(loginUser->homescreen, msg);
427 }
428
429 //--------------------------------------------------------------------------
430 /*
431  *  @brief  websocket utility callback function
432  *
433  *  @param [in] context     context
434  *  @param [in] event       event kinds
435  *  @param [in] id          client id
436  *  @param [in] detail      event detail
437  *  @param [in] data        user data
438  */
439 //--------------------------------------------------------------------------
440 void
441 CicoSCServer::uwsReceiveEventCB(const struct ico_uws_context *context,
442                                 const ico_uws_evt_e event,
443                                 const void *id,
444                                 const ico_uws_detail *detail,
445                                 void *user_data)
446 {
447     if (NULL == user_data) {
448         ICO_ERR("user_data is NULL");
449         return;
450     }
451
452     CicoSCServer* server = static_cast<CicoSCServer*>(user_data);
453     server->receiveEventCB(context, event, id, detail, user_data);
454 }
455
456 //--------------------------------------------------------------------------
457 /**
458  *  @brief   ecore file destructor callback fucntion
459  *
460  *  @param [in] data        user data
461  *  @param [in] handler     ecore file destructor handler
462  *
463  *  @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
464  */
465 //--------------------------------------------------------------------------
466 Eina_Bool
467 CicoSCServer::ecoreFdCallback(void *data, Ecore_Fd_Handler *ecoreFdhandler)
468 {
469 //    ICO_DBG("CicoSCServer::ecoreFdCallback Enter");
470
471     CicoSCUwsHandler *handler = NULL;
472     handler =  static_cast<CicoSCServer*>(data)->findUwsHandler(ecoreFdhandler);
473     if (NULL != handler) {
474         static_cast<CicoSCServer*>(data)->dispatch(handler);
475     }
476
477 //    ICO_DBG("CicoSCServer::ecoreFdCallback Leave");
478     return ECORE_CALLBACK_RENEW;
479 }
480
481 //--------------------------------------------------------------------------
482 /**
483  *  @brief   websocket callback function
484  *
485  *  @param [in] context     websocket context
486  *  @param [in] event       changed event
487  *  @param [in] id          source applicatin id
488  *  @param [in] detail      event detail information
489  *  @param [in] user_data   user data
490  */
491 //--------------------------------------------------------------------------
492 void
493 CicoSCServer::receiveEventCB(const struct ico_uws_context *context,
494                              const ico_uws_evt_e          event,
495                              const void                   *id,
496                              const ico_uws_detail         *detail,
497                              void                         *user_data)
498 {
499 //    ICO_DBG("CicoSCServer::receiveEventCB Enter");
500
501     // find handler
502     CicoSCUwsHandler *handler = findUwsHandler(context, id);
503     // If not found handler, create new handler
504     if (NULL == handler) {
505         handler = new CicoSCUwsHandler();
506         handler->uwsContext = (struct ico_uws_context*)context;
507         handler->id = (void*)(id);
508         handler->serviceFlag = false;
509     }
510
511     switch (event) {
512     case ICO_UWS_EVT_OPEN:
513         ICO_DBG(">>>RECV ICO_UWS_EVT_OPEN(id=0x%08x)", (int)id); 
514         break;
515     case ICO_UWS_EVT_CLOSE:
516         ICO_DBG(">>>RECV ICO_UWS_EVT_CLOSE(id=0x%08x)", (int)id);
517         break;
518     case ICO_UWS_EVT_RECEIVE:
519     {
520         ICO_DBG(">>>RECV ICO_UWS_EVT_RECEIVE(id=0x%08x, msg=%s, len=%d)", 
521                 (int)id, (char *)detail->_ico_uws_message.recv_data,
522                 detail->_ico_uws_message.recv_len);
523
524         // convert message to command
525         CicoSCCommand *cmd = new CicoSCCommand();
526         cmd->parseMessage((const char*)detail->_ico_uws_message.recv_data);
527
528         // update handler appid
529         if (cmd->cmdid == MSG_CMD_SEND_APPID) {
530             if (0 == cmd->appid.length()) {
531                 ICO_WRN("command argument invalid appid null");
532                 break;
533             }
534             handler->appid = cmd->appid;
535             handler->serviceFlag = true;
536             ICO_DBG("handler.appid=%s", handler->appid.c_str());
537
538             Ecore_Fd_Handler_Flags flags;
539             flags = (Ecore_Fd_Handler_Flags)(ECORE_FD_READ  |
540                                              ECORE_FD_WRITE |
541                                              ECORE_FD_ERROR);
542
543             ecore_main_fd_handler_active_set(handler->ecoreFdHandler, flags);
544
545             notifyConnected(handler->appid);
546             break;
547         }
548         
549         // Enqueue command
550         ICO_DBG("Enqueue command(0x%08x)", cmd->cmdid);
551         m_recvCmdQueue.push_back(cmd);
552         break;
553     }
554     case ICO_UWS_EVT_ERROR:
555         ICO_DBG(">>>RECV ICO_UWS_EVT_ERROR(id=0x%08x, err=%d)", 
556                 (int)id, detail->_ico_uws_error.code);
557         break;
558     case ICO_UWS_EVT_ADD_FD:
559         ICO_DBG(">>>RECV ICO_UWS_EVT_ADD_FD(id=0x%08x, fd=%d)",
560                     (int)id, detail->_ico_uws_fd.fd);
561         handler->fd = detail->_ico_uws_fd.fd;
562         addPollFd(handler);
563         break;
564     case ICO_UWS_EVT_DEL_FD:
565         ICO_DBG(">>>RECV ICO_UWS_EVT_DEL_FD(id=0x%08x, fd=%d)",
566                     (int)id, detail->_ico_uws_fd.fd);
567         delPollFd(handler);
568         break;
569     default:
570         break;
571     }
572 //    ICO_DBG("CicoSCServer::receiveEventCB Leave");
573 }
574
575 //--------------------------------------------------------------------------
576 /**
577  *  @brief   find websocket handler by context and id
578  *
579  *  @param [in] context     websocket context
580  *  @param [in] id          id
581  *
582  *  @return websocket handler instance on find, NULL on not found
583  */
584 //--------------------------------------------------------------------------
585 CicoSCUwsHandler*
586 CicoSCServer::findUwsHandler(const struct ico_uws_context *context,
587                              const void                   *id)
588 {
589     list<CicoSCUwsHandler*>::iterator itr;
590     itr = m_uwsHandlerList.begin();
591     for (; itr != m_uwsHandlerList.end(); ++itr) {
592 //        ICO_DBG("handler->context=%p handler->id=%p context=%p id=%p",
593 //                (*itr)->uwsContext, (*itr)->id, context, id);
594         if (((*itr)->uwsContext == context) &&
595             ((*itr)->id == id)) {
596             return *itr;
597         }
598     }
599     return NULL;
600 }
601
602 //--------------------------------------------------------------------------
603 /**
604  *  @brief   find websocket handler by ecore file destructor handler
605  *
606  *  @param [in] ecoreFdHandler  ecore file destructor handler
607  *
608  *  @return websocket handler instance on find, NULL on not found
609  */
610 //--------------------------------------------------------------------------
611 CicoSCUwsHandler*
612 CicoSCServer::findUwsHandler(const Ecore_Fd_Handler *ecoreFdHandler)
613 {
614     list<CicoSCUwsHandler*>::iterator itr;
615     itr = m_uwsHandlerList.begin();
616     for (; itr != m_uwsHandlerList.end(); ++itr) {
617         if ((*itr)->ecoreFdHandler == ecoreFdHandler) {
618             return *itr;
619         }
620     }
621     return NULL;
622 }
623
624 //--------------------------------------------------------------------------
625 /**
626  *  @brief   find websocket handler by appid
627  *
628  *  @param [in] addid   application id
629  *
630  *  @return websocket handler instance on find, NULL on not found
631  */
632 //--------------------------------------------------------------------------
633 CicoSCUwsHandler*
634 CicoSCServer::findUwsHandler(const string & appid)
635 {
636     list<CicoSCUwsHandler*>::iterator itr;
637     itr = m_uwsHandlerList.begin();
638     for (; itr != m_uwsHandlerList.end(); ++itr) {
639 //        ICO_DBG("handler->id=%p handler->appid=%s appid=%s",
640 //                (*itr)->id, (*itr)->appid.c_str(), appid.c_str());
641         if ((*itr)->appid == appid) {
642             return *itr;
643         }
644     }
645     return NULL;
646 }
647
648 //--------------------------------------------------------------------------
649 /**
650  *  @brief   find websocket handler by appid
651  *
652  *  @param [in] handler     websocket handler instance
653  *
654  *  @return true on exist, false on not exist
655  */
656 //--------------------------------------------------------------------------
657 bool
658 CicoSCServer::isExistUwsHandler(const CicoSCUwsHandler *handler)
659 {   
660     list<CicoSCUwsHandler*>::iterator itr;
661     itr = m_uwsHandlerList.begin();
662     for (; itr != m_uwsHandlerList.end(); ++itr) {
663         if (*itr == handler) {
664             return true;
665         }
666     }
667     return false;
668 }
669
670 //--------------------------------------------------------------------------
671 /**
672  *  @brief  notify information to homescreen on connected
673  *
674  *  @param [in] appid   application id
675  */
676 //--------------------------------------------------------------------------
677 void
678 CicoSCServer::notifyConnected(const std::string & appid)
679 {
680     const CicoSCUser *loginUser = m_userMgr->getLoginUser();
681     if (NULL == loginUser) {
682         ICO_WRN("homescreen unknown");
683         return;
684     }
685
686     // if appid equal homescreen
687     if (0 == loginUser->homescreen.compare(appid)) {
688         if (NULL != m_policyMgr) {
689             m_policyMgr->notifyConnected(appid);
690         }
691     }
692 }
693 // vim:set expandtab ts=4 sw=4: