PFW: Add resync mechanism if a subsystem needs resync

BZ: 76267

In the case of a hw subsystems reset, it's possible that its
parameter managed by the PFW may not be aligned with the PFW
blackboard.
A re-synchronization mechanism is implemented to ensure that the
subsystem is re-synchronized on the next configurations application.

Change-Id: I032150955d25a7020cf494e69456897b4c157916
Signed-off-by: Guillaume Denneulin <guillaume.denneulin@intel.com>
Reviewed-on: http://android.intel.com:8080/83015
Reviewed-by: Rocard, KevinX <kevinx.rocard@intel.com>
Reviewed-by: Centelles, Sylvain <sylvain.centelles@intel.com>
Tested-by: Dixon, CharlesX <charlesx.dixon@intel.com>
Reviewed-by: cactus <cactus@intel.com>
Tested-by: cactus <cactus@intel.com>
diff --git a/parameter/ConfigurableDomain.cpp b/parameter/ConfigurableDomain.cpp
index 7d713a1..6d1c19c 100644
--- a/parameter/ConfigurableDomain.cpp
+++ b/parameter/ConfigurableDomain.cpp
@@ -438,8 +438,15 @@
 }
 
 // Configuration application if required
-void CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce) const
+void CConfigurableDomain::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet* pSyncerSet, bool bForce) const
 {
+    // Apply configuration only if the blackboard will
+    // be synchronized either now or by syncerSet.
+    if(!pSyncerSet ^ _bSequenceAware) {
+        // The configuration can not be syncronised
+        return;
+    }
+
     if (bForce) {
         // Force a configuration restore by forgetting about last applied configuration
         _pLastAppliedConfiguration = NULL;
@@ -451,19 +458,24 @@
         // Check not the last one before applying
         if (!_pLastAppliedConfiguration || _pLastAppliedConfiguration != pApplicableDomainConfiguration) {
 
-            log_info("Applying configuration \"%s\" from domain \"%s\"", pApplicableDomainConfiguration->getName().c_str(), getName().c_str());
+            log_info("Applying configuration \"%s\" from domain \"%s\"",
+                     pApplicableDomainConfiguration->getName().c_str(),
+                     getName().c_str());
+
+            // Check if we need to synchronize during restore
+            bool bSync = !pSyncerSet && _bSequenceAware;
 
             // Do the restore
-            pApplicableDomainConfiguration->restore(pParameterBlackboard, _bSequenceAware, NULL);
+            pApplicableDomainConfiguration->restore(pParameterBlackboard, bSync, NULL);
 
             // Record last applied configuration
             _pLastAppliedConfiguration = pApplicableDomainConfiguration;
 
-            // Check we did not already sync the changes
-            if (!_bSequenceAware) {
+            // Check we need to provide syncer set to caller
+            if (pSyncerSet && !_bSequenceAware) {
 
                 // Since we applied changes, add our own sync set to the given one
-                syncerSet += _syncerSet;
+                *pSyncerSet += _syncerSet;
             }
         }
     }
diff --git a/parameter/ConfigurableDomain.h b/parameter/ConfigurableDomain.h
index 46d33d7..ad0cc33 100644
--- a/parameter/ConfigurableDomain.h
+++ b/parameter/ConfigurableDomain.h
@@ -80,7 +80,7 @@
     void validate(const CParameterBlackboard* pMainBlackboard);
 
     // Configuration application if required
-    void apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForced) const;
+    void apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet* pSyncerSet, bool bForced) const;
 
     // Return applicable configuration validity for given configurable element
     bool isApplicableConfigurationValid(const CConfigurableElement* pConfigurableElement) const;
diff --git a/parameter/ConfigurableDomains.cpp b/parameter/ConfigurableDomains.cpp
index a1bfb3c..fcfeb4d 100644
--- a/parameter/ConfigurableDomains.cpp
+++ b/parameter/ConfigurableDomains.cpp
@@ -61,17 +61,13 @@
 }
 
 // Configuration application if required
