PFW: Enhance subsytem libraries load mechanism

BZ: 24093

If a subsystem library depends on another one, the libraries have to be loaded
in a predefined order.

the previous recovery mechanism on PFW was: When a subsystem library does not
load because of a missing dependency, it tries to load all the other subsystems
before trying one more time to load the failing library.

Unfortunately, Android linker does not allow several try when loading a
library.

In consequence, this patch implements a new mechanism to load its subsystem
libraries.
For this new mechanism, the PFW will load the subsystem libraries in the order
they are disposed in the file ParameterFrameworkConfiguration.xml

Change-Id: I39b97e33c77a6b4392c3813cd3d780e10e3b60f8
Signed-off-by: Guillaume Denneulin <guillaumex.denneulin@intel.com>
Reviewed-on: http://android.intel.com:8080/35903
Reviewed-by: Barthes, FabienX <fabienx.barthes@intel.com>
Tested-by: Barthes, FabienX <fabienx.barthes@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
diff --git a/Schemas/ParameterFrameworkConfiguration.xsd b/Schemas/ParameterFrameworkConfiguration.xsd
index d84d108..8ece70d 100644
--- a/Schemas/ParameterFrameworkConfiguration.xsd
+++ b/Schemas/ParameterFrameworkConfiguration.xsd
@@ -3,11 +3,20 @@
 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     <xs:complexType name="ConfigurationFilePath">
         <xs:attribute name="Path" type="xs:anyURI" use="required"/>
-    </xs:complexType>
-	<xs:element name="SubsystemPluginFolders">
+    </xs:complexType> 
+    <xs:complexType name="PluginFile">
+        <xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>
+    </xs:complexType> 
+    <xs:complexType name="PluginLocation">
+            <xs:sequence>
+                <xs:element name="Plugin" type="PluginFile" maxOccurs="unbounded" minOccurs="0"/>
+            </xs:sequence>
+            <xs:attribute name="Folder" type="xs:anyURI" use="required"/>     
+    </xs:complexType> 
+    <xs:element name="SubsystemPlugins">
         <xs:complexType>
             <xs:sequence>
-                <xs:element name="PluginFolderLocation" type="ConfigurationFilePath" maxOccurs="unbounded"/>
+                <xs:element name="Location" type="PluginLocation" maxOccurs="unbounded" minOccurs="0"/>
             </xs:sequence>
         </xs:complexType>
     </xs:element>
@@ -20,7 +29,7 @@
     <xs:element name="ParameterFrameworkConfiguration">
         <xs:complexType>
             <xs:sequence>
-            	<xs:element ref="SubsystemPluginFolders"/>
+                <xs:element ref="SubsystemPlugins" />
             	<xs:element name="StructureDescriptionFileLocation" type="ConfigurationFilePath"/>
             	<xs:element name="SettingsConfiguration" type="SettingsConfigurationType" minOccurs="0"/>
             </xs:sequence>
diff --git a/parameter/Android.mk b/parameter/Android.mk
index 90e9ada..a27ae4c 100644
--- a/parameter/Android.mk
+++ b/parameter/Android.mk
@@ -50,7 +50,9 @@
         XmlFileIncluderElement.cpp \
         ParameterFrameworkConfiguration.cpp \
         FrameworkConfigurationGroup.cpp \
+        SubsystemPlugins.cpp \
         FrameworkConfigurationLocation.cpp \
+        PluginLocation.cpp \
         KindElement.cpp \
         ElementLibrarySet.cpp \
         ErrorContext.cpp \
diff --git a/parameter/ParameterMgr.cpp b/parameter/ParameterMgr.cpp
index 6ef37bb..3b6447a 100644
--- a/parameter/ParameterMgr.cpp
+++ b/parameter/ParameterMgr.cpp
@@ -54,6 +54,8 @@
 #include "XmlFileIncluderElement.h"
 #include "ParameterFrameworkConfiguration.h"
 #include "FrameworkConfigurationGroup.h"
+#include "PluginLocation.h"
+#include "SubsystemPlugins.h"
 #include "FrameworkConfigurationLocation.h"
 #include "ConfigurableDomains.h"
 #include "ConfigurableDomain.h"
