Add fix to handle dm cmp allActive / createInfo for installed but not started bundles
diff --git a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc
index 1fa3598..cf9c08b 100644
--- a/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc
+++ b/libs/framework/gtest/src/CelixBundleContextBundlesTestSuite.cc
@@ -631,7 +631,7 @@
     EXPECT_STREQ(result, "STOPPING");
 
     result = celix_bundleState_getName(CELIX_BUNDLE_STATE_ACTIVE);
-    EXPECT_STREQ(result, "ACTIVE");
+    EXPECT_STREQ(result, "ACTIVE"); 
 
     result = celix_bundleState_getName(OSGI_FRAMEWORK_BUNDLE_UNKNOWN);
     EXPECT_STREQ(result, "UNKNOWN");
@@ -658,6 +658,40 @@
     EXPECT_STREQ(result, "UNKNOWN");
 }
 
+TEST_F(CelixBundleContextBundlesTestSuite, UsingDmFunctionsWithInstalledBundlesTest) {
+    //Given a clean framework and a fw dependency manager
+    auto* dm = celix_bundleContext_getDependencyManager(ctx);
+
+    //Then all components are active (no bundles installed yet)
+    bool allActive = celix_dependencyManager_allComponentsActive(dm);
+    EXPECT_TRUE(allActive);
+
+    //When installing a bundle
+    long bndId = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, false);
+    EXPECT_GE(bndId, 0);
+
+    //Then all compnents are still active (bundle not started and no components in bundle) 
+    allActive = celix_dependencyManager_allComponentsActive(dm);
+    EXPECT_TRUE(allActive);
+
+    //And a dm info can be received for the fw bundle
+    auto* info = celix_dependencyManager_createInfo(dm, CELIX_FRAMEWORK_BUNDLE_ID);
+    EXPECT_NE(info, nullptr);
+    celix_dependencyManager_destroyInfo(dm, info);
+
+    //But a valid dm info cannot be received for the installed bundle (not started yet)
+    info = celix_dependencyManager_createInfo(dm, bndId);
+    EXPECT_EQ(info, nullptr);
+    celix_dependencyManager_destroyInfo(dm, info); //should be safe
+
+    //And infos can be received and only contains dm info for 1 bundle (the framework bundle)
+    auto* infos = celix_dependencyManager_createInfos(dm);
+    EXPECT_NE(infos, nullptr);
+    EXPECT_EQ(1, celix_arrayList_size(infos));
+    celix_dependencyManager_destroyInfos(dm, infos);
+}
+
+
 class CelixBundleContextTempBundlesTestSuite : public ::testing::Test {
 public:
     celix_framework_t* fw = nullptr;
diff --git a/libs/framework/include/celix_dependency_manager.h b/libs/framework/include/celix_dependency_manager.h
index b8c9c33..4625fa5 100644
--- a/libs/framework/include/celix_dependency_manager.h
+++ b/libs/framework/include/celix_dependency_manager.h
@@ -31,6 +31,8 @@
 #endif
 
 /**
+ * @file celix_dependency_manager.h
+ * 
  * The `celix_dependencyManager_add`, `celix_dependencyManager_remove` and `celix_dependencyManager_removeAllComponents`
  * funcions for celix_dependency_manager_t should be called outside the Celix event thread.
  * Note that bundle activators are started and stopped outside the Celix event thread and thus these
@@ -43,7 +45,7 @@
 
 
 /**
- * Adds a DM component to the dependency manager
+ * @brief Add a DM component to the dependency manager
  *
  * After this call the components will be build and if the components can be started, they
  * will be started and the services will be registered.
@@ -56,14 +58,14 @@
 CELIX_FRAMEWORK_EXPORT celix_status_t celix_dependencyManager_add(celix_dependency_manager_t *manager, celix_dm_component_t *component);
 
 /**
- * Same as celix_dependencyManager_add, but this call will not wait until all service registrations and
+ * @brief Same as celix_dependencyManager_add, but this call will not wait until all service registrations and
  * tracker are registered/opened on the Celix event thread.
  * Can be called on the Celix event thread.
  */
 CELIX_FRAMEWORK_EXPORT celix_status_t celix_dependencyManager_addAsync(celix_dependency_manager_t *manager, celix_dm_component_t *component);
 
 /**
- * Removes a DM component from the dependency manager and destroys it
+ * @brief Remove a DM component from the dependency manager and destroys it
  *
  * After this call - and if the component was found - the component will be destroyed and if the component was started,
  * the component will have been stopped and de-initialized.
@@ -73,7 +75,7 @@
 CELIX_FRAMEWORK_EXPORT celix_status_t celix_dependencyManager_remove(celix_dependency_manager_t *manager, celix_dm_component_t *component);
 
 /**
- * Same as celix_dependencyManager_remove, but this call will not wait until component is deactivated.
+ * @brief Same as celix_dependencyManager_remove, but this call will not wait until component is deactivated.
  * Can be called on the Celix event thread.
  *
  * The doneCallback will be called (if not NULL) with doneData as argument when the component is removed
@@ -87,14 +89,14 @@
         void (*doneCallback)(void* data));
 
 /**
- * Removes all DM components from the dependency manager.
+ * @brief Remove all DM components from the dependency manager.
  *
  * Should not be called from the Celix event thread.
  */
 CELIX_FRAMEWORK_EXPORT celix_status_t celix_dependencyManager_removeAllComponents(celix_dependency_manager_t *manager);
 
 /**
- * Same as celix_dependencyManager_removeAllComponents, but this call will not wait til all
+ * @brief Same as celix_dependencyManager_removeAllComponents, but this call will not wait til all
  * service registration and service trackers are unregistered/closed.
  *
  * The doneCallback will be called (if not NULL) with doneData as argument when the all component are removed
@@ -105,22 +107,23 @@
 CELIX_FRAMEWORK_EXPORT celix_status_t celix_dependencyManager_removeAllComponentsAsync(celix_dependency_manager_t *manager, void *doneData, void (*doneCallback)(void *data));
 
 /**
- * Check if all components for the bundle of the dependency manager are active (all required dependencies resolved).
+ * @brief Check if all components for the bundle of the dependency manager are active (all required dependencies resolved).
  */
 CELIX_FRAMEWORK_EXPORT bool celix_dependencyManager_areComponentsActive(celix_dependency_manager_t *manager);
 
 /**
- * Check if all components - for all bundles - are active (all required dependencies resolved).
+ * @brief Check if all components - for all bundles - are active (all required dependencies resolved).
  */
 CELIX_FRAMEWORK_EXPORT bool celix_dependencyManager_allComponentsActive(celix_dependency_manager_t *manager);
 
 /**
- * Return the nr of components for this dependency manager
+ * @brief Return the nr of components for this dependency manager
  */
 CELIX_FRAMEWORK_EXPORT size_t celix_dependencyManager_nrOfComponents(celix_dependency_manager_t *manager);
 
 /**
- * Wait for an empty Celix event queue.
+ * @brief Wait for an empty Celix event queue.
+ * 
  * Should not be called on the Celix event queue thread.
  *
  * Can be used to ensure that all created/updated components are completely processed (services registered
@@ -129,19 +132,22 @@
 CELIX_FRAMEWORK_EXPORT void celix_dependencyManager_wait(celix_dependency_manager_t* manager);
 
 /**
- * Create and returns a dependency manager info struct for the specified bundle.
+ * @brief Create and returns a dependency manager info struct for the specified bundle.
+ * 
  * The dependency manager info contains information about the state of the dependency manager components
  *
  * Caller has ownership of the return value (use celix_dependencyManager_destroyInfo to free the memory).
  *
  * @param manager The dependency manager
  * @param bndId The bundle id to get the info from.
- * @returns The dependency manager info for the provided bundle id or NULL if the bundle id is invalid.
+ * @returns The dependency manager info for the provided bundle id or NULL if the bundle id is invalid or the bundle of
+ *          the provided bundle id is not started.
  */
 CELIX_FRAMEWORK_EXPORT celix_dependency_manager_info_t* celix_dependencyManager_createInfo(celix_dependency_manager_t *manager, long bndId);
 
 /**
- * Create and returns a dependency manager info struct for all started bundles.
+ * @brief Create and returns a dependency manager info struct for all started bundles.
+ * 
  * The dependency manager info contains information about the state of the dependency manager components
  *
  * Caller has ownership of the return values (use celix_arrayList_destroy to free the memory).
@@ -152,18 +158,19 @@
 CELIX_FRAMEWORK_EXPORT celix_array_list_t * /*celix_dependency_manager_info_t* entries*/ celix_dependencyManager_createInfos(celix_dependency_manager_t *manager);
 
 /**
- * Destroys a DM info struct.
+ * @brief Destroy a DM info struct.
  */
 CELIX_FRAMEWORK_EXPORT void celix_dependencyManager_destroyInfo(celix_dependency_manager_t *manager, celix_dependency_manager_info_t *info);
 
 /**
- * Destroys a celix array list of  DM info structs.
+ * @brief Destroy a celix array list of  DM info structs.
  * @deprecated use celix_arrayList_destroy instead.
  */
 CELIX_FRAMEWORK_EXPORT void celix_dependencyManager_destroyInfos(celix_dependency_manager_t *manager, celix_array_list_t * infos /*entries celix_dependency_manager_info_t*/);
 
 /**
- * Print the dependency manager info for all bundles to the provided output stream.
+ * @brief Print the dependency manager info for all bundles to the provided output stream.
+ * 
  * @param manager The dependency manager.
  * @param fullInfo Whether to print the full info or summary.
  * @param useAnsiColors Whether to use ansi colors when printing info.
@@ -172,7 +179,8 @@
 CELIX_FRAMEWORK_EXPORT void celix_dependencyManager_printInfo(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, FILE* stream);
 
 /**
- * Print the dependency manager info for the provided bundle id to the provided output stream.
+ * @brief Print the dependency manager info for the provided bundle id to the provided output stream.
+ * 
  * @param manager The dependency manager.
  * @param fullInfo whether to print the full info or summary.
  * @param useAnsiColors Whether to use ansi colors when printing info.
diff --git a/libs/framework/src/dm_dependency_manager_impl.c b/libs/framework/src/dm_dependency_manager_impl.c
index 1de53a8..21a77d4 100644
--- a/libs/framework/src/dm_dependency_manager_impl.c
+++ b/libs/framework/src/dm_dependency_manager_impl.c
@@ -182,6 +182,10 @@
 static void celix_dm_getInfoCallback(void *handle, const celix_bundle_t *bnd) {
     celix_dependency_manager_info_t **out = handle;
 
+    if (celix_bundle_getState(bnd) != CELIX_BUNDLE_STATE_ACTIVE) {
+        return;
+    }
+
     celix_bundle_context_t *context = NULL;
     bundle_getContext((celix_bundle_t*)bnd, &context);
     celix_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(context);
@@ -261,6 +265,11 @@
 
 static void celix_dm_allComponentsActiveCallback(void *handle, const celix_bundle_t *bnd) {
 	bool *allActivePtr = handle;
+
+    if (celix_bundle_getState(bnd) != CELIX_BUNDLE_STATE_ACTIVE) {
+        return;
+    }
+
 	celix_bundle_context_t *context = NULL;
 	bundle_getContext((celix_bundle_t*)bnd, &context);
 	celix_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(context);
@@ -310,9 +319,11 @@
 }
 
 void celix_dependencyManager_destroyInfo(celix_dependency_manager_t *manager __attribute__((unused)), celix_dependency_manager_info_t *info) {
-	celix_arrayList_destroy(info->components);
-	free(info->bndSymbolicName);
-	free(info);
+    if (info != NULL) {
+        celix_arrayList_destroy(info->components);
+        free(info->bndSymbolicName);
+        free(info);
+    }
 }