jni: Extending native interface to NFD
- `startNfd` now accepts Map<String, String> instead of just a single
String/homeDir parameter.
- new `getNfdLogModules` method returns all available log modules
Change-Id: I597579c69be06607de0734c034226fe9a359a2bc
Refs: #2746, #2623
diff --git a/app/src/main/java/net/named_data/nfd/MainFragment.java b/app/src/main/java/net/named_data/nfd/MainFragment.java
index 68e9690..96443c0 100644
--- a/app/src/main/java/net/named_data/nfd/MainFragment.java
+++ b/app/src/main/java/net/named_data/nfd/MainFragment.java
@@ -78,8 +78,7 @@
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isOn)
{
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
- sp.edit()
+ m_sharedPreferences.edit()
.putBoolean(PREF_NFD_SERVICE_STATUS, isOn)
.apply();
@@ -110,6 +109,13 @@
}
@Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState)
+ {
+ super.onActivityCreated(savedInstanceState);
+ m_sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ }
+
+ @Override
public void
onResume() {
super.onResume();
@@ -232,7 +238,7 @@
setNfdServiceRunning();
G.Log("ClientHandler: NFD is Running.");
- m_handler.post(m_statusUpdateRunnable);
+ m_handler.postDelayed(m_statusUpdateRunnable, 500);
break;
case NfdService.NFD_SERVICE_STOPPED:
@@ -260,8 +266,7 @@
// Check if NFD Service is running
try {
- SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity());
- boolean shouldServiceBeOn = sp.getBoolean(PREF_NFD_SERVICE_STATUS, true);
+ boolean shouldServiceBeOn = m_sharedPreferences.getBoolean(PREF_NFD_SERVICE_STATUS, true);
Message msg = Message.obtain(null, shouldServiceBeOn ? NfdService.START_NFD_SERVICE : NfdService.STOP_NFD_SERVICE);
msg.replyTo = m_clientMessenger;
@@ -330,7 +335,8 @@
onPostExecute(ForwarderStatus fs)
{
if (fs == null) {
- // Maybe display error message from result.second
+ // when failed, try after 0.5 seconds
+ m_handler.postDelayed(m_statusUpdateRunnable, 500);
}
else {
m_versionView.setText(fs.getNfdVersion());
@@ -351,9 +357,10 @@
m_outDataView.setText(String.valueOf(fs.getNumOutDatas()));
m_nfdStatusView.setVisibility(View.VISIBLE);
- }
- m_handler.postDelayed(m_statusUpdateRunnable, 5000);
+ // refresh after 5 seconds
+ m_handler.postDelayed(m_statusUpdateRunnable, 5000);
+ }
}
}
@@ -395,5 +402,7 @@
}
};
+ private SharedPreferences m_sharedPreferences;
+
private static final String PREF_NFD_SERVICE_STATUS = "NFD_SERVICE_STATUS";
}
diff --git a/app/src/main/java/net/named_data/nfd/service/NfdService.java b/app/src/main/java/net/named_data/nfd/service/NfdService.java
index e4226db..1b43df3 100644
--- a/app/src/main/java/net/named_data/nfd/service/NfdService.java
+++ b/app/src/main/java/net/named_data/nfd/service/NfdService.java
@@ -29,6 +29,12 @@
import net.named_data.nfd.utils.G;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* NfdService that runs the native NFD.
*
@@ -68,11 +74,11 @@
/**
* Native API for starting the NFD.
*
- * @param homePath Absolute path of the home directory for the service;
- * Usually achieved by calling ContextWrapper.getFilesDir().getAbsolutePath()
+ * @param params NFD parameters. Must include 'homePath' with absolute path of the home directory
+ * for the service (ContextWrapper.getFilesDir().getAbsolutePath())
*/
public native static void
- startNfd(String homePath);
+ startNfd(Map<String, String> params);
/**
* Native API for stopping the NFD.
@@ -80,6 +86,9 @@
public native static void
stopNfd();
+ public native static List<String>
+ getNfdLogModules();
+
/** Message to start NFD Service */
public static final int START_NFD_SERVICE = 1;
@@ -144,7 +153,17 @@
serviceStartNfd() {
if (!m_isNfdStarted) {
m_isNfdStarted = true;
- startNfd(getFilesDir().getAbsolutePath());
+ HashMap<String, String> params = new HashMap<>();
+ params.put("homePath", getFilesDir().getAbsolutePath());
+ Set<Map.Entry<String,String>> e = params.entrySet();
+
+ startNfd(params);
+
+ // Example how to retrieve all available NFD log modules
+ List<String> modules = getNfdLogModules();
+ for (String module : modules) {
+ G.Log(module);
+ }
// TODO: Reload NFD and NRD in memory structures (if any)
diff --git a/app/src/main/jni/nfd-wrapper.cpp b/app/src/main/jni/nfd-wrapper.cpp
index d16049d..a5544a8 100644
--- a/app/src/main/jni/nfd-wrapper.cpp
+++ b/app/src/main/jni/nfd-wrapper.cpp
@@ -192,18 +192,61 @@
static unique_ptr<Runner> g_runner;
static boost::thread g_thread;
+static std::map<std::string, std::string> g_params;
} // namespace nfd
+
+std::map<std::string, std::string>
+getParams(JNIEnv* env, jobject jParams)
+{
+ std::map<std::string, std::string> params;
+
+ jclass jcMap = env->GetObjectClass(jParams);
+ jclass jcSet = env->FindClass("java/util/Set");
+ jclass jcIterator = env->FindClass("java/util/Iterator");
+ jclass jcMapEntry = env->FindClass("java/util/Map$Entry");
+
+ jmethodID jcMapEntrySet = env->GetMethodID(jcMap, "entrySet", "()Ljava/util/Set;");
+ jmethodID jcSetIterator = env->GetMethodID(jcSet, "iterator", "()Ljava/util/Iterator;");
+ jmethodID jcIteratorHasNext = env->GetMethodID(jcIterator, "hasNext", "()Z");
+ jmethodID jcIteratorNext = env->GetMethodID(jcIterator, "next", "()Ljava/lang/Object;");
+ jmethodID jcMapEntryGetKey = env->GetMethodID(jcMapEntry, "getKey", "()Ljava/lang/Object;");
+ jmethodID jcMapEntryGetValue = env->GetMethodID(jcMapEntry, "getValue", "()Ljava/lang/Object;");
+
+ jobject jParamsEntrySet = env->CallObjectMethod(jParams, jcMapEntrySet);
+ jobject jParamsIterator = env->CallObjectMethod(jParamsEntrySet, jcSetIterator);
+ jboolean bHasNext = env->CallBooleanMethod(jParamsIterator, jcIteratorHasNext);
+ while (bHasNext) {
+ jobject entry = env->CallObjectMethod(jParamsIterator, jcIteratorNext);
+
+ jstring jKey = (jstring)env->CallObjectMethod(entry, jcMapEntryGetKey);
+ jstring jValue = (jstring)env->CallObjectMethod(entry, jcMapEntryGetValue);
+
+ const char* cKey = env->GetStringUTFChars(jKey, nullptr);
+ const char* cValue = env->GetStringUTFChars(jValue, nullptr);
+
+ params.insert(std::make_pair(cKey, cValue));
+
+ env->ReleaseStringUTFChars(jKey, cKey);
+ env->ReleaseStringUTFChars(jValue, cValue);
+
+ bHasNext = env->CallBooleanMethod(jParamsIterator, jcIteratorHasNext);
+ }
+
+ return params;
+}
+
+
JNIEXPORT void JNICALL
-Java_net_named_1data_nfd_service_NfdService_startNfd(JNIEnv* env, jclass, jstring homePathJ)
+Java_net_named_1data_nfd_service_NfdService_startNfd(JNIEnv* env, jclass, jobject jParams)
{
if (nfd::g_runner.get() == nullptr) {
+ nfd::g_params = getParams(env, jParams);
+
// set/update HOME environment variable
- const char* homePath = env->GetStringUTFChars(homePathJ, nullptr);
- ::setenv("HOME", homePath, true);
- env->ReleaseStringUTFChars(homePathJ, homePath);
- NFD_LOG_INFO("Use [" << homePath << "] as a security storage");
+ ::setenv("HOME", nfd::g_params["homePath"].c_str(), true);
+ NFD_LOG_INFO("Use [" << nfd::g_params["homePath"] << "] as a security storage");
nfd::g_thread = boost::thread([] {
NFD_LOG_INFO("Starting NFD...");
@@ -238,3 +281,20 @@
// do not block anything
}
}
+
+JNIEXPORT jobject JNICALL
+Java_net_named_1data_nfd_service_NfdService_getNfdLogModules(JNIEnv* env, jclass)
+{
+ jclass jcLinkedList = env->FindClass("java/util/LinkedList");
+ jmethodID jcLinkedListConstructor = env->GetMethodID(jcLinkedList, "<init>", "()V");
+ jmethodID jcLinkedListAdd = env->GetMethodID(jcLinkedList, "add", "(Ljava/lang/Object;)Z");
+
+ jobject jModules = env->NewObject(jcLinkedList, jcLinkedListConstructor);
+
+ for (const auto& module : nfd::LoggerFactory::getInstance().getModules()) {
+ jstring jModule = env->NewStringUTF(module.c_str());
+ env->CallBooleanMethod(jModules, jcLinkedListAdd, jModule);
+ }
+
+ return jModules;
+}
diff --git a/app/src/main/jni/nfd-wrapper.hpp b/app/src/main/jni/nfd-wrapper.hpp
index 97e3cc1..fcd598d 100644
--- a/app/src/main/jni/nfd-wrapper.hpp
+++ b/app/src/main/jni/nfd-wrapper.hpp
@@ -26,13 +26,14 @@
#ifdef __cplusplus
extern "C" {
#endif
+
/*
* Class: net_named_data_nfd_service_NfdService
* Method: startNfd
- * Signature: (Ljava/lang/String;)V
+ * Signature: (Ljava/lang/Map;)V
*/
JNIEXPORT void JNICALL
-Java_net_named_1data_nfd_service_NfdService_startNfd(JNIEnv*, jclass, jstring);
+Java_net_named_1data_nfd_service_NfdService_startNfd(JNIEnv*, jclass, jobject);
/*
* Class: net_named_data_nfd_service_NfdService
@@ -42,6 +43,14 @@
JNIEXPORT void JNICALL
Java_net_named_1data_nfd_service_NfdService_stopNfd(JNIEnv*, jclass);
+/*
+ * Class: net_named_data_nfd_service_NfdService
+ * Method: getNfdLogModules
+ * Signature: ()Ljava/util/List;
+ */
+JNIEXPORT jobject JNICALL
+Java_net_named_1data_nfd_service_NfdService_getNfdLogModules(JNIEnv*, jclass);
+
#ifdef __cplusplus
}
#endif