Tizen 2.1 base
[platform/framework/native/app-service.git] / plugins / accessory-condition-handler / AccessoryConditionHandler.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://floralicense.org/license/
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        AccessoryConditionHandler.cpp
20  * @brief       This is the implementation file of the AccessoryConditionHandler class.
21  *
22  */
23
24 #include <unique_ptr.h>
25 #include <new>
26 #include <string.h>
27
28 #include <FApp_AppManagerImpl.h>
29 #include <FApp_AppLaunchConditionHandlerBase.h>
30 #include <FBase_StringConverter.h>
31 #include "AccessoryConditionHandler.h"
32 #include "AccessoryMonitor.h"
33
34 using namespace std;
35
36 using namespace Tizen::App;
37 using namespace Tizen::Base;
38 using namespace Tizen::Base::Collection;
39
40 const static char TIZEN_REQUEST[] = {"tizen.request"};
41 const static char TIZEN_RESPONSE[] = {"tizen.response"};
42 const static char TIZEN_LAUNCH_BY_CONDITION[] = {"tizen.launch_by_condition"};
43 const static char TIZEN_INITIALIZE[] = {"tizen.initialize"};
44 const static char TIZEN_SUCCESS[] = {"tizen.success"};
45 const static char TIZEN_FAILURE[] = {"tizen.failure"};
46 const static char TIZEN_PING[] = {"tizen.ping"};
47
48 const static char ACCESSORY_SERIAL_COMMAND_MESSAGE[] = {"Osp:Msg"};
49 const static char ACCESSORY_SERIAL_COMMAND_REQUEST[] = {"Osp:Req"};
50 const static char ACCESSORY_SERIAL_COMMAND_RESPONSE[] = {"Osp:Res"};
51 const static char ACCESSORY_SERIAL_COMMAND_HELLO[] = {"Hello"};
52 const static char ACCESSORY_SERIAL_COMMAND_OK[] = {"OK"};
53 const static char ACCESSORY_SERIAL_COMMAND_SUCCESS[] = {"Susccess"};
54 const static char ACCESSORY_SERIAL_COMMAND_FAIL[] = {"Fail"};
55
56 AccessoryConditionHandler::AccessoryConditionHandler()
57         :__pAccessoryMonitor(null)
58 {
59         result r = E_SUCCESS;
60         SysLog(NID_SYS, "AccessoryConditionHandler is initialized");
61
62         __pAccessoryMonitor = AccessoryMonitor::GetInstance();
63         r = __pAccessoryMonitor->Construct(this);
64
65         if (IsFailed(r))
66         {
67                 SysLogException(NID_SYS, r, "Failed to initialize AccessoryMonitor");
68                 return;
69         }
70
71         r = __appConditionList.Construct();
72
73         if (IsFailed(r))
74         {
75                 SysLogException(NID_SYS, r, "Failed to initialize Condition List");
76         }
77 }
78
79 AccessoryConditionHandler::~AccessoryConditionHandler()
80 {
81         if (__pAccessoryMonitor != null)
82         {
83                 __pAccessoryMonitor->ReleaseInstance();
84         }
85 }
86
87 result
88 AccessoryConditionHandler::Register(_AppLaunchCondition& operation)
89 {
90         String condition = operation.GetConditionString();
91         SysLog(NID_SYS, "Request to register accessory process, [%S][%S]", operation.GetAppId().GetPointer(), operation.GetConditionString().GetPointer());
92
93         SysTryReturnResult(NID_SYS, condition.StartsWith(L"Serial='", 0) == true, E_INVALID_FORMAT, "It is not compatible format.");
94         SysTryReturnResult(NID_SYS, condition.EndsWith(L"'") == true, E_INVALID_FORMAT, "It is not compatible format.");
95
96         condition.SubString(8, condition.GetLength() - 9, condition);
97         SysLog(NID_SYS, "Requested String is %ls", condition.GetPointer());
98
99         unique_ptr<IEnumerator> pEnum (__appConditionList.GetEnumeratorN());
100         SysTryReturnResult(NID_SYS, pEnum != null, E_SYSTEM, "Enumerator is not created.");
101
102         while(pEnum->MoveNext() == E_SUCCESS)
103         {
104                 _AppLaunchCondition* pCondition = static_cast<_AppLaunchCondition*> (pEnum->GetCurrent());
105                 if(pCondition->GetAppId() == operation.GetAppId())
106                 {
107                         SysTryReturnResult(NID_SYS, pCondition->GetConditionString() != condition, E_OBJ_ALREADY_EXIST, "The specified condition(%ls) is already registered.", condition.GetPointer());
108                 }
109         }
110         __appConditionList.Add(operation);
111
112         return E_SUCCESS;
113 }
114
115 result
116 AccessoryConditionHandler::Unregister(_AppLaunchCondition& operation)
117 {
118         SysLog(NID_SYS, "Request to unregister accessory process");
119
120         unique_ptr<IEnumerator> pEnum (__appConditionList.GetEnumeratorN());
121         SysTryReturnResult(NID_SYS, pEnum != null, E_SYSTEM, "Enumerator is not created.");
122
123         while(pEnum->MoveNext() == E_SUCCESS)
124         {
125                 _AppLaunchCondition* pCondition = static_cast<_AppLaunchCondition*> (pEnum->GetCurrent());
126                 if(pCondition->GetAppId() == operation.GetAppId())
127                 {
128                         if(pCondition->GetConditionString() == operation.GetConditionString())
129                         {
130                                 __appConditionList.Remove(*pCondition);
131                                 return E_SUCCESS;
132                         }
133                 }
134         }
135         return E_OBJ_NOT_FOUND;
136 }
137
138 char*
139 AccessoryConditionHandler::GetValueFromCommandN(const char* command, int length)
140 {
141         if (command == null || length <= 0)
142                 return null;
143
144         int valueLength = 0;
145         char* value = null;
146
147         char* indexStart = strstr(const_cast < char* > (command), "'");
148
149         if (indexStart == null)
150                 return null;
151
152         indexStart ++;
153
154         char* indexEnd = strstr(indexStart, "'");
155
156         if (indexEnd == null)
157                 return null;
158
159         valueLength = indexEnd - indexStart;
160
161         value = new (std::nothrow) char[valueLength + 1];
162         memset(value, 0, valueLength + 1);
163
164         strncpy(value, indexStart, valueLength);
165
166         return value;
167 }
168
169 bool
170 AccessoryConditionHandler::MessageCommandHandle(const char* command, int length)
171 {
172         result r = E_SUCCESS;
173         bool resultValue = true;
174         char* commandValue = GetValueFromCommandN(command, length);
175         char* response = null;
176
177         SysTryCatch(NID_IO, commandValue != null, resultValue = false, E_SYSTEM, "[E_SYSTEM] there is no message command");
178
179         SysLog(NID_IO, "Message command is [%s]", commandValue);
180
181         if (strcmp(commandValue, ACCESSORY_SERIAL_COMMAND_HELLO) == 0)
182         {
183                 SysLog(NID_IO, "This is hello request");
184
185                 int responseLength = strlen(ACCESSORY_SERIAL_COMMAND_MESSAGE) + strlen(ACCESSORY_SERIAL_COMMAND_OK) + 5;
186                 response = new (std::nothrow) char[responseLength];
187                 memset(response, 0, responseLength);
188
189                 response = strcat(response, ACCESSORY_SERIAL_COMMAND_MESSAGE);
190                 response = strcat(response, "='");
191                 response = strcat(response, ACCESSORY_SERIAL_COMMAND_OK);
192                 response = strcat(response, "'\r\n");
193
194                 r = __pAccessoryMonitor->SendData(response, strlen(response));
195
196                 SysTryCatch(NID_IO, r == E_SUCCESS, resultValue = true, E_SYSTEM, "[%s] Fail to send data");
197         }
198         else
199         {
200                 SysLog(NID_IO, "[%s] is not supported command", commandValue);
201         }
202
203 CATCH:
204         delete [] commandValue;
205         delete [] response;
206
207         return resultValue;
208 }
209
210 bool
211 AccessoryConditionHandler::TizenRequestCommand(const char* command, int length)
212 {
213         int ret = 0;
214         char request[16] = {0,};
215         char value[32] = {0, };
216         char condition[512] = {0, };
217         char* response = null;
218         char* responseMessage = null;
219         result r = E_SUCCESS;
220
221         SysTryCatch(NID_SYS, command != null && length > 0, ,E_SYSTEM, "Condition is not available.");
222
223         ret = sscanf(command, "%13s='%s %s'", request, value, condition);
224         
225         if(ret == 2)
226         {
227                 value[strlen(value) -1 ] = 0;
228         }
229         else if(ret == 3)
230         {
231                 condition[strlen(condition) -1 ] = 0;
232         }
233         else
234         {
235                 responseMessage = const_cast <char*> (TIZEN_FAILURE);
236         }
237
238         SysLog(NID_SYS, "Request: %s, %s, %s, %d", request, value, condition, ret);
239
240         if(strcmp(request, TIZEN_REQUEST) == 0 && (ret == 2 || ret ==3))
241         {
242                 SysLog(NID_SYS, "Command is request.");
243                 if(strcmp(value, TIZEN_LAUNCH_BY_CONDITION) == 0)
244                 {
245                         SysLog(NID_SYS, "Command is launch request.");
246
247                         unique_ptr<IEnumerator> pEnum (__appConditionList.GetEnumeratorN());
248                         SysTryCatch(NID_IO, pEnum != null, , E_SYSTEM, "Enumerator is not created.");
249
250                         while(pEnum->MoveNext() == E_SUCCESS)
251                         {
252                                 _AppLaunchCondition* pCondition = static_cast<_AppLaunchCondition*>(pEnum->GetCurrent());
253                                 SysTryCatch(NID_SYS, pCondition != null, ,E_SYSTEM, "Condition is not available.");
254                                 String registered = pCondition->GetConditionString();
255                                 String requested(condition);
256
257                                 registered.SubString(8, registered.GetLength() - 9, registered);
258                                 if(registered == requested)
259                                 {
260                                         SysLog(NID_SYS, "Application[%ls] launch is required.", pCondition->GetAppId().GetPointer());
261                                         Fire(*pCondition);
262                                         responseMessage = const_cast <char*> (TIZEN_SUCCESS);
263                                         break;
264                                 }
265                         }
266                 }
267                 else if(strcmp(value, TIZEN_PING) == 0)
268                 {
269                         SysLog(NID_SYS, "Command is launch request.");
270                         responseMessage = const_cast <char*> (TIZEN_PING);
271                 }
272                 else if(strcmp(value, TIZEN_INITIALIZE) == 0)
273                 {
274                         SysLog(NID_SYS, "Command is initialize.");
275                         responseMessage = const_cast <char*> (TIZEN_SUCCESS);
276                 }
277         }
278
279 CATCH:
280         if(responseMessage == null)
281         {
282                 responseMessage = const_cast <char*> (TIZEN_FAILURE);
283         }
284
285         int responseLength = strlen(TIZEN_RESPONSE) + strlen(responseMessage) + 6;
286         response = new (std::nothrow) char[responseLength];
287         if(response == null)
288         {
289                 SysLogException(NID_SYS, E_OUT_OF_MEMORY, "It is failed to allocate memory");
290                 return false;
291         }
292
293         memset(response, 0, responseLength);
294         response = strcat(response, TIZEN_RESPONSE);
295         response = strcat(response, "='");
296         response = strcat(response, responseMessage);
297         response = strcat(response, "'\r\n");
298
299         r = __pAccessoryMonitor->SendData(response, strlen(response)+1);
300         delete [] response;
301
302         if(r != E_SUCCESS)
303         {
304                 return false;
305         }
306
307         return true;
308 }
309 bool
310 AccessoryConditionHandler::RequestCommandHandle(const char* command, int length)
311 {
312         int ret = 0;
313         result r = E_SUCCESS;
314         char* response = null;
315         char* resultValue = null;
316         char condition[512] = {0, };
317         int responseLength = 0;
318
319         SysTryCatch(NID_SYS, command != null && length > 0, ,E_SYSTEM, "Condition is not available.");
320
321         ret = sscanf(command, "Osp:Req='%s'", condition);
322         SysTryCatch(NID_SYS, ret == 1, ,E_SYSTEM, "Condition is not available.(%d, %s/%s)", ret,  condition, command);
323
324         condition[strlen(condition) -1 ] = 0;
325
326         if(ret == 1)
327         {
328                 unique_ptr<IEnumerator> pEnum (__appConditionList.GetEnumeratorN());
329                 SysTryCatch(NID_IO, pEnum != null, , E_SYSTEM, "Enumerator is not created.");
330
331                 while(pEnum->MoveNext() == E_SUCCESS)
332                 {
333                         _AppLaunchCondition* pCondition = static_cast<_AppLaunchCondition*>(pEnum->GetCurrent());
334                         SysTryCatch(NID_SYS, pCondition != null, ,E_SYSTEM, "Condition is not available.");
335                         String registered = pCondition->GetConditionString();
336                         String requested(condition);
337
338                         registered.SubString(8, registered.GetLength() - 9, registered);
339                         if(registered == requested)
340                         {
341                                 SysLog(NID_SYS, "Application[%ls] launch is required.", pCondition->GetAppId().GetPointer());
342                                 Fire(*pCondition);
343                                 resultValue = const_cast<char*>(ACCESSORY_SERIAL_COMMAND_SUCCESS);
344                                 break;
345                         }
346                 }
347         }
348
349 CATCH:
350         if(resultValue == null)
351         {
352                 resultValue = const_cast<char*>(ACCESSORY_SERIAL_COMMAND_FAIL);
353         }
354
355         responseLength = strlen(ACCESSORY_SERIAL_COMMAND_RESPONSE) + strlen(resultValue) + 6;
356         response = new (std::nothrow) char[responseLength];
357         if(response == null)
358         {
359                 SysLogException(NID_SYS, E_OUT_OF_MEMORY, "It is failed to allocate memory");
360                 return false;
361         }
362
363         memset(response, 0, responseLength);
364         response = strcat(response, ACCESSORY_SERIAL_COMMAND_RESPONSE);
365         response = strcat(response, "='");
366         response = strcat(response, resultValue);
367         response = strcat(response, "'\r\n");
368
369         r = __pAccessoryMonitor->SendData(response, strlen(response)+1);
370         delete [] response;
371
372         if(r != E_SUCCESS)
373         {
374                 return false;
375         }
376
377         return true;
378 }
379
380 bool
381 AccessoryConditionHandler::ProcessPrimitiveCommand(const char* command, int length)
382 {
383         bool resultValue = false;
384
385         SysLog(NID_IO, "serial data is forwarded to ProcessPrimitiveCommand [%s]", command);
386         SysTryCatch(NID_IO, command != null && length > 0, resultValue = false, E_INVALID_ARG, "[E_INVALID_ARG] There is no available data");
387
388         if (strncmp(command, ACCESSORY_SERIAL_COMMAND_MESSAGE, strlen(ACCESSORY_SERIAL_COMMAND_MESSAGE)) == 0)
389         {
390                 resultValue = MessageCommandHandle(command, length);
391                 SysLog(NID_SYS, "Message result: %d", resultValue);
392         }
393         else if (strncmp(command, ACCESSORY_SERIAL_COMMAND_REQUEST, strlen(ACCESSORY_SERIAL_COMMAND_REQUEST)) == 0)
394         {
395                 resultValue = RequestCommandHandle(command, length);
396                 SysLog(NID_SYS, "Request result: %d", resultValue);
397         }
398         else if (strncmp(command, TIZEN_REQUEST, strlen(TIZEN_REQUEST)) == 0
399                 || strncmp(command, TIZEN_PING, strlen(TIZEN_PING)) == 0)
400         {
401                 resultValue = TizenRequestCommand(command, length);
402                 SysLog(NID_SYS, "Request result: %d", resultValue);
403         }
404
405 CATCH:
406         SysLog(NID_SYS, "result: %d", resultValue);
407         return resultValue;
408
409 }
410
411 /////////////////////////////////////////////////////////////////////////
412 //      All plugins must provide both a creation and a destruction function
413 /////////////////////////////////////////////////////////////////////////
414 extern "C"
415 {
416 _OSP_EXPORT_ _AppLaunchConditionHandlerBase*
417 CreatePlugin(void)
418 {
419         SysLog(NID_IO, "CreatePlugin is called");
420     return new (std::nothrow) AccessoryConditionHandler;
421 }
422
423 _OSP_EXPORT_ void
424 DestroyPlugin(_AppLaunchConditionHandlerBase* p)
425 {
426     delete p;
427 }
428 }//extern "C"