@@ -182,6 +184,7 @@
     _pMainParameterBlackboard(new CParameterBlackboard),
     _pElementLibrarySet(new CElementLibrarySet),
     _strXmlConfigurationFilePath(strConfigurationFilePath),
+    _pSubsystemPlugins(NULL),
     _uiStructureChecksum(0),
     _pRemoteProcessorServer(NULL),
     _uiMaxCommandUsageLength(0),
@@ -307,7 +310,7 @@
     }
 
     // Load subsystems
-    if (!getSystemClass()->loadSubsystems(strError, _astrPluginFolderPaths)) {
+    if (!getSystemClass()->loadSubsystems(strError, _pSubsystemPlugins)) {
 
         return false;
     }
@@ -373,33 +376,15 @@
     getSystemClass()->setName(getConstFrameworkConfiguration()->getSystemClassName());
     getConfigurableDomains()->setName(getConstFrameworkConfiguration()->getSystemClassName());
 
-    // Get subsystem plugins folders element
-    const CFrameworkConfigurationGroup* pSubsystemPluginFolders = static_cast<const CFrameworkConfigurationGroup*>(getConstFrameworkConfiguration()->findChild("SubsystemPluginFolders"));
+    // Get subsystem plugins elements
+    _pSubsystemPlugins = static_cast<const CSubsystemPlugins*>(getConstFrameworkConfiguration()->findChild("SubsystemPlugins"));
 
-    if (!pSubsystemPluginFolders) {
+    if (!_pSubsystemPlugins) {
 
-        strError = "Parameter Framework Configuration: couldn't find SubsystemPluginFolders element";
+        strError = "Parameter Framework Configuration: couldn't find SubsystemPlugins element";
 
         return false;
     }
-    // Get plugin locations
-    uint32_t uiPluginFolderLocation;
-    uint32_t uiNbPluginFolderLocations = pSubsystemPluginFolders->getNbChildren();
-
-    if (!uiNbPluginFolderLocations) {
-
-        strError = "Parameter Framework Configuration: couldn't find any PluginFolderLocation element";
-
-        return false;
-    }
-
-    // Collect plugin paths
-    for (uiPluginFolderLocation = 0; uiPluginFolderLocation < uiNbPluginFolderLocations; uiPluginFolderLocation++) {
-
-        const CFrameworkConfigurationLocation* pSubsystemPluginLocation = static_cast<const CFrameworkConfigurationLocation*>(pSubsystemPluginFolders->getChild(uiPluginFolderLocation));
-
-        _astrPluginFolderPaths.push_back(pSubsystemPluginLocation->getFilePath(_strXmlConfigurationFilePath));
-    }
 
     // Log tuning availability
     log("Tuning %s", getConstFrameworkConfiguration()->isTuningAllowed() ? "allowed" : "prohibited");
@@ -1736,8 +1721,8 @@
     CElementLibrary* pFrameworkConfigurationLibrary = new CElementLibrary;
 
     pFrameworkConfigurationLibrary->addElementBuilder(new TElementBuilderTemplate<CParameterFrameworkConfiguration>("ParameterFrameworkConfiguration"));
-    pFrameworkConfigurationLibrary->addElementBuilder(new TKindElementBuilderTemplate<CFrameworkConfigurationGroup>("SubsystemPluginFolders"));
-    pFrameworkConfigurationLibrary->addElementBuilder(new TKindElementBuilderTemplate<CFrameworkConfigurationLocation>("PluginFolderLocation"));
+    pFrameworkConfigurationLibrary->addElementBuilder(new TKindElementBuilderTemplate<CSubsystemPlugins>("SubsystemPlugins"));
+    pFrameworkConfigurationLibrary->addElementBuilder(new TKindElementBuilderTemplate<CPluginLocation>("Location"));
     pFrameworkConfigurationLibrary->addElementBuilder(new TKindElementBuilderTemplate<CFrameworkConfigurationLocation>("StructureDescriptionFileLocation"));
     pFrameworkConfigurationLibrary->addElementBuilder(new TKindElementBuilderTemplate<CFrameworkConfigurationGroup>("SettingsConfiguration"));
     pFrameworkConfigurationLibrary->addElementBuilder(new TKindElementBuilderTemplate<CFrameworkConfigurationLocation>("ConfigurableDomainsFileLocation"));
diff --git a/parameter/ParameterMgr.h b/parameter/ParameterMgr.h
index da4e43f..1a5ebf2 100644
--- a/parameter/ParameterMgr.h
+++ b/parameter/ParameterMgr.h
@@ -51,6 +51,7 @@
 class IRemoteProcessorServerInterface;
 class CBackSynchronizer;
 class CParameterHandle;
+class CSubsystemPlugins;
 
 class CParameterMgr : private CElement
 {
@@ -321,7 +322,7 @@
     string _strSchemaFolderLocation; // Place where schemas stand
 
     // Subsystem plugin location
-    vector<string> _astrPluginFolderPaths;
+    const CSubsystemPlugins* _pSubsystemPlugins;
 
     // Whole system structure checksum
     uint8_t _uiStructureChecksum;
diff --git a/parameter/PluginLocation.cpp b/parameter/PluginLocation.cpp
new file mode 100644
index 0000000..0c14731
--- /dev/null
+++ b/parameter/PluginLocation.cpp
@@ -0,0 +1,70 @@
+/* <auto_header>
+ * <FILENAME>
+ * 
+ * INTEL CONFIDENTIAL
+ * Copyright © 2011 Intel 
+ * Corporation All Rights Reserved.
+ * 
+ * The source code contained or described herein and all documents related to
+ * the source code ("Material") are owned by Intel Corporation or its suppliers
+ * or licensors. Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors. The Material contains trade secrets and proprietary
+ * and confidential information of Intel or its suppliers and licensors. The
+ * Material is protected by worldwide copyright and trade secret laws and
+ * treaty provisions. No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or
+ * disclosed in any way without Intel’s prior express written permission.
+ * 
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise. Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ * 
+ *  AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
+ * CREATED: 2011-06-01
+ * UPDATED: 2011-07-27
+ * 
+ * 
+ * </auto_header>
+ */
+#include "PluginLocation.h"
+
+#define base CKindElement
+
+CPluginLocation::CPluginLocation(const string& strName, const string& strKind) : base(strName, strKind)
+{
+
+}
+
+const string& CPluginLocation::getFolder() const
+{
+    return _strFolder;
+}
+
+const list<string>& CPluginLocation::getPluginList() const
+{
+    return _pluginList;
+}
+
+bool CPluginLocation::fromXml(const CXmlElement &xmlElement, CXmlSerializingContext &serializingContext)
+{
+    (void) serializingContext;
+
+    // Retrieve folder
+    _strFolder = xmlElement.getAttributeString("Folder");
+
+    // Get Info from children
+    CXmlElement::CChildIterator childIterator(xmlElement);
+
+    CXmlElement xmlPluginElement;
+
+    while (childIterator.next(xmlPluginElement)) {
+
+        // Fill Plugin List
+        _pluginList.push_back(xmlPluginElement.getAttributeString("Name"));
+    }
+
+    // Don't dig
+    return true;
+}
diff --git a/parameter/PluginLocation.h b/parameter/PluginLocation.h
new file mode 100644
index 0000000..ceba681
--- /dev/null
+++ b/parameter/PluginLocation.h
@@ -0,0 +1,54 @@
+/* <auto_header>
+ * <FILENAME>
+ * 
+ * INTEL CONFIDENTIAL
+ * Copyright © 2011 Intel 
+ * Corporation All Rights Reserved.
+ * 
+ * The source code contained or described herein and all documents related to
+ * the source code ("Material") are owned by Intel Corporation or its suppliers
+ * or licensors. Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors. The Material contains trade secrets and proprietary
+ * and confidential information of Intel or its suppliers and licensors. The
+ * Material is protected by worldwide copyright and trade secret laws and
+ * treaty provisions. No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or
+ * disclosed in any way without Intel’s prior express written permission.
+ * 
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise. Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ * 
+ *  AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
+ * CREATED: 2011-06-01
+ * UPDATED: 2011-07-27
+ * 
+ * 
+ * </auto_header>
+ */
+#pragma once
+#include <list>
+#include "KindElement.h"
+
+class CPluginLocation : public CKindElement
+{
+
+public:
+    CPluginLocation(const string& strName, const string& strKind);
+
+    // From IXmlSink
+    virtual bool fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext);
+
+    // Folder
+    const string& getFolder() const;
+
+    // Plugin list
+    const list<string>& getPluginList() const;
+
+private:
+    string _strFolder;
+    list<string> _pluginList;
+
+};
diff --git a/parameter/SubsystemPlugins.cpp b/parameter/SubsystemPlugins.cpp
new file mode 100644
index 0000000..4a4ba53
--- /dev/null
+++ b/parameter/SubsystemPlugins.cpp
@@ -0,0 +1,43 @@
+/* <auto_header>
+ * <FILENAME>
+ * 
+ * INTEL CONFIDENTIAL
+ * Copyright © 2011 Intel 
+ * Corporation All Rights Reserved.
+ * 
+ * The source code contained or described herein and all documents related to
+ * the source code ("Material") are owned by Intel Corporation or its suppliers
+ * or licensors. Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors. The Material contains trade secrets and proprietary
+ * and confidential information of Intel or its suppliers and licensors. The
+ * Material is protected by worldwide copyright and trade secret laws and
+ * treaty provisions. No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or
+ * disclosed in any way without Intel’s prior express written permission.
+ * 
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise. Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ * 
+ *  AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
+ * CREATED: 2011-06-01
+ * UPDATED: 2011-07-27
+ * 
+ * 
+ * </auto_header>
+ */
+#include "SubsystemPlugins.h"
+
+#define base CKindElement
+
+CSubsystemPlugins::CSubsystemPlugins(const string& strName, const string& strKind) : base(strName, strKind)
+{
+}
+
+bool CSubsystemPlugins::childrenAreDynamic() const
+{
+    return true;
+}
+
diff --git a/parameter/SubsystemPlugins.h b/parameter/SubsystemPlugins.h
new file mode 100644
index 0000000..09740d3
--- /dev/null
+++ b/parameter/SubsystemPlugins.h
@@ -0,0 +1,45 @@
+/* <auto_header>
+ * <FILENAME>
+ * 
+ * INTEL CONFIDENTIAL
+ * Copyright © 2011 Intel 
+ * Corporation All Rights Reserved.
+ * 
+ * The source code contained or described herein and all documents related to
+ * the source code ("Material") are owned by Intel Corporation or its suppliers
+ * or licensors. Title to the Material remains with Intel Corporation or its
+ * suppliers and licensors. The Material contains trade secrets and proprietary
+ * and confidential information of Intel or its suppliers and licensors. The
+ * Material is protected by worldwide copyright and trade secret laws and
+ * treaty provisions. No part of the Material may be used, copied, reproduced,
+ * modified, published, uploaded, posted, transmitted, distributed, or
+ * disclosed in any way without Intel’s prior express written permission.
+ * 
+ * No license under any patent, copyright, trade secret or other intellectual
+ * property right is granted to or conferred upon you by disclosure or delivery
+ * of the Materials, either expressly, by implication, inducement, estoppel or
+ * otherwise. Any license under such intellectual property rights must be
+ * express and approved by Intel in writing.
+ * 
+ *  AUTHOR: Patrick Benavoli (patrickx.benavoli@intel.com)
+ * CREATED: 2011-06-01
+ * UPDATED: 2011-07-27
+ * 
+ * 
+ * </auto_header>
+ */
+#pragma once
+
+#include "KindElement.h"
+#include <list>
+
+class CSubsystemPlugins : public CKindElement
+{
+
+public:
+    CSubsystemPlugins(const string& strName, const string& strKind);
+
+private:
+    virtual bool childrenAreDynamic() const;
+
+};
diff --git a/parameter/SystemClass.cpp b/parameter/SystemClass.cpp
index 6409c9b..d733dbd 100644
--- a/parameter/SystemClass.cpp
+++ b/parameter/SystemClass.cpp
@@ -38,6 +38,7 @@
 #include "VirtualSubsystem.h"
 #include "NamedElementBuilderTemplate.h"
 #include <assert.h>
+#include "PluginLocation.h"
 
 #define base CConfigurableElement
 
@@ -76,22 +77,33 @@
     return "SystemClass";
 }
 
-bool CSystemClass::loadSubsystems(string& strError, const vector<string>& astrPluginFolderPaths)
+bool CSystemClass::loadSubsystems(string& strError, const CSubsystemPlugins* pSubsystemPlugins)
 {
     CAutoLog autoLlog(this, "Loading subsystem plugins");
 
     // Plugin list
     list<string> lstrPluginFiles;
 
-    uint32_t uiFolderLocation;
+    uint32_t uiPluginLocation;
 
-    for (uiFolderLocation = 0; uiFolderLocation < astrPluginFolderPaths.size(); uiFolderLocation++) {
+    for (uiPluginLocation = 0; uiPluginLocation <  pSubsystemPlugins->getNbChildren(); uiPluginLocation++) {
 
-        // Folder for current SystemClass
-        string strPluginPath = astrPluginFolderPaths[uiFolderLocation] + "/";
+        // Get Folder for current Plugin Location
+        const CPluginLocation* pPluginLocation = static_cast<const CPluginLocation*>(pSubsystemPlugins->getChild(uiPluginLocation));
 
-        // Get plugin list
-        getPluginFiles(strPluginPath, lstrPluginFiles);
+        const string& strFolder = pPluginLocation->getFolder();
+
+        // Iterator on Plugin List:
+        list<string>::const_iterator it;
+
+        const list<string>& pluginList = pPluginLocation->getPluginList();
+
+        for (it = pluginList.begin(); it != pluginList.end(); ++it) {
+
+            // Fill Plugin files list
+            lstrPluginFiles.push_back(strFolder + "/" + *it);
+        }
+
     }
     // Check at least one subsystem plugin available
     if (!lstrPluginFiles.size()) {
@@ -132,41 +144,6 @@
     return true;
 }
 
-// Subsystem plugins
-bool CSystemClass::getPluginFiles(const string& strPluginPath, list<string>& lstrPluginFiles) const
-{
-    log("Seeking subsystem plugins from folder \"%s\"", strPluginPath.c_str());
-
-    DIR *dirp;
-    struct dirent *dp;
-
-    if ((dirp = opendir(strPluginPath.c_str())) == NULL) {
-
-        return false;
-    }
-
-    const string strPluginPattern(gpcPluginPattern);
-
-    // Parse it and load plugins
-    while ((dp = readdir(dirp)) != NULL) {
-
-        string strFileName(dp->d_name);
-
-        // Check file name ends with pattern
-        size_t uiPatternPos = strFileName.rfind(strPluginPattern, -1);
-
-        if (uiPatternPos != (size_t)-1 && uiPatternPos == strFileName.size() - strPluginPattern.size()) {
-            // Found plugin
-            lstrPluginFiles.push_back(strPluginPath + strFileName);
-        }
-    }
-
-    // Close plugin folder
-    closedir(dirp);
-
-    return true;
-}
-
 // Plugin symbol computation
 string CSystemClass::getPluginSymbol(const string& strPluginPath)
 {
diff --git a/parameter/SystemClass.h b/parameter/SystemClass.h
index 512c5ec..ead5565 100644
--- a/parameter/SystemClass.h
+++ b/parameter/SystemClass.h
@@ -31,6 +31,7 @@
 #pragma once
 
 #include "ConfigurableElement.h"
+#include "SubsystemPlugins.h"
 #include <list>
 
 class CSubsystemLibrary;
@@ -42,7 +43,8 @@
     virtual ~CSystemClass();
 
     // Called from parent before actual init
-    bool loadSubsystems(string& strError, const vector<string>& astrPluginFolderPaths);
+    bool loadSubsystems(string& strError, const CSubsystemPlugins* pSubsystemPlugins);
+    // Subsystem factory
     const CSubsystemLibrary* getSubsystemLibrary() const;
 
     // base
@@ -62,7 +64,7 @@
     // Plugin loading
     bool loadPlugins(list<string>& lstrPluginFiles, string& strError);
 
-    // ref only
+    // Subsystem factory
     CSubsystemLibrary* _pSubsystemLibrary;
 };