2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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.
17 ////////////////////////////////////////////////////////////////////////////////////////////////////
18 /// \defgroup <<Group Tag>> <<Group Name>>
19 /// \ingroup tag_NS_NPPService
21 ////////////////////////////////////////////////////////////////////////////////////////////////////
23 ////////////////////////////////////////////////////////////////////////////////////////////////////
24 /// \ingroup tag_NS_NPPService
25 /// \brief This file contain declaration of class CNorPersistenceWorker and CArchive.
26 /// Class CNorPersistenceWorker holds the implementation for worker thread.
27 /// Class CArchive holds the implementation for archive.
29 ////////////////////////////////////////////////////////////////////////////////////////////////////
31 #include <native_service/ns_timer_if.hpp>
32 #include <native_service/ns_np_service_if.h>
33 #include <native_service/ns_utility_sys.hpp>
34 #include <native_service/frameworkunified_framework_if.h>
35 #include <native_service/frameworkunified_multithreading.h>
36 #include <native_service/frameworkunified_service_protocol.h>
37 #include <native_service/ns_np_service_protocol.h>
38 #include <native_service/ns_np_service_nor_persistence.h>
41 #include <sys/types.h>
43 #include <boost/bind.hpp>
48 #include <native_service/ns_np_service_nor_persistence_internal.h>
49 #include "ns_npp_types.h"
50 #include "ns_npp_notificationpersistentservicelog.h"
51 #include "ns_npp_fs_directory.h"
52 #include "ns_npp_persistent_data.h"
53 #include "ns_npp_nor_persistence_worker_thread.h"
57 typedef std::string NotificationName;
58 typedef std::map<NotificationName, CTimerHelper *> TTimerList;
59 static TTimerList g_mtimers; /// List of all the timers for immediate persistence notifications
60 CMutex g_objmutextimerdata; /// Mutex object on g_mtimers
62 // Template function for NorWorkerCallback
63 template <typename C, eFrameworkunifiedStatus(C::*M)(HANDLE)> EFrameworkunifiedStatus NorWorkerCallback(HANDLE hthread) {
64 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
66 C *l_pClass = static_cast<C *>(FrameworkunifiedGetThreadSpecificData(hthread));
68 if (l_pClass) { // LCOV_EXCL_BR_LINE 6: l_pClass can't be NULL
69 l_estatus = (l_pClass->*M)(hthread);
74 static FrameworkunifiedProtocolCallbackHandler aServiceHandlers[] = { // NOLINT (readability/naming)
75 { NOR_PERSISTENCE_TIMER_START, NorWorkerCallback<CNorPersistenceWorker,
76 &CNorPersistenceWorker::OnNorPersistenceTimerStart>},
77 { NOR_PERSISTENCE_REGISTER, NorWorkerCallback<CNorPersistenceWorker,
78 &CNorPersistenceWorker::RegisterImmediatePersistNotification>},
79 { NOR_PERSISTENCE_UNREGISTER, NorWorkerCallback<CNorPersistenceWorker,
80 &CNorPersistenceWorker::UnregisterImmediatePersistNotification>},
81 { NOR_PERSISTENCE_ONSHUTDOWN, NorWorkerCallback<CNorPersistenceWorker,
82 &CNorPersistenceWorker::OnShutdown>},
83 { NOR_PERSISTENCE_CHANGE_CATEGORY, NorWorkerCallback<CNorPersistenceWorker,
84 &CNorPersistenceWorker::OnCategoryChange>}
87 ////////////////////////////////////////////////////////////////////////////////////////////////////
88 /// NSPNorPersistenceWorkerOnStart
89 /// Callback method on start of worker thread
90 ////////////////////////////////////////////////////////////////////////////////////////////////////
91 EFrameworkunifiedStatus NSPNorPersistenceWorkerOnStart(HANDLE hthread) {
92 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
93 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
95 if (NULL != hthread) { // LCOV_EXCL_BR_LINE 6: hthread can't be NULL
96 // Note: this variable is made static just to ignore the resource leak showing in coverity analysis
97 static CNorPersistenceWorker *l_pcnorpersistenceworker = new(std::nothrow) CNorPersistenceWorker;
99 if (NULL != l_pcnorpersistenceworker) { // LCOV_EXCL_BR_LINE 5: new's error case
100 l_estatus = FrameworkunifiedSetThreadSpecificData(hthread, l_pcnorpersistenceworker);
102 if (eFrameworkunifiedStatusOK == l_estatus) { // LCOV_EXCL_BR_LINE 4: NSFW error case
103 l_estatus = FrameworkunifiedAttachCallbacksToDispatcher(
104 hthread, AppName, aServiceHandlers, static_cast<UI_32>(_countof(aServiceHandlers)));
106 // LCOV_EXCL_START 4: NSFW error case
107 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
108 delete l_pcnorpersistenceworker;
109 l_pcnorpersistenceworker = NULL;
113 // LCOV_EXCL_START 5: new's error case
114 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
115 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Worker Object Null.");
116 l_estatus = eFrameworkunifiedStatusNullPointer;
120 // LCOV_EXCL_START 6: hthread can't be NULL
121 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
122 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Thread App Handle Null.");
123 l_estatus = eFrameworkunifiedStatusInvldHandle;
127 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
131 ////////////////////////////////////////////////////////////////////////////////////////////////////
132 /// NSPNorPersistenceWorkerOnStop
133 /// Callback method on stop of worker thread
134 ////////////////////////////////////////////////////////////////////////////////////////////////////
135 EFrameworkunifiedStatus NSPNorPersistenceWorkerOnStop(HANDLE hthread) { // LCOV_EXCL_START 200: can't test
136 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
137 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
138 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
140 if (NULL != hthread) {
141 CNorPersistenceWorker *l_pcnorpersistenceworker = static_cast<CNorPersistenceWorker *>(FrameworkunifiedGetThreadSpecificData(
144 if (NULL != l_pcnorpersistenceworker) {
145 delete l_pcnorpersistenceworker;
146 l_pcnorpersistenceworker = NULL;
148 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Worker Object Null");
149 l_estatus = eFrameworkunifiedStatusNullPointer;
152 if (eFrameworkunifiedStatusOK != (l_estatus = FrameworkunifiedSetThreadSpecificData(hthread, NULL))) {
153 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedSetThreadSpecificData error, status=%d", l_estatus);
156 PCSTR l_cservice = FrameworkunifiedGetAppName(hthread);
157 if (NULL != l_cservice) {
158 if (eFrameworkunifiedStatusOK != (l_estatus = FrameworkunifiedDetachServiceFromDispatcher(hthread, l_cservice))) {
159 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Error detaching service %s from dispatcher, status=%d", l_cservice, l_estatus);
162 l_estatus = eFrameworkunifiedStatusNullPointer;
163 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedGetAppName returned NULL");
166 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Thread App Handle Null.");
167 l_estatus = eFrameworkunifiedStatusInvldHandle;
169 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
175 ////////////////////////////////////////////////////////////////////////////////////////////////////
176 /// Class : CNorPersistenceWorker
177 ////////////////////////////////////////////////////////////////////////////////////////////////////
179 ////////////////////////////////////////////////////////////////////////////////////////////////////
180 /// CNorPersistenceWorker
181 /// Constructor of CNorPersistenceWorker class
182 ////////////////////////////////////////////////////////////////////////////////////////////////////
183 CNorPersistenceWorker::CNorPersistenceWorker() {
184 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
185 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
188 ////////////////////////////////////////////////////////////////////////////////////////////////////
189 /// ~CNorPersistenceWorker
190 /// Destructor of CNorPersistenceWorker class
191 ////////////////////////////////////////////////////////////////////////////////////////////////////
192 CNorPersistenceWorker::~CNorPersistenceWorker() {
193 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
194 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
197 ////////////////////////////////////////////////////////////////////////////////////////////////////
198 /// OnNorPersistenceTimerStart
199 /// This function starts the respective timer of the notification.
200 ////////////////////////////////////////////////////////////////////////////////////////////////////
201 EFrameworkunifiedStatus CNorPersistenceWorker::OnNorPersistenceTimerStart(HANDLE f_hThread) {
202 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusFail;
203 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
205 TNorPersistenceNotifInfoHeader *l_ptNorPersistentData = NULL;
206 UI_32 l_ui32ReceivedDataLength = FrameworkunifiedGetMsgLength(f_hThread);
207 UI_8 *l_pui32ReceivedData = new(std::nothrow) UI_8[l_ui32ReceivedDataLength];
209 if (l_ui32ReceivedDataLength >= sizeof(TNorPersistenceNotifInfoHeader)) { // LCOV_EXCL_BR_LINE 200: l_ui32ReceivedDataLength is bigger than sizeof(TNorPersistenceNotifInfoHeader) // NOLINT[whitespace/line_length]
210 if (NULL != l_pui32ReceivedData) { // LCOV_EXCL_BR_LINE 5: new's error case
211 std::memset(l_pui32ReceivedData, 0, l_ui32ReceivedDataLength);
212 l_estatus = FrameworkunifiedGetMsgDataOfSize(f_hThread, l_pui32ReceivedData, l_ui32ReceivedDataLength, eSMRRelease);
213 if (eFrameworkunifiedStatusOK == l_estatus) { // LCOV_EXCL_BR_LINE 4: NSFW error case
214 TTimerList::iterator l_itTimerList;
215 l_ptNorPersistentData = static_cast<TNorPersistenceNotifInfoHeader *>(static_cast<PVOID>(l_pui32ReceivedData));
217 g_objmutextimerdata.WriteLock();
218 // find the corresponding timer object in the list of timers
219 l_itTimerList = g_mtimers.find(l_ptNorPersistentData->m_cnotificationname);
220 if (g_mtimers.end() != l_itTimerList) { // LCOV_EXCL_BR_LINE 200: the notification must be registered
221 if (NULL != (l_itTimerList->second)) { // LCOV_EXCL_BR_LINE 200: l_itTimerList->second can't be null
222 if (NULL != (l_itTimerList->second)->m_pui8HeaderAndData) {
223 delete[](l_itTimerList->second)->m_pui8HeaderAndData;
224 (l_itTimerList->second)->m_pui8HeaderAndData = NULL;
227 // Update specific immediate persistence notification data
228 (l_itTimerList->second)->m_pui8HeaderAndData = l_pui32ReceivedData;
230 // if corresponding timer is not already running start it.
231 if (!(l_itTimerList->second)->IsRunning()) {
232 (l_itTimerList->second)->Start();
233 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Timer started, Notfn=%s", l_ptNorPersistentData->m_cnotificationname);
235 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Timer already running for notfn %s. Data updated",
236 l_ptNorPersistentData->m_cnotificationname);
239 l_estatus = eFrameworkunifiedStatusOK;
241 // LCOV_EXCL_START 200: l_itTimerList->second can't be null
242 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
243 l_estatus = eFrameworkunifiedStatusNullPointer;
244 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Immediate persistence: Timer object NULL for Notfn:%s.",
245 l_ptNorPersistentData->m_cnotificationname);
249 // LCOV_EXCL_START 200: the notification must be registered
250 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
251 l_estatus = eFrameworkunifiedStatusFail;
252 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Immediate persistence notification not registered. Notification: %s ",
253 l_ptNorPersistentData->m_cnotificationname != 0 ? l_ptNorPersistentData->m_cnotificationname : NULL);
256 g_objmutextimerdata.Unlock();
258 // LCOV_EXCL_START 4: NSFW error case
259 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
260 l_estatus = eFrameworkunifiedStatusFail;
261 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
262 "FrameworkunifiedGetMsgDataOfSize failed while retrieving immediate persistence notfn data. Status:0x%x ", l_estatus);
266 // LCOV_EXCL_START 5: new's error case
267 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
268 l_estatus = eFrameworkunifiedStatusNullPointer;
269 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Unable to allocate data. Can't persist.");
273 // LCOV_EXCL_START 200: l_ui32ReceivedDataLength is bigger than sizeof(TNorPersistenceNotifInfoHeader)
274 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
275 l_estatus = eFrameworkunifiedStatusInvldBuf;
276 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Invalid data length received. Can't persist.");
280 if ((eFrameworkunifiedStatusOK != l_estatus) && (NULL != l_pui32ReceivedData)) {
281 delete[] l_pui32ReceivedData;
282 l_pui32ReceivedData = NULL;
285 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
289 ////////////////////////////////////////////////////////////////////////////////////////////////////
290 /// RegisterImmediatePersistNotification
291 /// It creates a timer corresponding to the notification.
292 ////////////////////////////////////////////////////////////////////////////////////////////////////
293 EFrameworkunifiedStatus CNorPersistenceWorker::RegisterImmediatePersistNotification(HANDLE hthread) {
294 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
295 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
297 TImmediatePersistenceRegisterNotifInfo l_tRegisterNotifInfo = {};
299 if (sizeof(l_tRegisterNotifInfo) == FrameworkunifiedGetMsgLength(hthread)) { // LCOV_EXCL_BR_LINE 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo) // NOLINT[whitespace/line_length]
300 if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(hthread, &l_tRegisterNotifInfo, // LCOV_EXCL_BR_LINE 4: NSFW error case // NOLINT[whitespace/line_length]
301 sizeof(TImmediatePersistenceRegisterNotifInfo), eSMRRelease))) {
302 g_objmutextimerdata.WriteLock();
304 TTimerList::iterator l_itTimerList = g_mtimers.find(l_tRegisterNotifInfo.m_cnotificationname);
305 if (l_itTimerList != g_mtimers.end()) { // LCOV_EXCL_BR_LINE 6: notification can't be registered again
306 // LCOV_EXCL_START 6: notification can't be registered again
307 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Notification %s is already registered for immediate data persistence ",
308 l_tRegisterNotifInfo.m_cnotificationname);
311 // create timer corresponding to notification
312 CTimerHelper *l_pTimerHelper = new CTimerHelper();
313 if (NULL != l_pTimerHelper) { // LCOV_EXCL_BR_LINE 5: new's error case
314 l_pTimerHelper->SetTime(l_tRegisterNotifInfo.m_uidelay, 0);
315 // todo: modify SetNotifyMethod of timer NSTimer class to accept sender handle as well.
316 // This will help to have only one handle, instead of one handle per timer.
317 l_pTimerHelper->SetNotifyMethod(static_cast<UI_16>(l_pTimerHelper->GetCmdId()), FrameworkunifiedGetAppName(hthread));
319 // associate timer's timeout with the callback function.
320 FrameworkunifiedAttachCallbackToDispatcher(hthread, TIMER_QUE, l_pTimerHelper->GetCmdId(),
321 boost::bind(&CTimerHelper::OnTimeOut, l_pTimerHelper, hthread));
322 // add created timer in timers list
323 g_mtimers.insert(std::make_pair(l_tRegisterNotifInfo.m_cnotificationname, l_pTimerHelper));
324 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Notification %s is registered for immediate data persistence ",
325 l_tRegisterNotifInfo.m_cnotificationname != 0 ? l_tRegisterNotifInfo.m_cnotificationname : NULL);
329 g_objmutextimerdata.Unlock();
331 // LCOV_EXCL_START 4: NSFW error case
332 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
333 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
334 "Error getting message data for registering Immediate persistent notification, status: 0x%x", l_estatus);
338 // LCOV_EXCL_START 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo)
339 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
340 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
341 "FrameworkunifiedGetMsgLength and size of TImmediatePersistenceRegisterNotifInfo mismatched."
342 "Length received %d, buffer available: %ld ",
343 FrameworkunifiedGetMsgLength(hthread), static_cast<long int>(sizeof(TImmediatePersistenceRegisterNotifInfo))); // NOLINT (runtime/int)
347 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
351 ////////////////////////////////////////////////////////////////////////////////////////////////////
352 /// UnregisterImmediatePersistNotification
353 /// It deletes a timer corresponding to the notification.
354 ////////////////////////////////////////////////////////////////////////////////////////////////////
355 EFrameworkunifiedStatus CNorPersistenceWorker::UnregisterImmediatePersistNotification(HANDLE hthread) {
356 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
357 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
359 TImmediatePersistenceUnregisterNotifInfo l_tRegisterNotifInfo = {};
361 if (sizeof(l_tRegisterNotifInfo) == FrameworkunifiedGetMsgLength(hthread)) { // LCOV_EXCL_BR_LINE 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo) // NOLINT[whitespace/line_length]
362 if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(hthread, &l_tRegisterNotifInfo, // LCOV_EXCL_BR_LINE 4: NSFW error case // NOLINT[whitespace/line_length]
363 sizeof(TImmediatePersistenceUnregisterNotifInfo), eSMRRelease))) {
364 g_objmutextimerdata.WriteLock();
366 TTimerList::iterator l_itTimerList = g_mtimers.find(l_tRegisterNotifInfo.m_cnotificationname);
367 if (l_itTimerList != g_mtimers.end()) { // LCOV_EXCL_BR_LINE 6: notification can't be unregistered again
368 if (NULL != (l_itTimerList->second)) { // LCOV_EXCL_BR_LINE 200: l_itTimerList->second can't be null
369 EFrameworkunifiedStatus eStatus;
371 if (eFrameworkunifiedStatusOK != (eStatus = FrameworkunifiedDetachCallbackFromDispatcher(hthread, TIMER_QUE, // LCOV_EXCL_BR_LINE 4: NSFW error case // NOLINT[whitespace/line_length]
372 (l_itTimerList->second)->GetCmdId()))) {
373 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
374 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Error: FrameworkunifiedDetachCallbackFromDispatcher Failed Status:0x%x ", eStatus); // LCOV_EXCL_LINE 4: NSFW error case // NOLINT[whitespace/line_length]
376 delete l_itTimerList->second;
377 l_itTimerList->second = NULL;
379 g_mtimers.erase(l_itTimerList);
381 // LCOV_EXCL_START 6: notification can't be registered again
382 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
383 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__,
384 "Can't unregister. Notification %s is not a registered notification for immediate data persistence.",
385 l_tRegisterNotifInfo.m_cnotificationname != 0 ? l_tRegisterNotifInfo.m_cnotificationname : NULL);
389 g_objmutextimerdata.Unlock();
390 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__,
391 "Notification %s is unregistered for immediate data persistence, FrameworkunifiedGetMsgDataOfSize Error, status: 0x%x",
392 l_tRegisterNotifInfo.m_cnotificationname != 0 ? l_tRegisterNotifInfo.m_cnotificationname : NULL,
396 // LCOV_EXCL_START 200: the size of msg must be sizeof(TImmediatePersistenceUnregisterNotifInfo)
397 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
398 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
399 "FrameworkunifiedGetMsgLength and size of TImmediatePersistenceUnregisterNotifInfo mismatched."
400 "Length received %d, buffer available: %ld ",
401 FrameworkunifiedGetMsgLength(hthread), static_cast<long int>(sizeof(TImmediatePersistenceUnregisterNotifInfo))); // NOLINT (runtime/int)
405 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
409 ////////////////////////////////////////////////////////////////////////////////////////////////////
411 /// This API saves or deletes the data of NOR irrespective of delay depending on the message data
412 /// received from parent thread during shutdown.
413 ////////////////////////////////////////////////////////////////////////////////////////////////////
414 EFrameworkunifiedStatus CNorPersistenceWorker::OnShutdown(HANDLE f_hThread) {
415 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
416 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
418 UI_32 l_uiPersistCategoryFlag = 0;
420 TImmediateShutdown l_tImmShutdown = {};
422 CTimerHelper *l_pTimerHelper = NULL;
424 // iterator of list of nor notifications and its timers
425 TTimerList::iterator l_itTimerList;
427 TNorPersistenceNotifInfoHeader *l_ptImmediateNotfnHeader = NULL;
429 if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(f_hThread, &l_tImmShutdown, sizeof(l_tImmShutdown), // LCOV_EXCL_BR_LINE 4: NSFW error case // NOLINT[whitespace/line_length]
431 l_uiPersistCategoryFlag = l_tImmShutdown.f_uinotificationpersistentservicepersistcategoryflag;
433 // if quick shutdown is received then just stop the timer and dont save the data
434 if (eFrameworkunifiedQuickShutdown == l_tImmShutdown.f_eshutdowntype) {
435 for (l_itTimerList = g_mtimers.begin(); l_itTimerList != g_mtimers.end(); l_itTimerList++) {
436 l_pTimerHelper = l_itTimerList->second;
438 if (NULL != l_pTimerHelper && l_pTimerHelper->IsRunning()) {
440 l_pTimerHelper->Stop();
443 } else { // stop the timer and save the data
444 for (l_itTimerList = g_mtimers.begin(); l_itTimerList != g_mtimers.end(); l_itTimerList++) {
445 l_pTimerHelper = l_itTimerList->second;
447 if (NULL != l_pTimerHelper && l_pTimerHelper->IsRunning()) {
449 l_pTimerHelper->Stop();
451 l_ptImmediateNotfnHeader = static_cast<TNorPersistenceNotifInfoHeader *>
452 (static_cast<PVOID>(l_pTimerHelper->m_pui8HeaderAndData));
454 if (NULL != l_ptImmediateNotfnHeader) { // LCOV_EXCL_BR_LINE 200: l_ptImmediateNotfnHeader can't be null
455 if (eFrameworkunifiedUserData != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag) &&
456 eFrameworkunifiedFactoryData != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag) &&
457 eFrameworkunifiedFactoryCustomerData != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag) &&
458 eFrameworkunifiedDealerData != (l_ptImmediateNotfnHeader->m_epersistcategory & l_uiPersistCategoryFlag)) {
459 // save the new data to persistent memory
460 l_pTimerHelper->OnTimeOut(f_hThread);
463 // LCOV_EXCL_START 200: l_ptImmediateNotfnHeader can't be null
464 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
465 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Immediate notification data header is NULL");
466 l_estatus = eFrameworkunifiedStatusFail;
473 // LCOV_EXCL_START 4: NSFW error case
474 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
475 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedGetMsgDataOfSize failed for protocol NOR_PERSISTENCE_ONSHUTDOWN, status : %d",
480 if (eFrameworkunifiedStatusOK != (l_estatus = FrameworkunifiedSendParent(f_hThread, NOR_PERSISTENCE_ONSHUTDOWN_ACK, // LCOV_EXCL_BR_LINE 4: NSFW error case // NOLINT[whitespace/line_length]
481 sizeof(l_uiPersistCategoryFlag), &l_uiPersistCategoryFlag))) {
482 // LCOV_EXCL_START 4: NSFW error case
483 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
484 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedSendParent failed for protocol NOR_PERSISTENCE_ONSHUTDOWN_ACK, status : %d",
489 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
493 ////////////////////////////////////////////////////////////////////////////////////////////////////
495 /// This callback is called when category of immediate persistence is changed
496 ////////////////////////////////////////////////////////////////////////////////////////////////////
497 EFrameworkunifiedStatus CNorPersistenceWorker::OnCategoryChange(HANDLE hthread) {
498 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
499 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
501 if (NULL != hthread) { // LCOV_EXCL_BR_LINE 4: NSFW error case
502 UI_32 l_ui32ReceivedDataLength = FrameworkunifiedGetMsgLength(hthread);
504 if (l_ui32ReceivedDataLength >= sizeof(TImmediatePersistenceChangeCategory)) { // LCOV_EXCL_BR_LINE 200: l_ui32ReceivedDataLength is bigger than sizeof(TImmediatePersistenceChangeCategory) // NOLINT[whitespace/line_length]
505 UI_8 *l_pui32ReceivedData = new(std::nothrow) UI_8[l_ui32ReceivedDataLength];
507 if (NULL != l_pui32ReceivedData) { // LCOV_EXCL_BR_LINE 5: new's error case
508 std::memset(l_pui32ReceivedData, 0, l_ui32ReceivedDataLength);
509 if (eFrameworkunifiedStatusOK == (l_estatus = FrameworkunifiedGetMsgDataOfSize(hthread, l_pui32ReceivedData, l_ui32ReceivedDataLength, // LCOV_EXCL_BR_LINE 4: NSFW error case // NOLINT[whitespace/line_length]
511 TImmediatePersistenceChangeCategory *l_pChangePersistentCategory =
512 static_cast<TImmediatePersistenceChangeCategory *>(static_cast<PVOID>(l_pui32ReceivedData));
513 PUI_8 l_pui8Data = l_pui32ReceivedData + sizeof(TImmediatePersistenceChangeCategory);
515 TTimerList::iterator l_itTimerList;
517 g_objmutextimerdata.WriteLock();
518 // find the corresponding timer object in the list of timers
519 l_itTimerList = g_mtimers.find(l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname);
520 if (g_mtimers.end() != l_itTimerList) { // LCOV_EXCL_BR_LINE 6: notification must be in list
521 CTimerHelper *l_pTimerHelper = l_itTimerList->second;
523 if (NULL != l_pTimerHelper && l_pTimerHelper->IsRunning()) {
524 TNorPersistenceNotifInfoHeader *l_ptImmediateNotfnHeader =
525 static_cast<TNorPersistenceNotifInfoHeader *>(static_cast<PVOID>(l_pTimerHelper->m_pui8HeaderAndData));
527 if (NULL != l_ptImmediateNotfnHeader) { // LCOV_EXCL_BR_LINE 200: l_ptImmediateNotfnHeader can't be null
528 FRAMEWORKUNIFIEDLOG(ZONE_INFO, __FUNCTION__, "Changing category from %d to %d for notfn %s in dataHdr",
529 l_ptImmediateNotfnHeader->m_epersistcategory,
530 l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory,
531 l_ptImmediateNotfnHeader->m_cnotificationname);
533 l_ptImmediateNotfnHeader->m_epersistcategory =
534 l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory;
538 EFrameworkunifiedPersistCategory l_eOldPersistCategory = l_pChangePersistentCategory->m_eoldpersistcategory;
540 FRAMEWORKUNIFIEDLOG(ZONE_NPP_INFO, __FUNCTION__, "Changing persist category of %s from %d to %d",
541 l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname,
542 l_eOldPersistCategory,
543 l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory);
545 // write data to emmc
546 l_estatus = SynchronousWritePersistentData(
547 l_pChangePersistentCategory->m_tnornotifInfoheader.m_cpublishername,
548 l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname,
549 static_cast<PVOID>(l_pui8Data),
550 l_pChangePersistentCategory->m_tnornotifInfoheader.m_uimsgsize,
551 l_pChangePersistentCategory->m_tnornotifInfoheader.m_uidelay,
552 l_pChangePersistentCategory->m_tnornotifInfoheader.m_uimaxmsglength,
553 l_pChangePersistentCategory->m_tnornotifInfoheader.m_epersistcategory);
555 // Create the old file path string to be removed
556 std::string l_cPath = IMMEDIATE_PERSISTENCE_STORAGE_V2;
557 std::string l_cTempPath = l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname;
558 size_t l_uiTempPathSize = 0;
560 // replace all '/' by '_'
561 l_uiTempPathSize = l_cTempPath.find_first_of("/");
562 while (std::string::npos != l_uiTempPathSize) {
563 l_cTempPath[l_uiTempPathSize] = '_';
564 l_uiTempPathSize = l_cTempPath.find_first_of("/", l_uiTempPathSize + 1);
567 switch (l_eOldPersistCategory) {
568 case eFrameworkunifiedFactoryData:
569 l_cPath.append(FACTORYDATADIR);
571 case eFrameworkunifiedFactoryCustomerData:
572 l_cPath.append(FACTORYCUSTOMERDATADIR);
574 case eFrameworkunifiedDealerData:
575 l_cPath.append(DEALERDATADIR);
577 case eFrameworkunifiedUserData:
579 l_cPath.append(USERDATADIR);
580 l_cPath.append(ALLUSERAPPDATADIR);
585 l_cPath.append(IMMEDIATEDATADIR);
586 l_cPath.append(l_cTempPath);
588 l_cPath.append(l_pChangePersistentCategory->m_tnornotifInfoheader.m_cpublishername);
590 if (0 != unlink(l_cPath.c_str())) {
591 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Error deleting file %s, errno=%d", l_cPath.c_str(), errno);
594 // LCOV_EXCL_START 6: notification must be in list
595 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
596 l_estatus = eFrameworkunifiedStatusFail;
597 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Can't update persistent category, notfn %s not found in g_mtimers map",
598 l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname != 0 ?
599 l_pChangePersistentCategory->m_tnornotifInfoheader.m_cnotificationname : NULL);
602 g_objmutextimerdata.Unlock();
604 // LCOV_EXCL_START 4: NSFW error case
605 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
606 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "FrameworkunifiedGetMsgDataOfSize failed while retrieving"
607 "immediate persistence notfn data. Status:0x%x ", l_estatus);
611 delete[] l_pui32ReceivedData;
612 l_pui32ReceivedData = NULL;
614 // LCOV_EXCL_START 5: new's error case
615 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
616 l_estatus = eFrameworkunifiedStatusNullPointer;
617 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Unable to allocate data. Can't persist, errno=%d", errno);
621 // LCOV_EXCL_START 200: l_ui32ReceivedDataLength is bigger than sizeof(TImmediatePersistenceChangeCategory)
622 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
623 l_estatus = eFrameworkunifiedStatusInvldBuf;
624 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Invalid data length received %d. Can't persist.", l_ui32ReceivedDataLength);
628 // LCOV_EXCL_START 4: NSFW error case
629 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
630 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Invalid param, hthread is NULL");
631 l_estatus = eFrameworkunifiedStatusInvldParam;
635 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
639 /////////////////////////////
640 /// Class: CTimerHelper
641 /////////////////////////////
643 ////////////////////////////////////////////////////////////////////////////////////////////////////
645 /// Constructor of CTimerHelper class
646 ////////////////////////////////////////////////////////////////////////////////////////////////////
647 CTimerHelper::CTimerHelper() {
648 static UI_32 l_uiTimerCounter = PROTOCOL_FRAMEWORKUNIFIED_BASE_CMD;
650 m_uiCmdId = l_uiTimerCounter;
651 m_pui8HeaderAndData = NULL;
654 ////////////////////////////////////////////////////////////////////////////////////////////////////
656 /// Destructor of CTimerHelper class
657 ////////////////////////////////////////////////////////////////////////////////////////////////////
658 CTimerHelper::~CTimerHelper() {
659 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
661 if (NULL != m_pui8HeaderAndData) {
662 delete[] m_pui8HeaderAndData;
663 m_pui8HeaderAndData = NULL;
666 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");
669 ////////////////////////////////////////////////////////////////////////////////////////////////////
671 /// Returns id for timer
672 ////////////////////////////////////////////////////////////////////////////////////////////////////
673 UI_32 CTimerHelper::GetCmdId() {
677 ////////////////////////////////////////////////////////////////////////////////////////////////////
679 /// This function writes the corresponding data in NOR when timer expires.
680 ////////////////////////////////////////////////////////////////////////////////////////////////////
681 EFrameworkunifiedStatus CTimerHelper::OnTimeOut(HANDLE hthread) {
682 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "+");
683 EFrameworkunifiedStatus l_estatus = eFrameworkunifiedStatusOK;
685 g_objmutextimerdata.ReadLock();
686 if (NULL != m_pui8HeaderAndData) { // LCOV_EXCL_BR_LINE 200: m_pui8HeaderAndData can't be null
687 TNorPersistenceNotifInfoHeader *l_ptImmediateNotfnHeader =
688 static_cast<TNorPersistenceNotifInfoHeader *>(static_cast<PVOID>(m_pui8HeaderAndData));
689 PUI_8 l_pui8Data = m_pui8HeaderAndData + sizeof(TNorPersistenceNotifInfoHeader);
690 HANDLE l_hReceiverMq = McOpenSender(l_ptImmediateNotfnHeader->m_cpublishername);
692 // write data to emmc
693 l_estatus = SynchronousWritePersistentData(l_ptImmediateNotfnHeader->m_cpublishername,
694 l_ptImmediateNotfnHeader->m_cnotificationname,
695 static_cast<PVOID>(l_pui8Data),
696 l_ptImmediateNotfnHeader->m_uimsgsize,
697 l_ptImmediateNotfnHeader->m_uidelay,
698 l_ptImmediateNotfnHeader->m_uimaxmsglength,
699 l_ptImmediateNotfnHeader->m_epersistcategory);
701 // update corresponding application about data written status.
702 if (NULL != l_hReceiverMq) { // LCOV_EXCL_BR_LINE 5: NSFW error case
703 NC_ImmediateWriteAck l_tWriteAck = {};
704 std::strncpy(l_tWriteAck.notificationName, l_ptImmediateNotfnHeader->m_cnotificationname,
705 sizeof(l_tWriteAck.notificationName) - 1);
706 l_tWriteAck.eStatus = l_estatus;
708 if (eFrameworkunifiedStatusOK != (l_estatus = McSend(l_hReceiverMq, AppName, NPS_IMMEDIATE_WRITE_ACK, sizeof(l_tWriteAck), // LCOV_EXCL_BR_LINE 4: NSFW error case. // NOLINT[whitespace/line_length]
710 // LCOV_EXCL_START 4: NSFW error case.
711 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
712 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
713 "Error Sending NPS_IMMEDIATE_WRITE_ACK to %s for %s, Status: %d",
714 l_ptImmediateNotfnHeader->m_cpublishername != 0 ? l_ptImmediateNotfnHeader->m_cpublishername : NULL,
715 l_ptImmediateNotfnHeader->m_cnotificationname != 0 ?
716 l_ptImmediateNotfnHeader->m_cnotificationname : NULL,
720 McClose(l_hReceiverMq);
721 l_hReceiverMq = NULL;
723 // LCOV_EXCL_START 5: NSFW error case
724 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
725 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__,
726 "Error creating sender handle for service %s, Notification name %s Write Status: %d",
727 l_ptImmediateNotfnHeader->m_cpublishername != 0 ? l_ptImmediateNotfnHeader->m_cpublishername : NULL,
728 l_ptImmediateNotfnHeader->m_cnotificationname != 0 ?
729 l_ptImmediateNotfnHeader->m_cnotificationname : NULL,
731 l_estatus = eFrameworkunifiedStatusNullPointer;
735 // LCOV_EXCL_START 200: m_pui8HeaderAndData can't be null
736 FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "Not writing immediate persistence data. Data is NULL");
737 l_estatus = eFrameworkunifiedStatusNullPointer;
738 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
741 g_objmutextimerdata.Unlock();
743 FRAMEWORKUNIFIEDLOG(ZONE_FUNC, __FUNCTION__, "-");