-void CConfigurableDomains::apply(CParameterBlackboard* pParameterBlackboard, bool bForce) const
+void CConfigurableDomains::apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce) const
 {
-
    CAutoLog autoLog(this, "Applying configurations");
 
-    // Syncer set
-    CSyncerSet syncerSet;
+    /// Delegate to domains
 
-    // Delegate to domains
-
-    // Start with sequence unaware domains
+    // Start with domains that can be synchronized all at once (with passed syncer set)
     uint32_t uiChild;
     uint32_t uiNbConfigurableDomains = getNbChildren();
 
@@ -79,23 +75,19 @@
 
         const CConfigurableDomain* pChildConfigurableDomain = static_cast<const CConfigurableDomain*>(getChild(uiChild));
 
-        if (!pChildConfigurableDomain->getSequenceAwareness()) {
-            // Apply sequence unaware domain
-            pChildConfigurableDomain->apply(pParameterBlackboard, syncerSet, bForce);
-        }
+        // Apply and collect syncers when relevant
+        pChildConfigurableDomain->apply(pParameterBlackboard, &syncerSet, bForce);
     }
-    // Synchronize sequence unaware domains
+    // Synchronize those collected syncers
     syncerSet.sync(*pParameterBlackboard, false, NULL);
 
-    // Then deal with sequence aware domains
+    // Then deal with domains that need to synchronize along apply
     for (uiChild = 0; uiChild < uiNbConfigurableDomains; uiChild++) {
 
         const CConfigurableDomain* pChildConfigurableDomain = static_cast<const CConfigurableDomain*>(getChild(uiChild));
 
-        if (pChildConfigurableDomain->getSequenceAwareness()) {
-            // Apply sequence aware domain
-            pChildConfigurableDomain->apply(pParameterBlackboard, syncerSet, bForce);
-        }
+        // Apply and synchronize when relevant
+        pChildConfigurableDomain->apply(pParameterBlackboard, NULL, bForce);
     }
 }
 
diff --git a/parameter/ConfigurableDomains.h b/parameter/ConfigurableDomains.h
index 10a00ed..af98c52 100644
--- a/parameter/ConfigurableDomains.h
+++ b/parameter/ConfigurableDomains.h
@@ -83,7 +83,7 @@
     void validate(const CParameterBlackboard* pMainBlackboard);
 
     // Configuration application if required
-    void apply(CParameterBlackboard* pParameterBlackboard, bool bForce) const;
+    void apply(CParameterBlackboard* pParameterBlackboard, CSyncerSet& syncerSet, bool bForce) const;
 
     // Class kind
     virtual string getKind() const;
