IVGCVSW-6311 Add the pre-import backend capability

 * Update acl and ref backend capabilities
 * Add check for AsyncExecution capability in LoadedNetwork
 * Add new exception for capabilities

Signed-off-by: Finn Williams <Finn.Williams@arm.com>
Change-Id: I2f053c845a64f336e96d452793639c6e0d3eaa89
diff --git a/include/armnn/Exceptions.hpp b/include/armnn/Exceptions.hpp
index e3f086e..1a123bf 100644
--- a/include/armnn/Exceptions.hpp
+++ b/include/armnn/Exceptions.hpp
@@ -155,6 +155,12 @@
     using Exception::Exception;
 };
 
+class BackendCapabilityException : public Exception
+{
+public:
+    using Exception::Exception;
+};
+
 template <typename ExceptionType>
 void ConditionalThrow(bool condition, const std::string& message)
 {
diff --git a/src/armnn/LoadedNetwork.cpp b/src/armnn/LoadedNetwork.cpp
index 531d43d..9b5748b 100644
--- a/src/armnn/LoadedNetwork.cpp
+++ b/src/armnn/LoadedNetwork.cpp
@@ -19,6 +19,7 @@
 #include <armnn/backends/IMemoryManager.hpp>
 #include <backendsCommon/MemCopyWorkload.hpp>
 #include <backendsCommon/MemSyncWorkload.hpp>
+#include <armnn/BackendHelper.hpp>
 
 #include <fmt/format.h>
 
@@ -144,6 +145,14 @@
 
             IBackendInternal* backend = it.first->second.get();
 
+            if (networkProperties.m_AsyncEnabled &&
+                HasCapability(BackendOptions::BackendOption{"AsyncExecution", false}, backend->GetCapabilities()))
+            {
+                std::string er = backend->GetId();
+                er += " does not support AsyncExecution";
+                throw BackendCapabilityException(er);
+            }
+
             if (backend->SupportsTensorAllocatorAPI())
             {
                 auto workloadFactory = backend->CreateWorkloadFactory(
diff --git a/src/backends/backendsCommon/test/CompatibilityTests.cpp b/src/backends/backendsCommon/test/CompatibilityTests.cpp
index 34baad9..7b25732 100644
--- a/src/backends/backendsCommon/test/CompatibilityTests.cpp
+++ b/src/backends/backendsCommon/test/CompatibilityTests.cpp
@@ -128,26 +128,27 @@
 
 TEST_SUITE("BackendCapability")
 {
-#if defined(ARMNNREF_ENABLED)
 
-TEST_CASE("Ref_Backends_Capability_Test")
+namespace
 {
-    auto refBackend  = std::make_unique<RefBackend>();
-    auto refCapabilities = refBackend->GetCapabilities();
 
-    CHECK(armnn::HasCapability("NonConstWeights", refCapabilities));
-    CHECK(armnn::HasCapability("AsyncExecution", refCapabilities));
-
-    armnn::BackendOptions::BackendOption nonConstWeights{"NonConstWeights", true};
-    armnn::BackendOptions::BackendOption AsyncExecution{"AsyncExecution", true};
-
-    CHECK(armnn::HasCapability(nonConstWeights, refCapabilities));
-    CHECK(armnn::HasCapability(AsyncExecution, refCapabilities));
+void CapabilityTestHelper(BackendCapabilities &capabilities,
+                          std::vector<std::pair<std::string, bool>> capabilityVector)
+{
+    for (auto pair : capabilityVector)
+    {
+        CHECK_MESSAGE(armnn::HasCapability(pair.first, capabilities),
+                        pair.first << " capability was not been found");
+        CHECK_MESSAGE(armnn::HasCapability(BackendOptions::BackendOption{pair.first, pair.second}, capabilities),
+                        pair.first << " capability set incorrectly");
+    }
 }
 
-TEST_CASE("Ref_Backends_Unkown_Capability_Test")
+#if defined(ARMNNREF_ENABLED)
+
+TEST_CASE("Ref_Backends_Unknown_Capability_Test")
 {
-    auto refBackend  = std::make_unique<RefBackend>();
+    auto refBackend = std::make_unique<RefBackend>();
     auto refCapabilities = refBackend->GetCapabilities();
 
     armnn::BackendOptions::BackendOption AsyncExecutionFalse{"AsyncExecution", false};
@@ -167,44 +168,53 @@
     CHECK(!armnn::HasCapability(unkownCapability, refCapabilities));
 }
 
+TEST_CASE ("Ref_Backends_Capability_Test")
+{
+    auto refBackend = std::make_unique<RefBackend>();
+    auto refCapabilities = refBackend->GetCapabilities();
+
+    CapabilityTestHelper(refCapabilities,
+                         {{"NonConstWeights", true},
+                          {"AsyncExecution", true},
+                          {"ProtectedContentAllocation", false},
+                          {"ConstantTensorsAsInputs", true},
+                          {"PreImportIOTensors", false}});
+}
+
 #endif
 
 #if defined(ARMCOMPUTENEON_ENABLED)
 
-TEST_CASE("Neon_Backends_Capability_Test")
+TEST_CASE ("Neon_Backends_Capability_Test")
 {
     auto neonBackend = std::make_unique<NeonBackend>();
     auto neonCapabilities = neonBackend->GetCapabilities();
 
-    CHECK(armnn::HasCapability("NonConstWeights", neonCapabilities));
-    CHECK(armnn::HasCapability("AsyncExecution", neonCapabilities));
-
-    armnn::BackendOptions::BackendOption nonConstWeights{"NonConstWeights", false};
-    armnn::BackendOptions::BackendOption AsyncExecution{"AsyncExecution", false};
-
-    CHECK(armnn::HasCapability(nonConstWeights, neonCapabilities));
-    CHECK(armnn::HasCapability(AsyncExecution, neonCapabilities));
+    CapabilityTestHelper(neonCapabilities,
+                         {{"NonConstWeights", false},
+                          {"AsyncExecution", false},
+                          {"ProtectedContentAllocation", false},
+                          {"ConstantTensorsAsInputs", false},
+                          {"PreImportIOTensors", false}});
 }
 
 #endif
 
 #if defined(ARMCOMPUTECL_ENABLED)
 
-TEST_CASE("Cl_Backends_Capability_Test")
+TEST_CASE ("Cl_Backends_Capability_Test")
 {
     auto clBackend = std::make_unique<ClBackend>();
     auto clCapabilities = clBackend->GetCapabilities();
 
-    CHECK(armnn::HasCapability("NonConstWeights", clCapabilities));
-    CHECK(armnn::HasCapability("AsyncExecution", clCapabilities));
-
-    armnn::BackendOptions::BackendOption nonConstWeights{"NonConstWeights", false};
-    armnn::BackendOptions::BackendOption AsyncExecution{"AsyncExecution", false};
-
-    CHECK(armnn::HasCapability(nonConstWeights, clCapabilities));
-    CHECK(armnn::HasCapability(AsyncExecution, clCapabilities));
+    CapabilityTestHelper(clCapabilities,
+                         {{"NonConstWeights", false},
+                          {"AsyncExecution", false},
+                          {"ProtectedContentAllocation", true},
+                          {"ConstantTensorsAsInputs", false},
+                          {"PreImportIOTensors", false}});
 }
 
 #endif
-
+}
 }
diff --git a/src/backends/cl/ClBackend.hpp b/src/backends/cl/ClBackend.hpp
index 4f68c3b..570d301 100644
--- a/src/backends/cl/ClBackend.hpp
+++ b/src/backends/cl/ClBackend.hpp
@@ -26,7 +26,9 @@
                                              {
                                                      {"NonConstWeights", false},
                                                      {"AsyncExecution", false},
-                                                     {"ProtectedContentAllocation", true}
+                                                     {"ProtectedContentAllocation", true},
+                                                     {"ConstantTensorsAsInputs", false},
+                                                     {"PreImportIOTensors", false}
                                              });
 
 class ClBackend : public IBackendInternal
diff --git a/src/backends/neon/NeonBackend.hpp b/src/backends/neon/NeonBackend.hpp
index eae5732..0ae28d8 100644
--- a/src/backends/neon/NeonBackend.hpp
+++ b/src/backends/neon/NeonBackend.hpp
@@ -13,7 +13,10 @@
 const BackendCapabilities cpuAccCapabilities("GpuAcc",
                                              {
                                                      {"NonConstWeights", false},
-                                                     {"AsyncExecution", false}
+                                                     {"AsyncExecution", false},
+                                                     {"ProtectedContentAllocation", false},
+                                                     {"ConstantTensorsAsInputs", false},
+                                                     {"PreImportIOTensors", false}
                                              });
 
 
diff --git a/src/backends/reference/RefBackend.hpp b/src/backends/reference/RefBackend.hpp
index 2855957..1a79d70 100644
--- a/src/backends/reference/RefBackend.hpp
+++ b/src/backends/reference/RefBackend.hpp
@@ -13,7 +13,9 @@
                                              {
                                                     {"NonConstWeights", true},
                                                     {"AsyncExecution", true},
-                                                    {"ConstantTensorsAsInputs", true}
+                                                    {"ProtectedContentAllocation", false},
+                                                    {"ConstantTensorsAsInputs", true},
+                                                    {"PreImportIOTensors", false}
                                              });
 
 const std::set<armnn::BackendCapability> oldCpuRefCapabilities {