Allow fine grain verbose logging control through system property.

  - Existing DEBUG and INFO change to the new mechanism, existing ERROR and
    WARNING unchanged.
  - By default, all verbose logging are disabled.
  - setprop debug.nn.vlog 1 enables all verbose logging.
  - setprop debug.nn.vlog "tag1 tag2 ..." only enable the selected tags.
  - Available tags:
      all: same as 1.
      model: enable logging with tag MODEL.
      compilation: enable logging with tag COMPILATION.
      execution: enable logging with tag EXECUTION.
      cpuexe: enable logging with tag CPUEXE.
      manager: enable logging with tag MANAGER.
      driver: enable logging with tag DRIVER.

Bug: 63905942
Test: mm
Test: NeuralNetworksTests pass
Test: manually set property to allow individual module to logging
      verbosely
Test: tested with debug.nn.partition default -> 0 -> 1 to make
      sure getProp still works fine

Change-Id: Iaa0ffa62176dabcdc35058748597df720fd6e47e
diff --git a/nn/common/Utils.cpp b/nn/common/Utils.cpp
index c0c9ccf..f73b12c 100644
--- a/nn/common/Utils.cpp
+++ b/nn/common/Utils.cpp
@@ -20,13 +20,64 @@
 #include "NeuralNetworks.h"
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
 #include <sys/system_properties.h>
+#include <unordered_map>
 
 using ::android::hidl::allocator::V1_0::IAllocator;
 
 namespace android {
 namespace nn {
 
+const char kVLogPropKey[] = "debug.nn.vlog";
+int vLogMask = ~0;
+
+// Split the space separated list of tags from verbose log setting and build the
+// logging mask from it. note that '1' and 'all' are special cases to enable all
+// verbose logging.
+//
+// NN API verbose logging setting comes from system property debug.nn.vlog.
+// Example:
+// setprop debug.nn.vlog 1 : enable all logging tags.
+// setprop debug.nn.vlog "model compilation" : only enable logging for MODEL and
+//                                             COMPILATION tags.
+void initVLogMask() {
+    vLogMask = 0;
+    const std::string vLogSetting = android::base::GetProperty(kVLogPropKey, "");
+    if (vLogSetting.empty()) {
+        return;
+    }
+
+    std::unordered_map<std::string, int> vLogFlags = {
+        {"1", -1},
+        {"all", -1},
+        {"model", MODEL},
+        {"compilation", COMPILATION},
+        {"execution", EXECUTION},
+        {"cpuexe", CPUEXE},
+        {"manager", MANAGER},
+        {"driver", DRIVER}};
+
+    std::vector<std::string> elements = android::base::Split(vLogSetting, " ");
+    for (const auto& elem : elements) {
+        const auto& flag = vLogFlags.find(elem);
+        if (flag == vLogFlags.end()) {
+            LOG(ERROR) << "Unknown trace flag: " << elem;
+            continue;
+        }
+
+        if (flag->second == -1) {
+            // -1 is used for the special values "1" and "all" that enable all
+            // tracing.
+            vLogMask = ~0;
+            return;
+        } else {
+            vLogMask |= 1 << flag->second;
+        }
+    }
+}
+
 #define COUNT(X) (sizeof(X) / sizeof(X[0]))
 
 const char* kTypeNames[kNumberOfDataTypes] = {
@@ -384,31 +435,14 @@
 }
 
 #ifdef NN_DEBUGGABLE
-
-// Implementation of property_get from libcutils
-static int property_get(const char* key, char* value, const char* default_value) {
-    int len;
-    len = __system_property_get(key, value);
-    if (len > 0) {
-        return len;
-    }
-
-    if (default_value) {
-        len = strlen(default_value);
-        memcpy(value, default_value, len + 1);
-    }
-    return len;
-}
-
 uint32_t getProp(const char* str, uint32_t defaultValue) {
-    char buf[256];
-    if (property_get(str, buf, nullptr) > 0) {
-        return atoi(buf);
+    const std::string propStr = android::base::GetProperty(str, "");
+    if (propStr.size() > 0) {
+        return std::stoi(propStr);
     } else {
         return defaultValue;
     }
 }
-
 #endif  // NN_DEBUGGABLE
 
 } // namespace nn