Adding initial app framework

Change-Id: I0c53e3487eb3be1eefa2d0c7f260a90d82fd8844
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..4720ba0
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,99 @@
+import org.apache.tools.ant.taskdefs.condition.Os
+
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 21
+    buildToolsVersion "21.1.2"
+
+    defaultConfig {
+        applicationId "net.named_data.nfd"
+        minSdkVersion 14
+        targetSdkVersion 21
+        versionCode 2001
+        versionName "0.2.1"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    sourceSets {
+        main {
+            java.srcDirs "src/main/java"
+            res.srcDirs "src/main/res"
+            jniLibs.srcDir 'src/main/libs'
+            jni.srcDirs = [] //disable automatic ndk-build call
+        }
+        androidTest.setRoot('tests')
+        androidTest.java.srcDirs = ['tests/src']
+    }
+
+    splits {
+        abi {
+            enable true // enable ABI split feature to create one APK per ABI
+            universalApk true //generate an additional APK that targets all the ABIs
+        }
+    }
+
+    // map for the version code
+    // versionCode digit for each supported ABI, with 64bit>32bit and x86>armeabi-*
+    project.ext.versionCodes = ['armeabi': 1,
+                                'armeabi-v7a': 2,
+                                'arm64-v8a': 3,
+                                'mips': 5,
+                                'mips64': 6,
+                                'x86': 8,
+                                'x86_64': 9]
+
+    android.applicationVariants.all { variant ->
+        // assign different version code for each output
+        variant.outputs.each { output ->
+            output.versionCodeOverride = project.ext.versionCodes.get(
+                    output.getFilter(
+                            com.android.build.OutputFile.ABI), 0) * 1000000 +
+                    defaultConfig.versionCode
+        }
+    }
+
+    // call regular ndk-build(.cmd) script from app directory
+    task ndkBuild(type: Exec) {
+        commandLine getNdkBuildCmd(), '-C', file('src/main').absolutePath
+    }
+
+    tasks.withType(JavaCompile) {
+        compileTask -> compileTask.dependsOn ndkBuild
+    }
+
+    task cleanNative(type: Exec) {
+        commandLine getNdkBuildCmd(), '-C', file('src/main').absolutePath, 'clean'
+    }
+
+    clean.dependsOn cleanNative
+}
+
+def getNdkBuildCmd() {
+    if (System.env.ANDROID_NDK_ROOT != null)
+        return System.env.ANDROID_NDK_ROOT
+
+    Properties properties = new Properties()
+    properties.load(project.rootProject.file('local.properties').newDataInputStream())
+    String ndk_dir = properties.getProperty('ndk.dir', null)
+    if (ndk_dir == null) {
+        throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file or with an ANDROID_NDK_ROOT environment variable.")
+    }
+
+    String ndk_build = ndk_dir + "/ndk-build"
+    if (Os.isFamily(Os.FAMILY_WINDOWS)) {
+        ndk_build += ".cmd"
+    }
+
+    return ndk_build
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    compile 'com.android.support:appcompat-v7:21.0.3'
+    compile 'com.android.support:support-v4:21.0.3'
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3b96635
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="net.named_data.nfd" >
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".NfdSettingsActivity"
+            android:label="@string/app_name" >
+        </activity>
+    </application>
+
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.READ_LOGS" />
+
+</manifest>
diff --git a/app/src/main/java/net/named_data/nfd/NfdSettingsActivity.java b/app/src/main/java/net/named_data/nfd/NfdSettingsActivity.java
new file mode 100644
index 0000000..a161349
--- /dev/null
+++ b/app/src/main/java/net/named_data/nfd/NfdSettingsActivity.java
@@ -0,0 +1,280 @@
+package net.named_data.nfd;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.preference.RingtonePreference;
+import android.text.TextUtils;
+
+
+import java.util.List;
+
+import net.named_data.nfd.wrappers.Example;
+
+/**
+ * A {@link PreferenceActivity} that presents a set of application settings. On
+ * handset devices, settings are presented as a single list. On tablets,
+ * settings are split by category, with category headers shown to the left of
+ * the list of settings.
+ * <p/>
+ * See <a href="http://developer.android.com/design/patterns/settings.html">
+ * Android Design: Settings</a> for design guidelines and the <a
+ * href="http://developer.android.com/guide/topics/ui/settings.html">Settings
+ * API Guide</a> for more information on developing a Settings UI.
+ */
+public class NfdSettingsActivity extends PreferenceActivity
+{
+  /**
+   * Determines whether to always show the simplified settings UI, where
+   * settings are presented in a single list. When false, settings are shown
+   * as a master/detail two-pane view on tablets. When true, a single pane is
+   * shown on tablets.
+   */
+  private static final boolean ALWAYS_SIMPLE_PREFS = false;
+
+
+  @Override
+  protected void onPostCreate(Bundle savedInstanceState)
+  {
+    super.onPostCreate(savedInstanceState);
+
+    /// @todo Remove after the example no longer needed
+    Example.main();
+
+    setupSimplePreferencesScreen();
+  }
+
+  /**
+   * Shows the simplified settings UI if the device configuration if the
+   * device configuration dictates that a simplified, single-pane UI should be
+   * shown.
+   */
+  private void setupSimplePreferencesScreen()
+  {
+    if (!isSimplePreferences(this)) {
+      return;
+    }
+
+    // In the simplified UI, fragments are not used at all and we instead
+    // use the older PreferenceActivity APIs.
+
+    // Add 'general' preferences.
+    addPreferencesFromResource(R.xml.pref_general);
+
+    // Add 'notifications' preferences, and a corresponding header.
+    PreferenceCategory fakeHeader = new PreferenceCategory(this);
+    fakeHeader.setTitle(R.string.pref_header_notifications);
+    getPreferenceScreen().addPreference(fakeHeader);
+    addPreferencesFromResource(R.xml.pref_notification);
+
+    // Add 'data and sync' preferences, and a corresponding header.
+    fakeHeader = new PreferenceCategory(this);
+    fakeHeader.setTitle(R.string.pref_header_data_sync);
+    getPreferenceScreen().addPreference(fakeHeader);
+    addPreferencesFromResource(R.xml.pref_data_sync);
+
+    // Bind the summaries of EditText/List/Dialog/Ringtone preferences to
+    // their values. When their values change, their summaries are updated
+    // to reflect the new value, per the Android Design guidelines.
+    bindPreferenceSummaryToValue(findPreference("example_text"));
+    bindPreferenceSummaryToValue(findPreference("example_list"));
+    bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
+    bindPreferenceSummaryToValue(findPreference("sync_frequency"));
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean onIsMultiPane()
+  {
+    return isXLargeTablet(this) && !isSimplePreferences(this);
+  }
+
+  /**
+   * Helper method to determine if the device has an extra-large screen. For
+   * example, 10" tablets are extra-large.
+   */
+  private static boolean isXLargeTablet(Context context)
+  {
+    return (context.getResources().getConfiguration().screenLayout
+      & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
+  }
+
+  /**
+   * Determines whether the simplified settings UI should be shown. This is
+   * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
+   * doesn't have newer APIs like {@link PreferenceFragment}, or the device
+   * doesn't have an extra-large screen. In these cases, a single-pane
+   * "simplified" settings UI should be shown.
+   */
+  private static boolean isSimplePreferences(Context context)
+  {
+    return ALWAYS_SIMPLE_PREFS
+      || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
+      || !isXLargeTablet(context);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+  public void onBuildHeaders(List<Header> target)
+  {
+    if (!isSimplePreferences(this)) {
+      loadHeadersFromResource(R.xml.pref_headers, target);
+    }
+  }
+
+  /**
+   * A preference value change listener that updates the preference's summary
+   * to reflect its new value.
+   */
+  private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener()
+  {
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object value)
+    {
+      String stringValue = value.toString();
+
+      if (preference instanceof ListPreference) {
+        // For list preferences, look up the correct display value in
+        // the preference's 'entries' list.
+        ListPreference listPreference = (ListPreference) preference;
+        int index = listPreference.findIndexOfValue(stringValue);
+
+        // Set the summary to reflect the new value.
+        preference.setSummary(
+          index >= 0
+            ? listPreference.getEntries()[index]
+            : null);
+
+      } else if (preference instanceof RingtonePreference) {
+        // For ringtone preferences, look up the correct display value
+        // using RingtoneManager.
+        if (TextUtils.isEmpty(stringValue)) {
+          // Empty values correspond to 'silent' (no ringtone).
+          preference.setSummary(R.string.pref_ringtone_silent);
+
+        } else {
+          Ringtone ringtone = RingtoneManager.getRingtone(
+            preference.getContext(), Uri.parse(stringValue));
+
+          if (ringtone == null) {
+            // Clear the summary if there was a lookup error.
+            preference.setSummary(null);
+          } else {
+            // Set the summary to reflect the new ringtone display
+            // name.
+            String name = ringtone.getTitle(preference.getContext());
+            preference.setSummary(name);
+          }
+        }
+
+      } else {
+        // For all other preferences, set the summary to the value's
+        // simple string representation.
+        preference.setSummary(stringValue);
+      }
+      return true;
+    }
+  };
+
+  /**
+   * Binds a preference's summary to its value. More specifically, when the
+   * preference's value is changed, its summary (line of text below the
+   * preference title) is updated to reflect the value. The summary is also
+   * immediately updated upon calling this method. The exact display format is
+   * dependent on the type of preference.
+   *
+   * @see #sBindPreferenceSummaryToValueListener
+   */
+  private static void bindPreferenceSummaryToValue(Preference preference)
+  {
+    // Set the listener to watch for value changes.
+    preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
+
+    // Trigger the listener immediately with the preference's
+    // current value.
+    sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
+                                                             PreferenceManager
+                                                               .getDefaultSharedPreferences(preference.getContext())
+                                                               .getString(preference.getKey(), ""));
+  }
+
+  /**
+   * This fragment shows general preferences only. It is used when the
+   * activity is showing a two-pane settings UI.
+   */
+  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+  public static class GeneralPreferenceFragment extends PreferenceFragment
+  {
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+      super.onCreate(savedInstanceState);
+      addPreferencesFromResource(R.xml.pref_general);
+
+      // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+      // to their values. When their values change, their summaries are
+      // updated to reflect the new value, per the Android Design
+      // guidelines.
+      bindPreferenceSummaryToValue(findPreference("example_text"));
+      bindPreferenceSummaryToValue(findPreference("example_list"));
+    }
+  }
+
+  /**
+   * This fragment shows notification preferences only. It is used when the
+   * activity is showing a two-pane settings UI.
+   */
+  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+  public static class NotificationPreferenceFragment extends PreferenceFragment
+  {
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+      super.onCreate(savedInstanceState);
+      addPreferencesFromResource(R.xml.pref_notification);
+
+      // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+      // to their values. When their values change, their summaries are
+      // updated to reflect the new value, per the Android Design
+      // guidelines.
+      bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
+    }
+  }
+
+  /**
+   * This fragment shows data and sync preferences only. It is used when the
+   * activity is showing a two-pane settings UI.
+   */
+  @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+  public static class DataSyncPreferenceFragment extends PreferenceFragment
+  {
+    @Override
+    public void onCreate(Bundle savedInstanceState)
+    {
+      super.onCreate(savedInstanceState);
+      addPreferencesFromResource(R.xml.pref_data_sync);
+
+      // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+      // to their values. When their values change, their summaries are
+      // updated to reflect the new value, per the Android Design
+      // guidelines.
+      bindPreferenceSummaryToValue(findPreference("sync_frequency"));
+    }
+  }
+}
diff --git a/app/src/main/java/net/named_data/nfd/wrappers/Example.java b/app/src/main/java/net/named_data/nfd/wrappers/Example.java
new file mode 100644
index 0000000..0e70c0a
--- /dev/null
+++ b/app/src/main/java/net/named_data/nfd/wrappers/Example.java
@@ -0,0 +1,13 @@
+package net.named_data.nfd.wrappers;
+
+/**
+ * Created by cawka on 1/27/15.
+ */
+public class Example
+{
+  static {
+    System.loadLibrary("nfd-example");
+  }
+
+  public native static void main();
+}
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..67d22e0
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,8 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := nfd-example
+LOCAL_SRC_FILES := android-logger-streambuf.cpp wrappers-example.cpp
+# LOCAL_SHARED_LIBRARIES :=
+LOCAL_LDLIBS := -llog
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..980d621
--- /dev/null
+++ b/app/src/main/jni/Application.mk
@@ -0,0 +1,5 @@
+APP_ABI=all
+
+APP_STL := gnustl_shared
+APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti
+
diff --git a/app/src/main/jni/android-logger-streambuf.cpp b/app/src/main/jni/android-logger-streambuf.cpp
new file mode 100644
index 0000000..f693501
--- /dev/null
+++ b/app/src/main/jni/android-logger-streambuf.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "android-logger-streambuf.hpp"
+
+#include <android/log.h>
+
+namespace nfd_android {
+
+AndroidLoggerStreambuf::AndroidLoggerStreambuf()
+{
+  this->setp(buffer, buffer + MAX_BUF_SIZE - 1);
+}
+
+int
+AndroidLoggerStreambuf::overflow(int c)
+{
+  if (c == traits_type::eof()) {
+    *this->pptr() = traits_type::to_char_type(c);
+    this->sbumpc();
+  }
+  return this->sync()? traits_type::eof(): traits_type::not_eof(c);
+}
+
+int
+AndroidLoggerStreambuf::sync()
+{
+  int rc = 0;
+  if (this->pbase() != this->pptr()) {
+    __android_log_print(ANDROID_LOG_INFO, "Native", "%s",
+                        std::string(this->pbase(), this->pptr() - this->pbase()).c_str());
+    rc = 0;
+    this->setp(buffer, buffer + MAX_BUF_SIZE - 1);
+  }
+  return rc;
+}
+
+} // namespace nfd_android
diff --git a/app/src/main/jni/android-logger-streambuf.hpp b/app/src/main/jni/android-logger-streambuf.hpp
new file mode 100644
index 0000000..6ca2500
--- /dev/null
+++ b/app/src/main/jni/android-logger-streambuf.hpp
@@ -0,0 +1,57 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NFD_ANDROID_JNI_ANDROID_LOG_HPP
+#define NFD_ANDROID_JNI_ANDROID_LOG_HPP
+
+#include <streambuf>
+
+namespace nfd_android {
+
+/**
+ * @brief Streambuf implementation to redirect to streams to Android logging facility
+ *
+ * Based on code from http://stackoverflow.com/a/8870278/2150331
+ */
+class AndroidLoggerStreambuf : public std::streambuf
+{
+public:
+  AndroidLoggerStreambuf();
+
+protected:
+  virtual int
+  overflow(int c);
+
+  virtual int
+  sync();
+
+private:
+  enum { MAX_BUF_SIZE = 1024 };
+  char buffer[MAX_BUF_SIZE];
+};
+
+} // namespace nfd_android
+
+#endif // NFD_ANDROID_JNI_ANDROID_LOG_HPP
diff --git a/app/src/main/jni/wrappers-example.cpp b/app/src/main/jni/wrappers-example.cpp
new file mode 100644
index 0000000..5553258
--- /dev/null
+++ b/app/src/main/jni/wrappers-example.cpp
@@ -0,0 +1,43 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "wrappers-example.hpp"
+#include "android-logger-streambuf.hpp"
+
+#include <iostream>
+
+JNIEXPORT void JNICALL
+Java_net_named_1data_nfd_wrappers_Example_main(JNIEnv*, jclass)
+{
+  nfd_android::AndroidLoggerStreambuf newBuffer;
+  std::streambuf *backupCout = std::cout.rdbuf(&newBuffer);
+  std::streambuf *backupCerr = std::cerr.rdbuf(&newBuffer);
+
+  std::cout << "Test message to cout" << std::endl;
+  std::cerr << "Test message to cerr" << std::endl;
+
+  std::cerr.rdbuf(backupCerr);
+  std::cout.rdbuf(backupCout);
+}
diff --git a/app/src/main/jni/wrappers-example.hpp b/app/src/main/jni/wrappers-example.hpp
new file mode 100644
index 0000000..9bf11e3
--- /dev/null
+++ b/app/src/main/jni/wrappers-example.hpp
@@ -0,0 +1,46 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class net_named_data_nfd_wrappers_Example */
+
+#ifndef _Included_net_named_data_nfd_wrappers_Example
+#define _Included_net_named_data_nfd_wrappers_Example
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     net_named_data_nfd_wrappers_Example
+ * Method:    main
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_net_named_1data_nfd_wrappers_Example_main
+  (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/app/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/ic_launcher.png b/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..359047d
--- /dev/null
+++ b/app/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..71c6d76
--- /dev/null
+++ b/app/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4df1894
--- /dev/null
+++ b/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..63746a1
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">NFD</string>
+</resources>
diff --git a/app/src/main/res/values/strings_activity_nfd_settings.xml b/app/src/main/res/values/strings_activity_nfd_settings.xml
new file mode 100644
index 0000000..2686b04
--- /dev/null
+++ b/app/src/main/res/values/strings_activity_nfd_settings.xml
@@ -0,0 +1,60 @@
+<resources>
+
+    <!-- Strings related to Settings -->
+
+    <!-- Example General settings -->
+    <string name="pref_header_general">General</string>
+
+    <string name="pref_title_social_recommendations">Enable social recommendations</string>
+    <string name="pref_description_social_recommendations">Recommendations for people to contact
+        based on your message history
+    </string>
+
+    <string name="pref_title_display_name">Display name</string>
+    <string name="pref_default_display_name">John Smith</string>
+
+    <string name="pref_title_add_friends_to_messages">Add friends to messages</string>
+    <string-array name="pref_example_list_titles">
+        <item>Always</item>
+        <item>When possible</item>
+        <item>Never</item>
+    </string-array>
+    <string-array name="pref_example_list_values">
+        <item>1</item>
+        <item>0</item>
+        <item>-1</item>
+    </string-array>
+
+    <!-- Example settings for Data & Sync -->
+    <string name="pref_header_data_sync">Data &amp; sync</string>
+
+    <string name="pref_title_sync_frequency">Sync frequency</string>
+    <string-array name="pref_sync_frequency_titles">
+        <item>15 minutes</item>
+        <item>30 minutes</item>
+        <item>1 hour</item>
+        <item>3 hours</item>
+        <item>6 hours</item>
+        <item>Never</item>
+    </string-array>
+    <string-array name="pref_sync_frequency_values">
+        <item>15</item>
+        <item>30</item>
+        <item>60</item>
+        <item>180</item>
+        <item>360</item>
+        <item>-1</item>
+    </string-array>
+
+    <string name="pref_title_system_sync_settings">System sync settings</string>
+
+    <!-- Example settings for Notifications -->
+    <string name="pref_header_notifications">Notifications</string>
+
+    <string name="pref_title_new_message_notifications">New message notifications</string>
+
+    <string name="pref_title_ringtone">Ringtone</string>
+    <string name="pref_ringtone_silent">Silent</string>
+
+    <string name="pref_title_vibrate">Vibrate</string>
+</resources>
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..766ab99
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+    </style>
+
+</resources>
diff --git a/app/src/main/res/xml/pref_data_sync.xml b/app/src/main/res/xml/pref_data_sync.xml
new file mode 100644
index 0000000..ffda831
--- /dev/null
+++ b/app/src/main/res/xml/pref_data_sync.xml
@@ -0,0 +1,21 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
+         dismiss it. -->
+    <!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
+    <ListPreference
+        android:key="sync_frequency"
+        android:title="@string/pref_title_sync_frequency"
+        android:entries="@array/pref_sync_frequency_titles"
+        android:entryValues="@array/pref_sync_frequency_values"
+        android:defaultValue="180"
+        android:negativeButtonText="@null"
+        android:positiveButtonText="@null" />
+
+    <!-- This preference simply launches an intent when selected. Use this UI sparingly, per
+         design guidelines. -->
+    <Preference android:title="@string/pref_title_system_sync_settings">
+        <intent android:action="android.settings.SYNC_SETTINGS" />
+    </Preference>
+
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/pref_general.xml b/app/src/main/res/xml/pref_general.xml
new file mode 100644
index 0000000..c49cbed
--- /dev/null
+++ b/app/src/main/res/xml/pref_general.xml
@@ -0,0 +1,33 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <CheckBoxPreference
+        android:key="example_checkbox"
+        android:title="@string/pref_title_social_recommendations"
+        android:summary="@string/pref_description_social_recommendations"
+        android:defaultValue="true" />
+
+    <!-- NOTE: EditTextPreference accepts EditText attributes. -->
+    <!-- NOTE: EditTextPreference's summary should be set to its value by the activity code. -->
+    <EditTextPreference
+        android:key="example_text"
+        android:title="@string/pref_title_display_name"
+        android:defaultValue="@string/pref_default_display_name"
+        android:selectAllOnFocus="true"
+        android:inputType="textCapWords"
+        android:capitalize="words"
+        android:singleLine="true"
+        android:maxLines="1" />
+
+    <!-- NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
+         dismiss it. -->
+    <!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
+    <ListPreference
+        android:key="example_list"
+        android:title="@string/pref_title_add_friends_to_messages"
+        android:defaultValue="-1"
+        android:entries="@array/pref_example_list_titles"
+        android:entryValues="@array/pref_example_list_values"
+        android:negativeButtonText="@null"
+        android:positiveButtonText="@null" />
+
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/pref_headers.xml b/app/src/main/res/xml/pref_headers.xml
new file mode 100644
index 0000000..f2af3f2
--- /dev/null
+++ b/app/src/main/res/xml/pref_headers.xml
@@ -0,0 +1,17 @@
+<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- These settings headers are only used on tablets. -->
+
+    <header
+        android:fragment="nfd.named_data.net.nfd.NfdSettingsActivity$GeneralPreferenceFragment"
+        android:title="@string/pref_header_general"/>
+
+    <header
+        android:fragment="nfd.named_data.net.nfd.NfdSettingsActivity$NotificationPreferenceFragment"
+        android:title="@string/pref_header_notifications"/>
+
+    <header
+        android:fragment="nfd.named_data.net.nfd.NfdSettingsActivity$DataSyncPreferenceFragment"
+        android:title="@string/pref_header_data_sync"/>
+
+</preference-headers>
diff --git a/app/src/main/res/xml/pref_notification.xml b/app/src/main/res/xml/pref_notification.xml
new file mode 100644
index 0000000..b4b8cae
--- /dev/null
+++ b/app/src/main/res/xml/pref_notification.xml
@@ -0,0 +1,27 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- A 'parent' preference, which enables/disables child preferences (below)
+         when checked/unchecked. -->
+    <CheckBoxPreference
+        android:key="notifications_new_message"
+        android:title="@string/pref_title_new_message_notifications"
+        android:defaultValue="true" />
+
+    <!-- Allows the user to choose a ringtone in the 'notification' category. -->
+    <!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
+    <!-- NOTE: RingtonePreference's summary should be set to its value by the activity code. -->
+    <RingtonePreference
+        android:dependency="notifications_new_message"
+        android:key="notifications_new_message_ringtone"
+        android:title="@string/pref_title_ringtone"
+        android:ringtoneType="notification"
+        android:defaultValue="content://settings/system/notification_sound" />
+
+    <!-- NOTE: This preference will be enabled only when the checkbox above is checked. -->
+    <CheckBoxPreference
+        android:dependency="notifications_new_message"
+        android:key="notifications_new_message_vibrate"
+        android:title="@string/pref_title_vibrate"
+        android:defaultValue="true" />
+
+</PreferenceScreen>