diff --git a/parameter/IntegerParameterType.cpp b/parameter/IntegerParameterType.cpp
index ea08e43..3c3a626 100644
--- a/parameter/IntegerParameterType.cpp
+++ b/parameter/IntegerParameterType.cpp
@@ -227,6 +227,8 @@
 
 bool CIntegerParameterType::fromBlackboard(uint32_t& uiUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
 {
+    (void)parameterAccessContext;
+
     // Do assign
     uiUserValue = uiValue;
 
@@ -250,6 +252,8 @@
 
 bool CIntegerParameterType::fromBlackboard(int32_t& iUserValue, uint32_t uiValue, CParameterAccessContext& parameterAccessContext) const
 {
+    (void)parameterAccessContext;
+
     int32_t iValue = uiValue;
 
     // Sign extend
diff --git a/parameter/ParameterMgr.cpp b/parameter/ParameterMgr.cpp
index 5244199..4116dbe 100644
--- a/parameter/ParameterMgr.cpp
+++ b/parameter/ParameterMgr.cpp
@@ -355,9 +355,8 @@
     // We need to ensure all domains are valid
     pConfigurableDomains->validate(_pMainParameterBlackboard);
 
-    // Ensure application of currently selected configurations
-    // Force-apply configurations
-    pConfigurableDomains->apply(_pMainParameterBlackboard, true);
+    // At initialization, check subsystems that need resync
+    doApplyConfigurations(true);
 
     // Start remote processor server if appropriate
     return handleRemoteProcessingInterface(strError);
@@ -559,7 +558,7 @@
     return getSelectionCriteria()->getSelectionCriterion(strName);
 }
 
-// Selection criteria changed event
+// Configuration application
 void CParameterMgr::applyConfigurations()
 {
     CAutoLog autoLog(this, "Configuration application request");
@@ -570,11 +569,7 @@
     if (!_bTuningModeIsOn) {
 
         // Apply configuration(s)
-        getConfigurableDomains()->apply(_pMainParameterBlackboard, false);
-
-        // Reset the modified status of the current criteria to indicate that a new configuration has been applied
-        getSelectionCriteria()->resetModifiedStatus();
-
+        doApplyConfigurations(false);
     } else {
 
         log_warning("Configurations were not applied because the TuningMode is on");
@@ -1335,7 +1330,7 @@
 
         // Ensure application of currently selected configurations
         // Force-apply configurations
-        getConfigurableDomains()->apply(_pMainParameterBlackboard, true);
+        doApplyConfigurations(true);
 
         // Turn auto sync back on
         _bAutoSyncOn = true;
@@ -1908,8 +1903,22 @@
     return static_cast<const CConfigurableDomains*>(getChild(EConfigurableDomains));
 }
 
-/// GUI commands functions
+// Apply configurations
+void CParameterMgr::doApplyConfigurations(bool bForce)
+{
+    CSyncerSet syncerSet;
 
+    // Check subsystems that need resync
+    getSystemClass()->checkForSubsystemsToResync(syncerSet);
+
+    // Ensure application of currently selected configurations
+    getConfigurableDomains()->apply(_pMainParameterBlackboard, syncerSet, bForce);
+
+    // Reset the modified status of the current criteria to indicate that a new configuration has been applied
+    getSelectionCriteria()->resetModifiedStatus();
+}
+
+/// GUI commands functions
 bool CParameterMgr::getDomainsXMLString(string& strResult, bool bWithSettings)
 {
 
diff --git a/parameter/ParameterMgr.h b/parameter/ParameterMgr.h
index 7bbd2a2..44f3d41 100644
--- a/parameter/ParameterMgr.h
+++ b/parameter/ParameterMgr.h
@@ -299,6 +299,9 @@
     const CConfigurableDomains* getConstConfigurableDomains();
     const CConfigurableDomains* getConstConfigurableDomains() const;
 
+    // Apply configurations
+    void doApplyConfigurations(bool bForce);
+
     // Dynamic object creation libraries feeding
     void feedElementLibraries();
 
diff --git a/parameter/Subsystem.cpp b/parameter/Subsystem.cpp
index 3882c93..a9115c8 100644
--- a/parameter/Subsystem.cpp
+++ b/parameter/Subsystem.cpp
@@ -74,6 +74,20 @@
     return _bBigEndian;
 }
 
+// Susbsystem sanity
+bool CSubsystem::isAlive() const
+{
+    return true;
+}
+
+// Resynchronization after subsystem restart needed
+bool CSubsystem::needResync(bool bClear)
+{
+    (void)bClear;
+
+    return false;
+}
+
 // From IXmlSink
 bool CSubsystem::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
 {
diff --git a/parameter/Subsystem.h b/parameter/Subsystem.h
index 359690c..0b808ad 100644
--- a/parameter/Subsystem.h
+++ b/parameter/Subsystem.h
@@ -49,6 +49,12 @@
     // Susbsystem Endianness
     bool isBigEndian() const;
 
+    // Susbsystem sanity
+    virtual bool isAlive() const;
+
+    // Resynchronization after subsystem restart needed
+    virtual bool needResync(bool bClear);
+
     // XML configuration settings parsing
     virtual bool serializeXmlSettings(CXmlElement& xmlConfigurationSettingsElementContent, CConfigurationAccessContext& configurationAccessContext) const;
 
diff --git a/parameter/SubsystemObject.cpp b/parameter/SubsystemObject.cpp
index 8c5c5e4..15bba6c 100644
--- a/parameter/SubsystemObject.cpp
+++ b/parameter/SubsystemObject.cpp
@@ -23,8 +23,10 @@
  * UPDATED: 2011-07-27
  */
 #include "SubsystemObject.h"
+#include "Subsystem.h"
 #include "InstanceConfigurableElement.h"
 #include "ParameterBlackboard.h"
+#include "ParameterAccessContext.h"
 #include "MappingContext.h"
 #include <assert.h>
 #include <stdlib.h>
@@ -74,6 +76,18 @@
     return ostr.str();
 }
 
+// Default back synchronization
+void CSubsystemObject::setDefaultValues(CParameterBlackboard& parameterBlackboard) const
+{
+    string strError;
+
+    // Create access context
+    CParameterAccessContext parameterAccessContext(strError, &parameterBlackboard, false);
+
+    // Just implement back synchronization with default values
+    _pInstanceConfigurableElement->setDefaultValues(parameterAccessContext);
+}
+
 // Synchronization
 bool CSubsystemObject::sync(CParameterBlackboard& parameterBlackboard, bool bBack, string& strError)
 {
@@ -86,29 +100,34 @@
     return true;
 #endif
 
-    // Synchronize to/from HW
-    if (bBack) {
+    // Retrieve subsystem
+    const CSubsystem* pSubsystem = _pInstanceConfigurableElement->getBelongingSubsystem();
 
-        // Read from HW
-        if (!accessHW(true, strError)) {
+    // Get it's health insdicator
+    bool bIsSubsystemAlive = pSubsystem->isAlive();
 
-            strError = "Unable to back synchronize configurable element " + _pInstanceConfigurableElement->getPath() + ": " + strError;
-            log_warning(strError);
+    // Check subsystem health
+    if (!bIsSubsystemAlive) {
 
-            return false;
-        }
-
-    } else {
-
-        // Send to HW
-        if (!accessHW(false, strError)) {
-
-            strError = "Unable to synchronize configurable element " + _pInstanceConfigurableElement->getPath() + ": " + strError;
-            log_warning(strError);
-
-            return false;
-        }
+        strError = "Susbsystem not alive";
     }
+
+    // Synchronize to/from HW
+    if (!bIsSubsystemAlive || !accessHW(bBack, strError)) {
+
+        strError = string("Unable to ") + (bBack ? "back" : "forward") + " synchronize configurable element " +
+                _pInstanceConfigurableElement->getPath() + ": " + strError;
+
+        log_warning(strError);
+
+        // Fall back to parameter default initialization
+        if (bBack) {
+
+           setDefaultValues(parameterBlackboard);
+        }
+        return false;
+    }
+
     return true;
 }
 
diff --git a/parameter/SubsystemObject.h b/parameter/SubsystemObject.h
index 6cbfd76..9ba7546 100644
--- a/parameter/SubsystemObject.h
+++ b/parameter/SubsystemObject.h
@@ -65,6 +65,10 @@
     // from ISyncer
     virtual bool sync(CParameterBlackboard& parameterBlackboard, bool bBack, string& strError);
 
+    // Default back synchronization
+    void setDefaultValues(CParameterBlackboard& parameterBlackboard) const;
+
+    // Prevent unsupported operators
     CSubsystemObject(const CSubsystemObject&);
 
     // Define affection operator
diff --git a/parameter/SystemClass.cpp b/parameter/SystemClass.cpp
index dbce345..bf98cb1 100644
--- a/parameter/SystemClass.cpp
+++ b/parameter/SystemClass.cpp
@@ -232,6 +232,26 @@
     return _pSubsystemLibrary;
 }
 
+// Fill syncer-set with syncers from subsytems that need resync
+void CSystemClass::checkForSubsystemsToResync(CSyncerSet& syncerSet)
+{
+    uint32_t uiNbChildren = getNbChildren();
+    uint32_t uiChild;
+
+    for (uiChild = 0; uiChild < uiNbChildren; uiChild++) {
+
+        CSubsystem* pSubsystem = static_cast<CSubsystem*>(getChild(uiChild));
+
+        // Collect and consume the need for a resync
+        if (pSubsystem->needResync(true)) {
+
+            log_info("Resynchronizing subsystem: %s", pSubsystem->getName().c_str());
+            // get all subsystem syncers
+            pSubsystem->fillSyncerSet(syncerSet);
+        }
+    }
+}
+
 bool CSystemClass::init(string& strError)
 {
     return base::init(strError);
diff --git a/parameter/SystemClass.h b/parameter/SystemClass.h
index 5cb86e4..a522a33 100644
--- a/parameter/SystemClass.h
+++ b/parameter/SystemClass.h
@@ -41,6 +41,9 @@
     // Subsystem factory
     const CSubsystemLibrary* getSubsystemLibrary() const;
 
+    // Fill syncer-set with syncers from subsytems that need resync
+    void checkForSubsystemsToResync(CSyncerSet& syncerSet);
+
     // base
     virtual bool init(string& strError);
     virtual string getKind() const;