diff --git a/vendor/friendlyelec/apps/ADCDemo/Android.mk b/vendor/friendlyelec/apps/ADCDemo/Android.mk
new file mode 100644
index 00000000000..76ae9353b24
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := ADCDemo 
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/ADCDemo/AndroidManifest.xml b/vendor/friendlyelec/apps/ADCDemo/AndroidManifest.xml
new file mode 100644
index 00000000000..1c5e121fa04
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.friendlyarm.ADCDemo"
+      coreApp="true"
+      android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name="ADCDemoMainActivity"
+                  android:label="@string/ADCReaderActivityTitle">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/ADCDemo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/ADCDemo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/ADCDemo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/ADCDemo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/ADCDemo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/ADCDemo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/ADCDemo/res/drawable/icon.png b/vendor/friendlyelec/apps/ADCDemo/res/drawable/icon.png
new file mode 100644
index 00000000000..d15d4a2f75e
Binary files /dev/null and b/vendor/friendlyelec/apps/ADCDemo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/ADCDemo/res/layout/adc_listview_item.xml b/vendor/friendlyelec/apps/ADCDemo/res/layout/adc_listview_item.xml
new file mode 100644
index 00000000000..93440d052a4
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/res/layout/adc_listview_item.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+>
+
+<TextView 
+    android:id="@+id/listTextView1"
+    android:layout_width="0dip" 
+    android:layout_height="wrap_content" 
+    android:layout_weight="1"
+    android:textSize="18px"
+    android:paddingLeft="20dip"
+/>
+
+<TextView 
+    android:id="@+id/listTextView2"
+    android:layout_width="0dip" 
+    android:layout_height="wrap_content" 
+    android:layout_weight="1"
+    android:textSize="18px"
+    android:gravity="right"
+    android:textColor="#FF7F00"
+    android:paddingRight="20dip"
+/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/ADCDemo/res/layout/adc_main.xml b/vendor/friendlyelec/apps/ADCDemo/res/layout/adc_main.xml
new file mode 100644
index 00000000000..4719410c93f
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/res/layout/adc_main.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+ 
+ <ListView android:id="@+id/listView1" android:layout_width="fill_parent"
+  android:layout_height="fill_parent" />
+ 
+</LinearLayout>
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/ADCDemo/res/values/strings.xml b/vendor/friendlyelec/apps/ADCDemo/res/values/strings.xml
new file mode 100644
index 00000000000..7b7f500b2ea
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">ADC Sample</string>
+    <string name="ADCReaderActivityTitle">ADC Sample</string>
+</resources>
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/ADCDemo/ADC.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/ADCDemo/ADC.java
new file mode 100644
index 00000000000..2542ee1cd8c
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/ADCDemo/ADC.java
@@ -0,0 +1,30 @@
+package com.friendlyarm.ADCDemo;
+
+public class ADC {
+
+    int value = 0;
+    String name = null;
+
+    public ADC(int value, String name) {
+        super();
+        this.value = value;
+        this.name = name;
+    }
+
+    public int getValue() {
+        return value;
+    }
+
+    public void setValue(int value) {
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/ADCDemo/ADCDemoMainActivity.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/ADCDemo/ADCDemoMainActivity.java
new file mode 100644
index 00000000000..ac884cf35dd
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/ADCDemo/ADCDemoMainActivity.java
@@ -0,0 +1,221 @@
+package com.friendlyarm.ADCDemo;
+import java.util.ArrayList;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import java.io.BufferedWriter;
+import android.os.Message;
+import android.os.Handler;
+import android.os.Looper;
+import java.io.*;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.BoardType;
+
+public class ADCDemoMainActivity extends Activity {
+
+    MyCustomAdapter dataAdapter = null;
+    private static final String TAG = "ADCDemo";
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.adc_main);
+        Log.d("ADCDemo", "BoardID: " + mBoardType);
+        timer.schedule(task, 0, 500);
+    }
+
+    static int readNumFromFile(String path, String fileName) {
+        int result = 0;
+        File file = new File(path,fileName);
+        try {
+            BufferedReader br = new BufferedReader(new FileReader(file));
+            String line = br.readLine();
+            br.close();
+
+            try {
+                result = Integer.parseInt(line);
+            } catch(NumberFormatException nfe) {
+               System.out.println("Could not parse " + nfe);
+               result = 0;
+            } 
+        }
+        catch (IOException e) {
+            //You'll need to add proper error handling here
+        }
+        return result;
+    }
+
+    private int mBoardType = HardwareControler.getBoardType();
+    private Timer timer = new Timer();
+    private Handler handler = new Handler() {
+        public void handleMessage(Message msg) {
+
+            // Array list of countries
+            ArrayList<ADC> adcValueList = new ArrayList<ADC>();
+
+            switch (msg.what) {
+            case 1:
+                if (mBoardType > BoardType.RK3399_BASE && mBoardType <= BoardType.RK3399_MAX) {
+                    //path: 
+                    //ADC
+                    //in_voltage0_raw
+                    //in_voltage2_raw
+                    //in_voltage3_raw
+
+                    int[] channels = { 0, 2, 3 };
+                    int[] adc = { 0, 0, 0 };
+                    final String path = "/sys/devices/platform/ff100000.saradc/iio:device0";
+
+                    adc[0] = readNumFromFile(path, "in_voltage0_raw");
+                    adc[1] = readNumFromFile(path, "in_voltage2_raw");
+                    adc[2] = readNumFromFile(path, "in_voltage3_raw");
+
+                    for (int i = 0; i < 3; i++) {
+                        ADC adcObj = new ADC(adc[i], String.format("[AIN%d]",
+                                channels[i]));
+                        adcValueList.add(adcObj);
+                    }
+                } else if (mBoardType > BoardType.RK3568_BASE && mBoardType <= BoardType.RK3568_MAX) {
+                    int channel = 2;
+                    int adc = 0;
+                    final String path = "/sys/devices/platform/fe720000.saradc/iio:device0";
+                    adc = readNumFromFile(path, "in_voltage2_raw");
+                    ADC adcObj = new ADC(adc, String.format("[AIN%d]",channel));
+                    adcValueList.add(adcObj);
+                } else if (mBoardType > BoardType.RK3588_BASE && mBoardType <= BoardType.RK3588_MAX) {
+                    int channel = 2;
+                    int adc = 0;
+                    final String path = "/sys/devices/platform/fec10000.saradc/iio:device0";
+                    adc = readNumFromFile(path, "in_voltage2_raw");
+                    ADC adcObj = new ADC(adc, String.format("[AIN%d]",channel));
+                    adcValueList.add(adcObj);
+                } else if (mBoardType == BoardType.S3C6410_COMMON) {
+                    int[] channels = { 0, 1, 4, 5, 6, 7 };
+                    int[] adc = HardwareControler.readADCWithChannels(channels);
+
+                    for (int i = 0; i < 6; i++) {
+                        ADC adcObj = new ADC(adc[i], String.format("[AIN%d]",
+                                channels[i]));
+                        adcValueList.add(adcObj);
+                    }
+
+                } else if (mBoardType == BoardType.S5PV210_COMMON) {
+                    int[] channels = { 0, 1, 6, 7, 8, 9 };
+                    int[] adc = HardwareControler.readADCWithChannels(channels);
+
+                    for (int i = 0; i < 6; i++) {
+                        ADC adcObj = new ADC(adc[i], String.format("[AIN%d]",
+                                channels[i]));
+                        adcValueList.add(adcObj);
+                    }
+
+                } else if (mBoardType == BoardType.S5P4412_COMMON) {
+                    int[] channels = { 0, 1, 2, 3 };
+                    int[] adc = HardwareControler.readADCWithChannels(channels);
+
+                    for (int i = 0; i < 4; i++) {
+                        ADC adcObj = new ADC(adc[i], String.format("[AIN%d]",
+                                channels[i]));
+                        adcValueList.add(adcObj);
+                    }
+                    
+                } else if (mBoardType == BoardType.Smart4418SDK) {
+                    int[] channels = { 1, 3, 4, 5, 6, 7 };
+                    int[] adc = HardwareControler.readADCWithChannels(channels);
+
+                    for (int i = 0; i < channels.length; i++) {
+                        ADC adcObj = new ADC(adc[i], String.format("[AIN%d]",
+                                channels[i]));
+                        adcValueList.add(adcObj);
+                    }
+                } else {
+                    int adc = HardwareControler.readADCWithChannel(0);
+                    ADC adcObj = new ADC(adc, String.format("[AIN%d]", 0));
+                    adcValueList.add(adcObj);
+                }
+
+                dataAdapter = new MyCustomAdapter(getApplicationContext(),
+                        R.layout.adc_listview_item, adcValueList);
+                ListView listView = (ListView) findViewById(R.id.listView1);
+                listView.setAdapter(dataAdapter);
+
+                break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+    private TimerTask task = new TimerTask() {
+        public void run() {
+            Message message = new Message();
+            message.what = 1;
+            handler.sendMessage(message);
+        }
+    };
+    
+
+    private class MyCustomAdapter extends ArrayAdapter<ADC> {
+
+        private ArrayList<ADC> adcValueList;
+
+        public MyCustomAdapter(Context context, int textViewResourceId,
+                ArrayList<ADC> adcValueList) {
+            super(context, textViewResourceId, adcValueList);
+            this.adcValueList = new ArrayList<ADC>();
+            this.adcValueList.addAll(adcValueList);
+        }
+
+        private class ViewHolder {
+            TextView nameTextView;
+            TextView valueTextView;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+
+            ViewHolder holder = null;
+            Log.v("ConvertView", String.valueOf(position));
+
+            if (convertView == null) {
+                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                convertView = vi.inflate(R.layout.adc_listview_item, null);
+
+                holder = new ViewHolder();
+                
+                holder.nameTextView = (TextView) convertView
+                        .findViewById(R.id.listTextView1);
+                
+                holder.valueTextView = (TextView) convertView
+                        .findViewById(R.id.listTextView2);
+                
+                convertView.setTag(holder);
+
+            } else {
+                holder = (ViewHolder) convertView.getTag();
+            }
+
+            ADC adcObj = adcValueList.get(position);
+            if (holder.nameTextView != null) {
+                holder.nameTextView.setText(adcObj.getName());
+            }
+            if (holder.valueTextView != null) {
+                holder.valueTextView.setText(String.valueOf(adcObj.getValue()));
+            }
+            
+            return convertView;
+
+        }
+
+    }
+}
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/ADCDemo/sync.sh b/vendor/friendlyelec/apps/ADCDemo/sync.sh
new file mode 100755
index 00000000000..70b560332f5
--- /dev/null
+++ b/vendor/friendlyelec/apps/ADCDemo/sync.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+adb disable-verity; adb root; adb remount; adb sync; adb reboot;
diff --git a/vendor/friendlyelec/apps/BoardConfigPartial.mk b/vendor/friendlyelec/apps/BoardConfigPartial.mk
new file mode 100644
index 00000000000..932548e19c6
--- /dev/null
+++ b/vendor/friendlyelec/apps/BoardConfigPartial.mk
@@ -0,0 +1,15 @@
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/Android.mk b/vendor/friendlyelec/apps/GPIO_LED_Demo/Android.mk
new file mode 100644
index 00000000000..786b07b09cc
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := GPIO_LED_Demo
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/AndroidManifest.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/AndroidManifest.xml
new file mode 100644
index 00000000000..a62ffa1d3cf
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.friendlyarm.GPIODemo"
+      coreApp="true"
+      android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name="GPIODemoMainActivity"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/GPIO_LED_Demo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/GPIO_LED_Demo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/GPIO_LED_Demo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/GPIO_LED_Demo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/gray_thumb.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/gray_thumb.xml
new file mode 100644
index 00000000000..75d4a39e224
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/gray_thumb.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <!-- 高度40 -->
+    <size android:height="40dp" android:width="40dp"/>
+    <!-- 圆角弧度 20 -->
+	<corners android:radius="20dp"/>
+    
+	
+	<!-- 变化率 -->
+    <gradient
+        android:endColor="#eeeeee"
+        android:startColor="#eeeeee" />
+    
+    <stroke android:width="1dp"
+        android:color="#666666"/>
+
+</shape>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/gray_track.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/gray_track.xml
new file mode 100644
index 00000000000..23602e8a088
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/gray_track.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <!-- 高度30   此处设置宽度无效-->
+    <size android:height="20dp"/>
+    <!-- 圆角弧度 15 -->
+	<corners android:radius="10dp"/>
+    
+	
+	<!-- 变化率  定义从左到右的颜色不变 -->
+    <gradient
+        android:endColor="#888888"
+        android:startColor="#888888" />
+
+</shape>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/green_thumb.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/green_thumb.xml
new file mode 100644
index 00000000000..a340b220b80
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/green_thumb.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <!-- 高度40 -->
+    <size android:height="40dp" android:width="40dp"/>
+    <!-- 圆角弧度 20 -->
+	<corners android:radius="20dp"/>
+    
+	
+	<!-- 变化率 -->
+    <gradient
+        android:endColor="#eeeeee"
+        android:startColor="#eeeeee" />
+    
+    <stroke android:width="1dp"
+        android:color="#33da33"/>
+
+</shape>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/green_track.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/green_track.xml
new file mode 100644
index 00000000000..a0a64ab23c7
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/green_track.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <!-- 高度40 -->
+    <size android:height="20dp"/>
+    <!-- 圆角弧度 20 -->
+	<corners android:radius="10dp"/>
+	<!-- 变化率 -->
+    <gradient
+        android:endColor="#33da33"
+        android:startColor="#33da33" />
+
+
+
+</shape>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/icon.png b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/icon.png
new file mode 100644
index 00000000000..54ad39d63ef
Binary files /dev/null and b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/red_thumb.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/red_thumb.xml
new file mode 100644
index 00000000000..e4433a6202c
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/red_thumb.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle" >
+
+    <!-- 高度40 -->
+    <size android:height="40dp" android:width="40dp"/>
+    <!-- 圆角弧度 20 -->
+	<corners android:radius="20dp"/>
+    
+	
+	<!-- 变化率 -->
+    <gradient
+        android:endColor="#da3333"
+        android:startColor="#da3333" />
+    
+    <stroke android:width="1dp"
+        android:color="#da3333"/>
+
+</shape>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/thumb.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/thumb.xml
new file mode 100644
index 00000000000..ade39dbda4c
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/thumb.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 按钮的选择器,可以设置按钮在不同状态下的时候,按钮不同的颜色 -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    
+<item android:state_checked="true"  android:drawable="@drawable/green_thumb" />
+<item                               android:drawable="@drawable/gray_thumb" />
+</selector>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/track.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/track.xml
new file mode 100644
index 00000000000..1750e8c2749
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/drawable/track.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 底层下滑条的样式选择器,可控制Switch在不同状态下,底下下滑条的颜色 -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+<item android:state_checked="true"  android:drawable="@drawable/green_track" />
+<item                               android:drawable="@drawable/gray_track" />
+
+</selector>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/layout/gpiodemo_main.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/layout/gpiodemo_main.xml
new file mode 100644
index 00000000000..74965fa0836
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/layout/gpiodemo_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+ 
+    <ListView android:id="@+id/listView1" android:layout_width="fill_parent" 
+	android:layout_height="0dp" android:layout_weight="1" />
+
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:orientation="vertical"
+        android:gravity="bottom"
+        android:layout_alignParentBottom="true"
+        android:layout_marginTop="20dp">
+	<Button
+	    android:onClick="onMoreSamplesPressed"
+            android:id="@+id/btn_morebutton"
+            android:text="@string/moreSamplesButtonText"
+            android:layout_height="wrap_content"
+	    android:layout_width="fill_parent">
+        </Button>
+    </LinearLayout>
+</LinearLayout>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/layout/listview_item.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/layout/listview_item.xml
new file mode 100644
index 00000000000..92b2b07a196
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/layout/listview_item.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:padding="6dip" >
+
+    <Switch
+        android:id="@+id/pin_switch"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:switchMinWidth="20dp"
+        android:textOn="High"
+        android:textOff="Low"
+        android:textSize="20sp"
+        android:showText="true"
+        android:thumb="@drawable/thumb"
+        android:track="@drawable/track" />
+        
+</RelativeLayout>
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/res/values/strings.xml b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/values/strings.xml
new file mode 100644
index 00000000000..62fd9c050bb
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">GPIO Sample</string>
+    <string name="MainActivityTitle">GPIO Sample</string>
+    <string name="ledtext">LED</string>
+    <string name="moreSamplesButtonText">More samples? \nClick here</string>
+</resources>
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/GPIODemo/GPIODemoMainActivity.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/GPIODemo/GPIODemoMainActivity.java
new file mode 100644
index 00000000000..d494a48b4b5
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/GPIODemo/GPIODemoMainActivity.java
@@ -0,0 +1,314 @@
+package com.friendlyarm.GPIODemo;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.net.Uri;
+import android.content.Intent;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Switch;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.CompoundButton;
+import android.widget.AdapterView.OnItemClickListener;
+import java.util.List;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.BoardType;
+
+public class GPIODemoMainActivity extends Activity {
+    private static final String TAG = "GPIODemo";
+    private Timer timer = new Timer();
+    private int step = 0; 
+    private Map<String, Integer> demoGPIOPins = new HashMap<String, Integer>();  
+    
+    static int STEP_INIT_GPIO_DIRECTION = 1;
+    static int STEP_INIT_VIEW = 2;
+    
+    @Override
+        public void onDestroy() {
+            timer.cancel();
+            super.onDestroy();
+        }
+
+    public void onMoreSamplesPressed(View view) {
+        Uri uri = Uri.parse("http://wiki.friendlyelec.com/wiki/index.php/FriendlyThings_for_Rockchip");
+        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+        startActivity(intent); 
+    }
+
+    private void displayListView() {
+        Log.d(TAG, "displayListView");
+
+        ArrayList<GPIOPin> pinList = new ArrayList<GPIOPin>();
+        List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(demoGPIOPins.entrySet());
+        Collections.sort(list,new Comparator<Map.Entry<String,Integer>>() {
+            public int compare(Map.Entry<String, Integer> o1,
+                    Map.Entry<String, Integer> o2) {
+                return o1.getKey().compareTo(o2.getKey());
+            }
+        });
+
+        Log.d(TAG, "{{{{ DUMP GPIO Values");
+        for(Map.Entry<String,Integer> entry:list){
+            int value = HardwareControler.getGPIOValue(entry.getValue());
+            if (value == GPIOEnum.HIGH) {
+                Log.d(TAG, entry.getKey() + "(" + String.valueOf(entry.getValue()) + ") = HIGH");
+            } else {
+                Log.d(TAG, entry.getKey() + "(" + String.valueOf(entry.getValue()) + ") = LOW");
+            }
+            GPIOPin pin = new GPIOPin(entry.getValue(), entry.getKey(), value);
+            pinList.add(pin);
+        } 
+        Log.d(TAG, "}}}}");
+
+        dataAdapter = new MyCustomAdapter(this, R.layout.listview_item,
+                pinList);
+        ListView listView = (ListView) findViewById(R.id.listView1);
+        listView.setAdapter(dataAdapter);
+    }
+
+    @SuppressLint("HandlerLeak")
+    private Handler handler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case 1:
+                    timer.cancel();
+                    displayListView();
+                    break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+
+    private TimerTask init_task = new TimerTask() {
+        public void run() {
+            Log.d(TAG, "init_task " + step);
+            if (step == STEP_INIT_GPIO_DIRECTION) {
+                for (Integer sysPinNum: demoGPIOPins.values()) {
+                    int currentDirection = HardwareControler.getGPIODirection(sysPinNum);
+                    Log.v(TAG, String.format("currentDirection(%d) == %d", sysPinNum, currentDirection));
+                    if (currentDirection < 0 || currentDirection != GPIOEnum.OUT) {
+                        if (HardwareControler.setGPIODirection(sysPinNum, GPIOEnum.OUT) != 0) {
+                            Log.v(TAG, String.format("setGPIODirection(%d) to OUT failed", sysPinNum));
+                        } else {
+                            Log.v(TAG, String.format("setGPIODirection(%d) to OUT OK", sysPinNum));
+                        }
+                    }
+                }
+                step ++;
+            } else if (step == STEP_INIT_VIEW) {
+                Message message = new Message();
+                message.what = 1;
+                handler.sendMessage(message);
+            }
+
+        }
+    }; 
+    //////////////////////////////////////
+
+    MyCustomAdapter dataAdapter = null;
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.gpiodemo_main);
+        setTitle("GPIO Demo");
+
+        int boardType = HardwareControler.getBoardType();
+        if (boardType == BoardType.Smart4418SDK) {
+            demoGPIOPins.put("GPIOC9", 73);
+            demoGPIOPins.put("GPIOC10", 74);
+            demoGPIOPins.put("GPIOC11", 75);
+            demoGPIOPins.put("GPIOC12", 76);
+        } else if (boardType == BoardType.NanoPC_T2
+                || boardType == BoardType.NanoPC_T3
+                || boardType == BoardType.NanoPC_T3T
+                ) {
+            demoGPIOPins.put("Pin17", 68);
+            demoGPIOPins.put("Pin18", 71);
+            demoGPIOPins.put("Pin19", 72);
+            demoGPIOPins.put("Pin20", 88);
+            demoGPIOPins.put("Pin21", 92);
+            demoGPIOPins.put("Pin22", 58);
+        } else if (boardType == BoardType.NanoPC_T4) {
+            demoGPIOPins.put("Pin11", 33);
+            demoGPIOPins.put("Pin12", 50);
+            demoGPIOPins.put("Pin15", 36);
+            demoGPIOPins.put("Pin16", 54);
+            demoGPIOPins.put("Pin18", 55);
+            demoGPIOPins.put("Pin22", 56);
+            demoGPIOPins.put("Pin37", 96);
+            demoGPIOPins.put("Pin38", 125);
+            demoGPIOPins.put("Pin40", 126);
+        } else if (boardType == BoardType.NanoPi_M4 || boardType == BoardType.NanoPi_M4v2 || boardType == BoardType.NanoPi_M4B || boardType == BoardType.NanoPi_NEO4 || boardType == BoardType.NanoPi_NEO4v2) {
+            demoGPIOPins.put("Pin11", 33);
+            demoGPIOPins.put("Pin12", 50);
+            demoGPIOPins.put("Pin15", 36);
+            demoGPIOPins.put("Pin16", 54);
+            demoGPIOPins.put("Pin18", 55);
+            demoGPIOPins.put("Pin22", 56);
+        } else if (boardType == BoardType.SOM_RK3399 || boardType == BoardType.SOM_RK3399v2) {
+            demoGPIOPins.put("Pin7", 41);
+            demoGPIOPins.put("Pin9", 42);
+        } else if (boardType == BoardType.NanoPC_T6) {
+            demoGPIOPins.put("Pin07", 106);  // GPIO3_B2
+            demoGPIOPins.put("Pin12", 111);  // GPIO3_B7
+            demoGPIOPins.put("Pin15",  39);  // GPIO1_A7
+            demoGPIOPins.put("Pin16", 107);  // GPIO3_B3
+            demoGPIOPins.put("Pin18", 108);  // GPIO3_B4
+            demoGPIOPins.put("Pin26",  40);  // GPIO1_B0
+            //spi0 (m2)
+            //demoGPIOPins.put("Pin19",  42);  // GPIO1_B2
+            //demoGPIOPins.put("Pin21",  41);  // GPIO1_B1
+            //demoGPIOPins.put("Pin22",  45);  // GPIO1_B5
+            //demoGPIOPins.put("Pin23",  43);  // GPIO1_B3
+            //demoGPIOPins.put("Pin24",  44);  // GPIO1_B4
+        } else if (boardType == BoardType.NanoPi_R6C) {
+            //i2s1 (m0)
+            demoGPIOPins.put("Pin07", 128);  // GPIO4_A0
+            demoGPIOPins.put("Pin11", 129);  // GPIO4_A1
+            demoGPIOPins.put("Pin13", 130);  // GPIO4_A2
+            demoGPIOPins.put("Pin15", 133);  // GPIO4_A5
+            demoGPIOPins.put("Pin16", 134);  // GPIO4_A6
+            demoGPIOPins.put("Pin18", 137);  // GPIO4_B1
+            demoGPIOPins.put("Pin22", 138);  // GPIO4_B2
+        } else if (boardType == BoardType.NanoPi_R6S) {
+            //spi0
+            demoGPIOPins.put("Pin03",  43);  // GPIO1_B3
+            demoGPIOPins.put("Pin05",  41);  // GPIO1_B1
+            demoGPIOPins.put("Pin06",  44);  // GPIO1_B4
+            demoGPIOPins.put("Pin07",  42);  // GPIO1_B2
+            //uart1 (m1)
+            demoGPIOPins.put("Pin09",  47);  // GPIO1_B7
+            demoGPIOPins.put("Pin10",  46);  // GPIO1_B6
+            //uart5 (m1)
+            //demoGPIOPins.put("Pin11", 116);  // GPIO3_C4
+            //demoGPIOPins.put("Pin12", 117);  // GPIO3_C5
+        } else if (boardType == BoardType.NanoPi_R5S || boardType == BoardType.NanoPi_R5S_LTS) {
+            //spi1
+            demoGPIOPins.put("Pin03", 115);  // GPIO3_C3
+            demoGPIOPins.put("Pin05", 114);  // GPIO3_C2
+            demoGPIOPins.put("Pin06",  97);  // GPIO3_A1
+            demoGPIOPins.put("Pin07", 113);  // GPIO3_C1
+            //uart9 (m1)
+            //demoGPIOPins.put("Pin09", 149);  // GPIO4_C5
+            //demoGPIOPins.put("Pin10", 150);  // GPIO4_C6
+            //uart7 (m1)
+            demoGPIOPins.put("Pin11", 116);  // GPIO3_C4
+            demoGPIOPins.put("Pin12", 117);  // GPIO3_C5
+        } else if (android.os.Build.VERSION.RELEASE.contains("4.1.2")) {
+            demoGPIOPins.put("LED 1", 281);
+            demoGPIOPins.put("LED 2", 282);
+            demoGPIOPins.put("LED 3", 283);
+            demoGPIOPins.put("LED 4", 284);
+        }
+
+        if (demoGPIOPins.size() == 0) {
+            Toast.makeText(this, String.format("Not found any GPIO pin."),
+                    Toast.LENGTH_SHORT).show();
+        } else {
+            // export all pins
+            for (Integer sysPinNum: demoGPIOPins.values()) {
+                if (HardwareControler.exportGPIOPin(sysPinNum) != 0) {
+                    Toast.makeText(this, String.format("exportGPIOPin(%d) failed!", sysPinNum),
+                            Toast.LENGTH_SHORT).show();
+                }
+            }
+            step = STEP_INIT_GPIO_DIRECTION;
+            timer.schedule(init_task, 300, 200);
+        }
+    }
+
+    private class MyCustomAdapter extends ArrayAdapter<GPIOPin> {
+        private ArrayList<GPIOPin> pinList;
+        public MyCustomAdapter(Context context, int resourceId,
+                ArrayList<GPIOPin> pinList) {
+            super(context, resourceId, pinList);
+            this.pinList = new ArrayList<GPIOPin>();
+            this.pinList.addAll(pinList);
+        }
+
+        private class ViewHolder {
+            Switch switchView;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            ViewHolder viewHolder = null;
+            if (convertView == null) {
+                LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                convertView = vi.inflate(R.layout.listview_item, null);
+                viewHolder = new ViewHolder();
+                viewHolder.switchView = (Switch) convertView.findViewById(R.id.pin_switch);
+                convertView.setTag(viewHolder);
+            } else {
+                viewHolder = (ViewHolder) convertView.getTag();
+            }
+
+            // reinit switchView
+            GPIOPin pin = pinList.get(position);
+            viewHolder.switchView.setText(pin.getName());
+            viewHolder.switchView.setChecked(pin.getValue() == GPIOEnum.HIGH);
+            viewHolder.switchView.setTag(pin);
+            /*
+            viewHolder.switchView.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                    if (!buttonView.isPressed()) {
+                        return;
+                    }
+                    Switch sw = (Switch) buttonView;
+                    GPIOPin newPinData = (GPIOPin) sw.getTag();
+                    if (isChecked) {
+                        newPinData.setValue(GPIOEnum.HIGH);
+                    } else {
+                        newPinData.setValue(GPIOEnum.LOW);
+                    }
+                    if (HardwareControler.setGPIOValue(newPinData.getSysPinNum(),newPinData.getValue()) == 0) {
+                        Log.v(TAG, String.format("setGPIOValue" + newPinData.getName() + " (%d) OK", newPinData.getSysPinNum()));
+                    } else {
+                        Log.v(TAG, String.format("setGPIOValue" + newPinData.getName() + " (%d) Failed", newPinData.getSysPinNum()));
+                    }
+                    pinList.set(position, newPinData);
+                }
+            });
+            */
+            viewHolder.switchView.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View v) {
+                    // you might keep a reference to the CheckBox to avoid this class cast
+                    Switch sw = (Switch) v;
+                    GPIOPin newPinData = (GPIOPin) sw.getTag();
+                    if (sw.isChecked()) {
+                        newPinData.setValue(GPIOEnum.HIGH);
+                    } else {
+                        newPinData.setValue(GPIOEnum.LOW);
+                    }
+                    if (HardwareControler.setGPIOValue(newPinData.getSysPinNum(),newPinData.getValue()) == 0) {
+                        Log.v(TAG, String.format("setGPIOValue" + newPinData.getName() + " (%d) OK", newPinData.getSysPinNum()));
+                    } else {
+                        Log.v(TAG, String.format("setGPIOValue" + newPinData.getName() + " (%d) Failed", newPinData.getSysPinNum()));
+                    }
+                    pinList.set(position, newPinData);
+                }
+            });
+            return convertView;
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/GPIODemo/GPIOPin.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/GPIODemo/GPIOPin.java
new file mode 100644
index 00000000000..76b1fac848e
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/GPIODemo/GPIOPin.java
@@ -0,0 +1,34 @@
+package com.friendlyarm.GPIODemo;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+
+public class GPIOPin {
+    private int sysPinNum = 0;
+    private String name = null;
+    private int value = GPIOEnum.LOW;
+     
+    public GPIOPin(int sysPinNum, String name, int value) {
+        super();
+        this.sysPinNum = sysPinNum;
+        this.name = name;
+        this.value = value;
+    }
+    public int getSysPinNum() {
+        return sysPinNum;
+    }
+    public void setSysPinNum(int sysPinNum) {
+        this.sysPinNum = sysPinNum;
+    }
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    
+    public int getValue() {
+        return this.value;
+    }
+    public void setValue(int newValue) {
+        this.value = newValue;
+    }
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/GPIO_LED_Demo/sync.sh b/vendor/friendlyelec/apps/GPIO_LED_Demo/sync.sh
new file mode 100755
index 00000000000..1603f29f738
--- /dev/null
+++ b/vendor/friendlyelec/apps/GPIO_LED_Demo/sync.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+adb root
+adb remount
+adb sync
+adb reboot
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/.settings/org.eclipse.jdt.core.prefs b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..b080d2ddc88
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/Android.mk b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/Android.mk
new file mode 100644
index 00000000000..3e9f8d62320
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := LCD1602 
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/AndroidManifest.xml b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/AndroidManifest.xml
new file mode 100644
index 00000000000..dfd172d1e79
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.friendlyarm.LCD1602Demo"
+      coreApp="true"
+      android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        <activity android:name="MainActivity"
+                  android:label="@string/MainActivityTitle">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/drawable/icon.png b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/drawable/icon.png
new file mode 100644
index 00000000000..d6c9bfe9b3f
Binary files /dev/null and b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/layout/mainactivity.xml b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/layout/mainactivity.xml
new file mode 100644
index 00000000000..51cf7a269f9
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/layout/mainactivity.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:orientation="vertical" android:layout_width="fill_parent"
+	android:layout_height="fill_parent">
+	
+	<TextView android:id="@+id/statusView" android:layout_width="fill_parent"
+		android:layout_height="wrap_content" android:textSize="16px" android:gravity="center"/>
+	
+	<EditText android:id="@+id/writeEditor" android:layout_width="fill_parent"
+		android:layout_height="100dip" android:singleLine="false" android:editable="true"
+		 android:gravity="top" android:textSize="14px" />
+
+	<Button android:id="@+id/sendButton" android:layout_width="fill_parent"
+		android:layout_height="wrap_content" android:text="@string/sendButtonText">
+	</Button>
+</LinearLayout>
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/values/strings.xml b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/values/strings.xml
new file mode 100644
index 00000000000..0b0a7cfd66b
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">I2C-LCD1602 Sample</string>
+    <string name="MainActivityTitle">I2C-LCD1602 Sample</string>
+    <string name="sendButtonText">Apply</string>
+</resources>
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/LCD1602Demo/MainActivity.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/LCD1602Demo/MainActivity.java
new file mode 100644
index 00000000000..928e3c817d5
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/LCD1602Demo/MainActivity.java
@@ -0,0 +1,228 @@
+package com.friendlyarm.LCD1602Demo;
+
+import android.app.Activity;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.os.Bundle;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+import com.friendlyarm.FriendlyThings.BoardType;
+import com.friendlyarm.LCD1602Demo.R;
+/* for thread */
+import android.os.Message;
+import android.os.Handler;
+import android.os.Looper;
+
+public class MainActivity extends Activity implements OnClickListener {
+    EditText writeEditor;
+    TextView statusView;
+    private Handler messageHandler;
+    Thread writeThread = null;
+    int devFD = -1;
+    final int MAX_LINE_SIZE = 16;
+
+    private class MessageHandler extends Handler {
+        public MessageHandler(Looper looper) {
+            super(looper);
+        }
+        
+        @Override
+        public void handleMessage(Message msg) {
+            String result = (String) msg.obj;
+            if (result.equals("ERROR")) {
+                statusView.setText("Status: Error");
+            } else if (result.equals("DONE")) {
+                statusView.setText("Status: Done");
+            } else {
+                statusView.setText("Status: Processing");
+            }
+        }
+    }
+    
+    @Override
+    public void onDestroy() {
+        if (devFD >= 0) {
+            HardwareControler.close(devFD);
+            devFD = -1;
+        }
+        super.onDestroy();
+    }
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.mainactivity);
+        
+        writeEditor = (EditText) findViewById(R.id.writeEditor);
+        writeEditor.setText("Don't give up and don't give in.");
+        
+        statusView = (TextView) findViewById(R.id.statusView);
+        Button writeButton = (Button)findViewById(R.id.sendButton);
+        writeButton.setOnClickListener(this);
+        
+        Looper looper = Looper.myLooper();
+        messageHandler = new MessageHandler(looper);
+        String i2cDevName = "/dev/i2c-0";
+        int boardType = HardwareControler.getBoardType();
+        if (mBoardType > BoardType.RK3399_BASE && mBoardType <= BoardType.RK3399_MAX) {
+             i2cDevName = "/dev/i2c-2";
+        }
+        devFD = HardwareControler.open(i2cDevName, FileCtlEnum.O_RDWR);
+        if (devFD < 0) {
+            statusView.setText("Fail to open " + i2cDevName + " device.");
+            writeEditor.setEnabled(false);
+            writeButton.setEnabled(false);
+        } else {
+            // for LCD1602 (chip: pcf8574)
+            if (HardwareControler.setI2CSlave(devFD, 0x27) < 0) {
+                statusView.setText("Fail to set " + i2cDevName + " slave.");
+                writeEditor.setEnabled(false);
+                writeButton.setEnabled(false);
+            } else {
+                statusView.setText("Status: Ready");
+            }
+        }
+    }
+
+    private int LCD1602Init() throws InterruptedException {
+        Thread.sleep(0,1000*15);
+        if (PCF8574.writeCmd4(devFD, (byte)(0x03 << 4)) == -1) {
+            return -1;
+        }
+        Thread.sleep(0,100*41);
+        if (PCF8574.writeCmd4(devFD, (byte)(0x03 << 4)) == -1) {
+            return -1;
+        }
+        Thread.sleep(0,100);
+        if (PCF8574.writeCmd4(devFD, (byte)(0x03 << 4)) == -1) { 
+            return -1;
+        }
+        if (PCF8574.writeCmd4(devFD, (byte)(0x02 << 4)) == -1) {
+            return -1;
+        }    
+        if (PCF8574.writeCmd8(devFD, (byte)(0x28)) == -1) {
+            return -1;
+        }
+        if (PCF8574.writeCmd8(devFD, (byte)(0x0c)) == -1) {
+            return -1;
+        }
+        Thread.sleep(0,2000);
+        if (PCF8574.writeCmd8(devFD, (byte)(0x06)) == -1) {
+            return -1;
+        }
+        if (PCF8574.writeCmd8(devFD, (byte)(0x02)) == -1) {
+            return -1;
+        }
+        Thread.sleep(0,2000);
+        return 0;
+    }
+    
+    private int LCD1602DispStr(byte x, byte y, String str) throws InterruptedException
+    {
+        byte addr;
+        addr = (byte)(((y + 2) * 0x40) + x);
+
+        if (PCF8574.writeCmd8(devFD, addr) == -1) {
+            return -1;
+        }
+        byte[] strBytes = str.getBytes();
+        byte b;
+
+        for (int i = 0; i < strBytes.length && i<MAX_LINE_SIZE; i++) {
+            b = strBytes[i];
+            if (PCF8574.writeData8(devFD, b) == -1) {
+                return -1;
+            }
+        }
+        return 0;
+    }
+
+    private int LCD1602DispLines(String line1, String line2) throws InterruptedException {
+        int ret = LCD1602DispStr((byte)0, (byte)0, line1);
+        if (ret != -1 && line2.length() > 0) {
+            ret = LCD1602DispStr((byte)0, (byte)1, line2);
+        }
+        return ret;
+    }
+    
+    private int LCD1602Clear() throws InterruptedException {
+        if (PCF8574.writeCmd8(devFD, (byte)0x01) == -1) { 
+             return -1;
+        }
+        return 0;
+    }
+    
+    private boolean lcd1602Inited = false;
+    private void sendMessage(String msg) {
+        Message message = Message.obtain();
+        message.obj = msg;
+        messageHandler.sendMessage(message);
+    }
+    private void startWriteEEPROMThread(final String displayText) {
+        statusView.setText("Status: Processing");
+        new Thread() {
+            @Override
+            public void run() {
+                if (!lcd1602Inited) {
+                    try  {  
+                        if (LCD1602Init() == 0) {
+                            lcd1602Inited = true;
+                        }
+                    } catch  (Exception e) {  
+                        sendMessage("ERROR");
+                        return ;
+                    }
+                }
+
+                if (!lcd1602Inited) {
+                    sendMessage("ERROR");
+                    return ;
+                }
+                
+                try {
+                    LCD1602Clear();
+                    Thread.sleep(100, 0);
+                    
+                    String line1 = "";
+                    String line2 = "";
+                    for (int i=0; i<displayText.length(); i++) {
+                        if (line1.length() >= MAX_LINE_SIZE) {
+                            if (line2.length() >= MAX_LINE_SIZE) {
+                                break;
+                            } else {
+                                line2 = line2 + displayText.charAt(i);
+                            }
+                        } else {
+                            line1 = line1 + displayText.charAt(i);
+                        }
+                    }
+                    
+                    if (LCD1602DispLines(line1, line2) == -1) {
+                        sendMessage("ERROR");
+                        return ;
+                    }
+                } catch (Exception e) {
+                    sendMessage("ERROR");
+                    return ;
+                }
+                sendMessage("DONE");
+            }
+
+        }.start();
+    }
+    
+    public void onClick(View v) {
+        switch (v.getId()) {
+        case R.id.sendButton:
+            startWriteEEPROMThread(writeEditor.getText().toString());
+            break;
+        default:
+            break;
+        }
+    }
+    
+}
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/LCD1602Demo/PCF8574.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/LCD1602Demo/PCF8574.java
new file mode 100644
index 00000000000..1aeac9569aa
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/LCD1602Demo/PCF8574.java
@@ -0,0 +1,64 @@
+package com.friendlyarm.LCD1602Demo;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+
+public class PCF8574 {
+    static final byte RS = 0x01;
+    static final byte En = 0x04;
+    static final byte BL = 0x08;
+    
+    static int pulseEnable(int devFD, byte data) throws InterruptedException {
+        if (HardwareControler.I2CWriteByte(devFD, (byte)(data | En), 1) != 0) {
+            return -1;
+        }
+        if (HardwareControler.I2CWriteByte(devFD, (byte)(data & ~En), 0) != 0) {
+            return -1;
+        }
+        return 0;
+    }
+    
+    static int writeCmd4(int devFD, byte command) throws InterruptedException {
+        if (HardwareControler.I2CWriteByte(devFD, (byte)(command | BL), 0) != 0) {
+            return -1;
+        }
+        if (pulseEnable(devFD, (byte)(command | BL)) != 0) {
+            return -1;
+        }
+        return 0;
+    }
+
+    static int writeCmd8(int devFD, byte command) throws InterruptedException {
+        byte command_H = (byte) (command & 0xf0);
+        byte command_L = (byte) ((command << 4) & 0xf0);
+        if (writeCmd4(devFD, command_H) == -1) {
+            return -1;
+        }
+
+        if (writeCmd4(devFD, command_L) == -1) {
+            return -1;
+        }
+        return 0;
+    }
+
+    static int writeData4(int devFD, byte data) throws InterruptedException {
+        if (HardwareControler.I2CWriteByte(devFD, (byte)(data | RS | BL), 0) != 0) {
+            return -1;
+        }
+        if (pulseEnable(devFD, (byte)(data | RS | BL)) == -1) {
+            return -1;
+        }
+        return 0;
+    }
+
+    static int writeData8(int devFD, byte data) throws InterruptedException {
+        byte data_H = (byte) (data & 0xf0);
+        byte data_L = (byte) ((data << 4) & 0xf0);
+        if (writeData4(devFD, data_H) == -1) {
+            return -1;
+        }
+        if (writeData4(devFD, data_L) == -1) {
+            return -1;
+        }
+        return 0;
+    }
+}
diff --git a/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/I2C_LCD1602_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/Android.mk b/vendor/friendlyelec/apps/PWMDemo/Android.mk
new file mode 100644
index 00000000000..3b0f011fb3c
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := PWMDemo
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/PWMDemo/AndroidManifest.xml b/vendor/friendlyelec/apps/PWMDemo/AndroidManifest.xml
new file mode 100644
index 00000000000..d316e78514f
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.friendlyarm.PWMDemo"
+      coreApp="true"
+      android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        
+       <activity android:name="PWMTestingActivity"
+                  android:label="@string/PWMTestingActivityTitle">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+	
+
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/PWMDemo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/PWMDemo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/PWMDemo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/PWMDemo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/PWMDemo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/PWMDemo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/PWMDemo/res/drawable/icon.png b/vendor/friendlyelec/apps/PWMDemo/res/drawable/icon.png
new file mode 100644
index 00000000000..fcce595b1c9
Binary files /dev/null and b/vendor/friendlyelec/apps/PWMDemo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/PWMDemo/res/layout/pwmtestingactivity.xml b/vendor/friendlyelec/apps/PWMDemo/res/layout/pwmtestingactivity.xml
new file mode 100644
index 00000000000..0c09f1036aa
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/res/layout/pwmtestingactivity.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <CheckBox
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/txtEnable"
+        android:id="@+id/checkbox_enable"
+        android:checked="true"
+        android:onClick="onCheckboxEnableClicked"/>
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/txtFreq"
+        android:id="@+id/text_freq"
+        android:layout_marginTop="10dp"/>
+    <SeekBar
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/seekbar_pwm_freq"
+        android:progress="7"
+        android:min="0"
+        android:max="11"
+        android:longClickable="true"/>
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/txtDutyCycle"
+        android:id="@+id/text_cycle"
+        android:layout_marginTop="10dp"/>
+    <SeekBar
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:progress="50"
+        android:max="100"
+        android:id="@+id/seekbar_cycle"/>
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/txtApply"
+        android:id="@+id/button_apply"
+        android:layout_marginTop="40dp"
+        android:onClick="onApplyPressed"/>
+</LinearLayout>
diff --git a/vendor/friendlyelec/apps/PWMDemo/res/values/strings.xml b/vendor/friendlyelec/apps/PWMDemo/res/values/strings.xml
new file mode 100644
index 00000000000..203de8cffeb
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/res/values/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">PWM Sample</string>
+    <string name="PWMTestingActivityTitle">PWM Sample</string>
+    <string name="txtEnable">Enable</string>
+    <string name="txtFreq">Freq</string>
+    <string name="txtDutyCycle">Duty cycle</string>
+    <string name="txtApply">Apply</string>
+</resources>
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/PWMDemo/PWMTestingActivity.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/PWMDemo/PWMTestingActivity.java
new file mode 100644
index 00000000000..8a661024b04
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/PWMDemo/PWMTestingActivity.java
@@ -0,0 +1,223 @@
+package com.friendlyarm.PWMDemo;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.BoardType;
+import com.friendlyarm.PWMDemo.R;
+import com.friendlyarm.Utils.CommonFuncs;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.widget.TextView;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.view.View.OnClickListener;
+import android.widget.CheckBox;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Toast;
+import java.io.BufferedWriter;
+import android.os.Message;
+import android.os.Handler;
+import android.os.Looper;
+import java.io.*;
+
+public class PWMTestingActivity extends Activity {
+    /** Called when the activity is first created. */
+    private int mBoardType;
+    private static final String TAG = "PWMDemo";
+
+    private boolean mEnable = true;
+    private TextView mTextViewFreq, mTextViewCycle;
+    private SeekBar mSeekBarFreq, mSeekBarCycle;
+    private CheckBox mCheckBoxEnable;
+    private Button mApplyButton;
+    private String pwmChip;
+    MessageHandler mMessageHandler;
+    private String[] mFreqTexts = { "1Hz","5Hz","10Hz","50Hz","100Hz","500Hz","1KHz","5KHz","10KHz","20KHz","50KHz", "100KHz" };
+    private int[] mFreqs = {1,5,10,50,100,500,1000,5000,10000,20000,50000,100000};
+
+    int mFreqIndex=8;
+    int mOldFreqIndex=mFreqIndex;
+    int mCycle=50;    //0~100
+
+    private class MessageHandler extends Handler {
+        Activity parent;
+        public MessageHandler(Looper looper, Activity v) {
+            super(looper);
+            parent = v;
+        }
+        
+        @Override
+        public void handleMessage(Message msg) {
+            String result = (String) msg.obj;
+            if (result.equals("START")) {
+                Toast.makeText(parent, String.format("Please wait..."),
+                    Toast.LENGTH_SHORT).show();
+                enableUI(false);
+            } else if (result.equals("DONE")) {
+                Toast.makeText(parent, String.format("Done"),
+                    Toast.LENGTH_SHORT).show();
+                enableUI(true);
+            } else {
+                Toast.makeText(parent, result,
+                    Toast.LENGTH_SHORT).show();
+            }
+        }
+    }
+    private void sendMessage(String msg) {
+        Message message = Message.obtain();
+        message.obj = msg;
+        mMessageHandler.sendMessage(message);
+    }
+
+    private void enableUI(boolean b) {
+        mSeekBarFreq.setEnabled(b);
+        mSeekBarCycle.setEnabled(b);
+        mCheckBoxEnable.setEnabled(b);
+        mApplyButton.setEnabled(b);
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.pwmtestingactivity);
+        Looper looper = Looper.myLooper();
+        mMessageHandler = new MessageHandler(looper, this);
+
+        mTextViewFreq = (TextView)findViewById(R.id.text_freq);
+        mTextViewCycle = (TextView)findViewById(R.id.text_cycle);
+        mSeekBarFreq = (SeekBar)findViewById(R.id.seekbar_pwm_freq);
+        mSeekBarCycle = (SeekBar)findViewById(R.id.seekbar_cycle);
+        mCheckBoxEnable = (CheckBox)findViewById(R.id.checkbox_enable);
+        mApplyButton = (Button)findViewById(R.id.button_apply);
+        
+        mSeekBarFreq.setProgress(mFreqIndex);
+        mSeekBarCycle.setProgress(mCycle);
+        mCheckBoxEnable.setChecked(mEnable);
+
+        mSeekBarFreq.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
+                mOldFreqIndex = mFreqIndex;
+                mFreqIndex = i;
+                setGuiText();
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {
+            }
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {
+            }
+        });
+        mSeekBarCycle.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
+                mCycle = i;
+                setGuiText();
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {
+            }
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {
+            }
+        });
+        setGuiText();
+        mBoardType = HardwareControler.getBoardType();
+        if (mBoardType > BoardType.RK3399_BASE && mBoardType <= BoardType.RK3399_MAX) {
+            pwmChip = "pwmchip1";
+        } else if (mBoardType > BoardType.RK3588_BASE && mBoardType <= BoardType.RK3588_MAX) {
+            pwmChip = "pwmchip1";
+        } else {
+            pwmChip = "pwmchip0";
+        }
+        applyPWMSetting();
+    }
+
+    void writeNumToFile(String fileName, long v) {
+        Log.d(TAG, "#### Write " + Long.toString(v) + " to " + fileName);
+        try {
+            BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));
+            writer.write(Long.toString(v));
+            writer.close();
+        } catch(IOException ie) {
+            ie.printStackTrace();
+            Log.e(TAG, "Write file error: " + fileName);
+            Log.e(TAG, ie.toString());
+            sendMessage("Fail to write: " + fileName + "(value: " + Long.toString(v) + ")");
+        } 
+    }
+
+    private void applyPWMSetting() {
+        new Thread() {
+            @Override
+            public void run() {
+                try {
+                    sendMessage("START");
+                    File file = new File("/sys/class/pwm/" + pwmChip + "/pwm0/enable");
+                    if (file.exists()) {
+                        writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/enable", 0);
+                        Thread.sleep(100);
+                    } else {
+                        writeNumToFile("/sys/class/pwm/" + pwmChip + "/export", 0);
+                        Thread.sleep(1000);
+                    }
+
+                    if (mEnable) {
+                        long period = 1000000000/mFreqs[mFreqIndex];
+                        if (mOldFreqIndex >= mFreqIndex) {
+                            writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/period", period);
+                            Thread.sleep(100);
+                            writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/duty_cycle", (long)(period * (mCycle/100.0)));
+                            Thread.sleep(100);
+                        } else {
+                            writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/duty_cycle", (long)(period * (mCycle/100.0)));
+                            Thread.sleep(100);
+                            writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/period", period);
+                            Thread.sleep(100);
+                        }
+                        writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/enable", 1);
+                        Thread.sleep(100);
+                    }
+
+                    sendMessage("DONE");
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }.start();
+    }
+
+    private void setGuiText(){
+        mTextViewFreq.setText(getString(R.string.txtFreq) + " (" + mFreqTexts[mFreqIndex] + ")");
+        mTextViewCycle.setText(getString(R.string.txtDutyCycle) + " (" + String.valueOf(mCycle) + "%)");
+    }
+
+    @Override
+    public void onDestroy() {
+        writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/enable", 0);
+        writeNumToFile("/sys/class/pwm/" + pwmChip + "/pwm0/duty_cycle", 0);
+        try {
+            Thread.sleep(100,0);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+        writeNumToFile("/sys/class/pwm/" + pwmChip + "/unexport", 0);
+        super.onDestroy();
+    }
+
+    public void onApplyPressed(View view) {
+        applyPWMSetting();
+    }
+
+    public void onCheckboxEnableClicked(View view) {
+        mEnable = ((CheckBox)view).isChecked();
+    }
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/Utils/BorderScrollView.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/Utils/BorderScrollView.java
new file mode 100644
index 00000000000..6bb2f6592e7
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/Utils/BorderScrollView.java
@@ -0,0 +1,27 @@
+package com.friendlyarm.Utils;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.widget.ScrollView;
+
+
+public class BorderScrollView extends ScrollView
+{
+    @Override
+    protected void onDraw(Canvas canvas)
+    {
+        super.onDraw(canvas);
+        Paint paint = new Paint();
+        paint.setColor(android.graphics.Color.GRAY);
+        canvas.drawLine(0, 0, this.getWidth() - 1, 0, paint);
+        canvas.drawLine(0, 0, 0, this.getHeight() - 1, paint);
+        canvas.drawLine(this.getWidth() - 1, 0, this.getWidth() - 1, this.getHeight() - 1, paint);
+        canvas.drawLine(0, this.getHeight() - 1, this.getWidth() - 1, this.getHeight() - 1, paint);
+    }
+    public BorderScrollView(Context context, AttributeSet attrs)
+    {
+        super(context, attrs);
+    }
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/PWMDemo/sync.sh b/vendor/friendlyelec/apps/PWMDemo/sync.sh
new file mode 100755
index 00000000000..0614251b55a
--- /dev/null
+++ b/vendor/friendlyelec/apps/PWMDemo/sync.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+adb root; adb remount; adb sync; adb reboot;
diff --git a/vendor/friendlyelec/apps/RTC_Demo/Android.mk b/vendor/friendlyelec/apps/RTC_Demo/Android.mk
new file mode 100644
index 00000000000..c76831d1c13
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := RTCDemo
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/RTC_Demo/AndroidManifest.xml b/vendor/friendlyelec/apps/RTC_Demo/AndroidManifest.xml
new file mode 100644
index 00000000000..bef11b8a58e
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.friendlyarm.RTCDemo"
+      coreApp="true"
+      android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/icon"
+        android:label="@string/app_name">
+	
+        <activity
+	    android:name="RTCDemoMainActivity"
+            android:label="@string/app_name"
+            android:windowSoftInputMode="stateHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/RTC_Demo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/RTC_Demo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/RTC_Demo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/RTC_Demo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/RTC_Demo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/RTC_Demo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/RTC_Demo/res/drawable/icon.png b/vendor/friendlyelec/apps/RTC_Demo/res/drawable/icon.png
new file mode 100644
index 00000000000..7f9299d527b
Binary files /dev/null and b/vendor/friendlyelec/apps/RTC_Demo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/RTC_Demo/res/layout/main.xml b/vendor/friendlyelec/apps/RTC_Demo/res/layout/main.xml
new file mode 100644
index 00000000000..487098498e9
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/res/layout/main.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/txtDateLabel"
+        android:layout_marginTop="10dp"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/text_date"
+        android:textSize="24dp"
+        android:layout_marginTop="10dp"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/txtTimeLabel"
+        android:layout_marginTop="10dp"/>
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/text_time"
+        android:textSize="24dp"
+        android:layout_marginTop="10dp"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/text_autoWakeUpLabel"
+        android:layout_marginTop="10dp"/>
+
+    <SeekBar
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/seekbar_autowakeup"
+        android:progress="120"
+        android:max="3600"
+        android:longClickable="true"/>
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/txtEnableAutoWakeUp"
+        android:id="@+id/button_enableAutoWakeUp"
+        android:layout_marginTop="40dp"
+        android:onClick="onEnableAutoWakeUpPressed"/>
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/text_result"
+        android:textSize="24dp"
+        android:layout_marginTop="10dp"/>
+
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/txtPoweroff"
+        android:layout_marginTop="40dp"
+        android:onClick="onPoweroffPressed"/>
+
+    <FrameLayout
+	android:layout_width="match_parent"
+	android:layout_height="0dp"
+	android:layout_weight="1">
+    </FrameLayout>
+
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:orientation="vertical"
+        android:gravity="bottom"
+        android:layout_alignParentBottom="true"
+        android:layout_marginTop="20dp">
+       <Button
+           android:onClick="onMoreSamplesPressed"
+            android:id="@+id/btn_morebutton"
+            android:text="@string/moreSamplesButtonText"
+            android:layout_height="wrap_content"
+           android:layout_width="fill_parent">
+        </Button>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/vendor/friendlyelec/apps/RTC_Demo/res/values/strings.xml b/vendor/friendlyelec/apps/RTC_Demo/res/values/strings.xml
new file mode 100644
index 00000000000..c1b2ca74b99
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">RTC Sample</string>
+    <string name="txtDateLabel">RTC Date</string>
+    <string name="txtTimeLabel">RTC Time</string>
+    <string name="txtAutoWakeUpLabel">Auto Wake Up</string>
+    <string name="txtEnableAutoWakeUp">Enable Auto Wake Up</string>
+    <string name="txtPoweroff">Power off</string>
+    <string name="moreSamplesButtonText">More samples? \nClick here</string>
+</resources>
+
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/RTCDemo/RTCDemoMainActivity.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/RTCDemo/RTCDemoMainActivity.java
new file mode 100644
index 00000000000..7b7670c7f32
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/RTCDemo/RTCDemoMainActivity.java
@@ -0,0 +1,224 @@
+package com.friendlyarm.RTCDemo;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.BoardType;
+import com.friendlyarm.RTCDemo.R;
+import com.friendlyarm.Utils.CommonFuncs;
+
+import android.net.Uri;
+import android.content.Intent;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.widget.TextView;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.view.View.OnClickListener;
+import android.widget.CheckBox;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Toast;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.os.Handler;
+import android.os.Message;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import android.os.IPowerManager;
+import android.os.PowerManager;
+import android.os.ServiceManager;
+import android.content.Context;
+import android.os.RemoteException;
+import java.io.*;
+
+public class RTCDemoMainActivity extends Activity {
+    private static final String TAG = "RTCDemo";
+
+    private TextView mDateTextView;
+    private TextView mTimeTextView;
+    private TextView mAutoWakeUpTextView;
+    private SeekBar mAutoWakeUpSeekBar;
+    private Button mEnableButton;
+    private TextView mResultTextView;
+    private int mWakeUpSeconds = 120;
+    final int MSG_SHOW_DATETIME = 1;
+    final int MSG_SHOW_WAKEUP_TIMEOUT = 2;
+    private int mWakeUpSecondsCountDown = mWakeUpSeconds;
+
+   public void onMoreSamplesPressed(View view) {
+        Uri uri = Uri.parse("http://wiki.friendlyelec.com/wiki/index.php/FriendlyThings_for_Rockchip");
+        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+        startActivity(intent); 
+    }
+
+    private static boolean writeToFile(String fileName, String v) {
+        Log.d(TAG, "#### Write " + v + " to " + fileName);
+        try {
+            BufferedWriter writer = new BufferedWriter(new FileWriter(fileName));
+            writer.write(v);
+            writer.close();
+            return true;
+        } catch(IOException ie) {
+            ie.printStackTrace();
+            Log.e(TAG, "Write file error: " + fileName);
+            Log.e(TAG, ie.toString());
+        }
+        return false;
+    }
+
+    private static String readFromFile(String path, String fileName) {
+        File file = new File(path,fileName);
+        try {
+            BufferedReader br = new BufferedReader(new FileReader(file));
+            String str = br.readLine().trim();
+            br.close();
+            return str;
+        }
+        catch (IOException e) {
+            //You'll need to add proper error handling here
+        }
+        return "";
+    }
+
+    private Timer timer = new Timer();
+    private TimerTask task = new TimerTask() {
+        public void run() {
+            Message message = new Message();
+            message.what = MSG_SHOW_DATETIME;
+            handler.sendMessage(message);
+        }
+    };
+
+    private Timer timerForWakeUp = null;
+    private TimerTask taskForWakeUp = null;
+
+    private int mBoardType = HardwareControler.getBoardType();
+    private Handler handler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case MSG_SHOW_DATETIME:
+                if (mBoardType > BoardType.RK3399_BASE && mBoardType <= BoardType.RK3399_MAX
+			|| mBoardType > BoardType.RK3568_BASE && mBoardType <= BoardType.RK3568_MAX
+			|| mBoardType > BoardType.RK3588_BASE && mBoardType <= BoardType.RK3588_MAX) {
+                    mDateTextView.setText(readFromFile("/sys/class/rtc/rtc0/","date"));
+                    mTimeTextView.setText(readFromFile("/sys/class/rtc/rtc0/","time"));
+                }
+                break;
+            case MSG_SHOW_WAKEUP_TIMEOUT:
+                mWakeUpSecondsCountDown --;
+                if (mWakeUpSecondsCountDown < 0) {
+                    mWakeUpSecondsCountDown = 0;
+                    mEnableButton.setEnabled(true);
+                    mAutoWakeUpSeekBar.setEnabled(true);
+                    mResultTextView.setText("");
+
+                    timerForWakeUp.cancel();
+                    timerForWakeUp = null;
+                    taskForWakeUp.cancel();
+                    taskForWakeUp = null;
+                    return ;
+                }
+                mResultTextView.setText("The board will wake up automatically after " + String.valueOf(mWakeUpSecondsCountDown) + " seconds");
+                break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mDateTextView = (TextView)findViewById(R.id.text_date);
+        mTimeTextView = (TextView)findViewById(R.id.text_time);
+        mAutoWakeUpTextView = (TextView)findViewById(R.id.text_autoWakeUpLabel);
+        mAutoWakeUpSeekBar = (SeekBar)findViewById(R.id.seekbar_autowakeup);
+        mEnableButton = (Button)findViewById(R.id.button_enableAutoWakeUp);
+        mResultTextView = (TextView)findViewById(R.id.text_result);
+
+	if (mBoardType > BoardType.RK3399_BASE && mBoardType <= BoardType.RK3399_MAX) {
+		//rk3399
+	} else {
+		mAutoWakeUpTextView.setVisibility(View.INVISIBLE);
+		mAutoWakeUpSeekBar.setVisibility(View.INVISIBLE);
+		mEnableButton.setVisibility(View.INVISIBLE);
+	}
+        
+        mAutoWakeUpSeekBar.setProgress(mWakeUpSeconds);
+        mAutoWakeUpSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
+                if (i > 0) {
+                    mWakeUpSeconds = i;
+                }
+                setGuiText();
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar seekBar) {
+            }
+
+            @Override
+            public void onStopTrackingTouch(SeekBar seekBar) {
+            }
+        });
+
+        timer.schedule(task, 0, 1000);
+        setGuiText();
+    }
+
+    private void setGuiText(){
+        mAutoWakeUpTextView.setText(getString(R.string.txtAutoWakeUpLabel) + " (After " + String.valueOf(mWakeUpSeconds) + "s)");
+    }
+
+    public void onEnableAutoWakeUpPressed(View view) {
+        if (mBoardType > BoardType.RK3399_BASE && mBoardType <= BoardType.RK3399_MAX
+		|| mBoardType > BoardType.RK3568_BASE && mBoardType <= BoardType.RK3568_MAX
+		|| mBoardType > BoardType.RK3588_BASE && mBoardType <= BoardType.RK3588_MAX) {
+            if (writeToFile("/sys/class/rtc/rtc0/wakealarm", "+" + String.valueOf(mWakeUpSeconds))) {
+                Toast.makeText(this, String.format("Performed successfully"),
+                        Toast.LENGTH_SHORT).show();
+                mWakeUpSecondsCountDown = mWakeUpSeconds;
+                mResultTextView.setText("The board will wake up automatically after " + String.valueOf(mWakeUpSecondsCountDown) + " seconds");
+                mEnableButton.setEnabled(false);
+                mAutoWakeUpSeekBar.setEnabled(false);
+
+                if (timerForWakeUp == null) {
+                    timerForWakeUp = new Timer();
+                }
+                if (taskForWakeUp == null) {
+                    taskForWakeUp = new TimerTask() {
+                        public void run() {
+                            Message message = new Message();
+                            message.what = MSG_SHOW_WAKEUP_TIMEOUT;
+                            handler.sendMessage(message);
+                        }
+                    };
+                }
+                timerForWakeUp.schedule(taskForWakeUp, 0, 1000);
+            } else {
+                Toast.makeText(this, String.format("Failed"),
+                        Toast.LENGTH_SHORT).show();
+            }
+        }
+    }
+
+    public void onPoweroffPressed(View view) {
+        Thread thr = new Thread("Shutdown") {
+            @Override
+            public void run() {
+                IPowerManager pm = IPowerManager.Stub.asInterface(
+                        ServiceManager.getService(Context.POWER_SERVICE));
+                try {
+                    pm.shutdown(false, PowerManager.SHUTDOWN_USER_REQUESTED, false);
+                } catch (RemoteException e) {
+                }
+            }
+        };
+        thr.start();
+    }
+}
diff --git a/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/RTC_Demo/sync.sh b/vendor/friendlyelec/apps/RTC_Demo/sync.sh
new file mode 100755
index 00000000000..0614251b55a
--- /dev/null
+++ b/vendor/friendlyelec/apps/RTC_Demo/sync.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+adb root; adb remount; adb sync; adb reboot;
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/.classpath b/vendor/friendlyelec/apps/SPI_OLED_Demo/.classpath
new file mode 100644
index 00000000000..7bc01d9a9c6
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/.project b/vendor/friendlyelec/apps/SPI_OLED_Demo/.project
new file mode 100644
index 00000000000..a33b34e5bb9
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>SPI_OLED_Demo</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/.settings/org.eclipse.jdt.core.prefs b/vendor/friendlyelec/apps/SPI_OLED_Demo/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000000..b080d2ddc88
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/Android.mk b/vendor/friendlyelec/apps/SPI_OLED_Demo/Android.mk
new file mode 100644
index 00000000000..208db629876
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := SPI-OLED
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/AndroidManifest.xml b/vendor/friendlyelec/apps/SPI_OLED_Demo/AndroidManifest.xml
new file mode 100644
index 00000000000..d1ed7a6170c
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.friendlyarm.SPI_OLED"
+      coreApp="true"
+      android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+	    <activity android:name="com.friendlyarm.SPI_OLED.MainActivity"
+	      android:label="@string/MainActivityTitle"
+	      android:windowSoftInputMode="adjustPan">
+	            <intent-filter>
+	                <action android:name="android.intent.action.MAIN" />
+	                <category android:name="android.intent.category.LAUNCHER" />
+	            </intent-filter>  
+	    </activity>
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/Smart4418SDK+OLED.png b/vendor/friendlyelec/apps/SPI_OLED_Demo/Smart4418SDK+OLED.png
new file mode 100644
index 00000000000..6e644ee193c
Binary files /dev/null and b/vendor/friendlyelec/apps/SPI_OLED_Demo/Smart4418SDK+OLED.png differ
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/SPI_OLED_Demo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/SPI_OLED_Demo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/SPI_OLED_Demo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/SPI_OLED_Demo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/project.properties b/vendor/friendlyelec/apps/SPI_OLED_Demo/project.properties
new file mode 100644
index 00000000000..0840b4a0598
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-15
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/res/drawable/icon.png b/vendor/friendlyelec/apps/SPI_OLED_Demo/res/drawable/icon.png
new file mode 100644
index 00000000000..c660c599d27
Binary files /dev/null and b/vendor/friendlyelec/apps/SPI_OLED_Demo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/res/layout/mainactivity.xml b/vendor/friendlyelec/apps/SPI_OLED_Demo/res/layout/mainactivity.xml
new file mode 100644
index 00000000000..508f01d1a67
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/res/layout/mainactivity.xml
@@ -0,0 +1,22 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+    
+    <!-- <linearlayout android:focusable="true" android:focusableInTouchMode="true" android:layout_height="0px" android:layout_width="0px"> -->
+	<EditText android:id="@+id/toEditor" android:layout_width="fill_parent"
+		android:layout_height="200dip" android:inputType="textMultiLine"
+		android:singleLine="false"
+       android:editable="true" android:gravity="top" />
+    <!--  </linearlayout> -->  
+    
+	<Button android:id="@+id/cleanButton" android:layout_width="fill_parent"
+		android:layout_height="40dip" android:text="@string/cleanButtonLabel">
+	</Button>
+	
+	<Button android:id="@+id/backButton" android:layout_width="fill_parent"
+		android:layout_height="40dip" android:text="@string/backButtonText">
+	</Button>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/res/values/strings.xml b/vendor/friendlyelec/apps/SPI_OLED_Demo/res/values/strings.xml
new file mode 100644
index 00000000000..8133bd96fa0
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/res/values/strings.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">SPI-OLED</string>
+	<string name="MainActivityTitle">SPI-OLED</string>
+    <string name="backButtonText">Back</string>
+    <string name="cleanButtonLabel">Clear</string>
+</resources>
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/SPI_OLED/MainActivity.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/SPI_OLED/MainActivity.java
new file mode 100644
index 00000000000..29f717ef99a
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/SPI_OLED/MainActivity.java
@@ -0,0 +1,216 @@
+package com.friendlyarm.SPI_OLED;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.BoardType;
+import com.friendlyarm.SPI_OLED.R;
+import com.friendlyarm.SPI_OLED.OLED;
+
+public class MainActivity extends Activity implements OnClickListener {
+    private static final String TAG = "SPILCD";
+    private EditText toEditor = null;
+    private int mBoardType = HardwareControler.getBoardType();
+    private boolean mBoardSupported = true;
+    
+    private final String devName = "/dev/spidev0.0";   /*For S5P4418*/
+    //private final int gpioPin_For_DC = 75;               /*GPIOC11 on Smart4418*/
+    //private final int gpioPin_For_Reset = 74;          /*GPIOC10 on Smart4418*/
+    
+    private int gpioPin_For_DC;
+    private int gpioPin_For_Reset;
+    
+    OLED oled;
+
+    private Timer mExportGPIOTimer = new Timer();
+    private Timer mFlashTextTimer = new Timer();
+    private int mSPIInitStep = 0; 
+    private final int STEP_INIT_GPIO = 1;
+    private final int STEP_INIT_SPI = 2;
+    private final int ID_TIMER_EXPORT_GPIO = 1;
+    private final int ID_TIMER_FLASH_TEXT = 2;
+    
+    @Override
+    public void onDestroy() {
+        mExportGPIOTimer.cancel();
+        mFlashTextTimer.cancel();
+        
+        HardwareControler.unexportGPIOPin( gpioPin_For_DC );
+        HardwareControler.unexportGPIOPin( gpioPin_For_Reset );
+        oled.Deinit();
+        
+        super.onDestroy();
+    }
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.mainactivity);
+        setTitle("SPI OLED");
+
+        Button backButton = (Button)findViewById(R.id.backButton);
+        backButton.setOnClickListener(this);
+        ((Button)findViewById(R.id.cleanButton)).setOnClickListener(this);
+       
+        toEditor = (EditText)findViewById(R.id.toEditor);
+        toEditor.setText("ABCDEFGHIJKOMNOPabcdefghijkomnop1234567890123456,./<>?;':\"[]{}*@");
+
+         if (mBoardType>=BoardType.S5P4418_BASE && mBoardType<=BoardType.S5P4418_MAX) {
+             gpioPin_For_DC = 75;            /* GPIOC11 on Smart4418 */
+             gpioPin_For_Reset = 74;         /* GPIOC10 on Smart4418 */
+        } else if (mBoardType>=BoardType.S5P6818_BASE && mBoardType<=BoardType.S5P6818_MAX) {
+             gpioPin_For_DC = 68;            /* GPIOC4 on T3, PIn17 */
+             gpioPin_For_Reset = 71;         /* GPIOC7 on T3, Pin18 */
+         } else if (mBoardType>=BoardType.RK3399_BASE && mBoardType<=BoardType.RK3399_MAX) {
+             gpioPin_For_DC = 33;            /* GPIO1_A1 on T4, NEO4, M4, Pin11 */
+             gpioPin_For_Reset = 36;         /* GPIO1_A4 on T4, NEO4, M4, Pin15 */
+         } else if (mBoardType == BoardType.NanoPC_T6) {
+             gpioPin_For_DC = 108;           /* GPIO3_B4, Pin18 */
+             gpioPin_For_Reset = 107;        /* GPIO3_B3, Pin16 */
+         } else {
+            Toast.makeText(this, String.format("Current implementation only supports S5P4418/S5P6818/RK3399/NanoPC_T6."),
+                Toast.LENGTH_SHORT).show();
+            mBoardSupported = false;
+         }
+        
+        /* no focus when begin */
+        toEditor.clearFocus();
+        toEditor.setFocusable(false);
+        toEditor.setFocusableInTouchMode(true);
+        
+
+        oled = new OLED();
+        if (HardwareControler.exportGPIOPin( gpioPin_For_DC ) == 0 
+                && HardwareControler.exportGPIOPin( gpioPin_For_Reset ) == 0) {
+            
+            Log.d(TAG, "exportGPIOPin ok");
+            
+            /*
+             * 1->set direction gpio  
+             * 2->set gpio value  
+             * 3->unexport  
+             * >3 quit mExportGPIOTimer
+             */
+            
+            mSPIInitStep = STEP_INIT_GPIO;  
+            mExportGPIOTimer.schedule(init_task, 100, 100); 
+        } else {
+            Toast.makeText(this,"exportGPIOPin failed!",Toast.LENGTH_SHORT).show();
+        }
+    }
+    
+    private Handler handler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case ID_TIMER_EXPORT_GPIO:
+                mExportGPIOTimer.cancel();
+                break;
+            case ID_TIMER_FLASH_TEXT:
+                mFlashTextTimer.cancel();
+                break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+    
+    private void quitTimer(int timerId) {
+        Message message = new Message();
+        message.what = timerId;
+        handler.sendMessage(message);
+    }
+    
+    private TimerTask init_task = new TimerTask() {
+        public void run() {
+            if (mSPIInitStep == STEP_INIT_GPIO) {
+                if (oled.Init(devName, gpioPin_For_DC, gpioPin_For_Reset) == 0) {
+                    mSPIInitStep ++;
+                } else {
+                    quitTimer(ID_TIMER_EXPORT_GPIO);
+                }
+            } else if (mSPIInitStep == STEP_INIT_SPI) {
+                mSPIInitStep ++;
+                quitTimer(ID_TIMER_EXPORT_GPIO);
+                mFlashTextTimer.schedule(flash_text_task, 1000, 1000);
+            }
+        }
+    }; 
+    
+    public static String[] splitByByteSize(String content, int size){
+        byte[] bytes = content.getBytes();
+        int totalSize = bytes.length;
+        int partNum = 0;
+        if(totalSize == 0){
+            return new String[0];
+        }
+        if(totalSize % size == 0){
+            partNum = totalSize / size;
+        }else{
+            partNum = totalSize / size + 1;
+        }
+        String[] arr = new String[partNum];
+        int arrIndex = -1;
+        for(int i=0;i<totalSize;i++){
+            if(i%size == 0){
+                arrIndex++;
+                arr[arrIndex] = "";
+            }
+            arr[arrIndex]+=((char)bytes[i]);
+        }
+        return arr;
+
+    }
+
+    private TimerTask flash_text_task = new TimerTask() {
+        public void run() {
+            Log.d(TAG, "Enter flash_text_task");
+            final int MAX_CHATS_PER_LINE = 16;
+            final int MAX_LINE = 4;
+            String displayText = toEditor.getText().toString();
+            //clear
+            if (oled.OLEDCleanScreen() != 0) {
+                Log.e(TAG, "oled.OLEDCleanScreen failed.");
+            } else {
+                Log.e(TAG, "oled.OLEDCleanScreen ok.");
+            }
+            if (displayText.length() > 0) {
+                Log.e(TAG, "need display text: " + displayText);
+                String[] lines = splitByByteSize(displayText, MAX_CHATS_PER_LINE);
+                for (int i=0; i<MAX_LINE && i<lines.length; i++) {
+                    Log.e(TAG, "display line: " + i + ", text: " + lines[i]);
+                    if (oled.OLEDDisp8x16Str(0, i*MAX_CHATS_PER_LINE, lines[i].getBytes()) != 0) {
+                        Log.e(TAG, "oled.OLEDDisp8x16Str failed.");
+                    } else {
+                        Log.e(TAG, "oled.OLEDDisp8x16Str ok.");
+                    }
+                }
+            }
+            quitTimer(ID_TIMER_FLASH_TEXT);
+            Log.d(TAG, "Leave flash_text_task");
+            
+        }
+    };
+    
+    public void onClick(View v)
+    {
+        switch (v.getId()) {
+        case R.id.backButton:
+            finish();
+            break;
+        case R.id.cleanButton:
+            toEditor.setText("");
+            break;
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/SPI_OLED/OLED.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/SPI_OLED/OLED.java
new file mode 100644
index 00000000000..1c2bb448ba2
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/SPI_OLED/OLED.java
@@ -0,0 +1,507 @@
+package com.friendlyarm.SPI_OLED;
+
+import android.util.Log;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class OLED {
+    
+    private int devFD = -1;
+    private int gpioPin_For_DC = -1;
+    private int gpioPin_For_Reset = -1;
+    private boolean isValid = false;
+    
+    static final byte spiMode = 0;
+    static final char spiBits = 8;
+    static final int spiSpeed = 25000000;
+    static short spiDelay;
+    final String TAG = "OLED";
+    
+    final int OLED_WIDTH = 132;
+    final int OLED_HEIGHT = 64;
+    
+    // 8 x 16 font
+    static final short OLEDCharMap[]=
+    {
+            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//  0
+            0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
+            0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
+            0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
+            0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
+            0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
+            0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
+            0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
+            0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
+            0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
+            0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
+            0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
+            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
+            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
+            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
+            0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
+            0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
+            0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
+            0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
+            0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
+            0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
+            0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
+            0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
+            0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
+            0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
+            0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
+            0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
+            0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
+            0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
+            0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
+            0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
+            0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
+            0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
+            0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
+            0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
+            0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
+            0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
+            0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
+            0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
+            0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
+            0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
+            0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
+            0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
+            0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
+            0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
+            0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
+            0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
+            0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
+            0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
+            0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
+            0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
+            0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
+            0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
+            0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
+            0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
+            0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
+            0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
+            0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
+            0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
+            0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
+            0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
+            0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
+            0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
+            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
+            0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
+            0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
+            0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
+            0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
+            0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
+            0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
+            0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
+            0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
+            0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
+            0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
+            0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
+            0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
+            0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
+            0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
+            0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
+            0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
+            0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
+            0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
+            0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
+            0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
+            0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
+            0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
+            0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
+            0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
+            0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
+            0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
+            0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
+            0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
+            0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
+            0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
+            0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
+    };
+
+    // write 8 * 8 bitmap
+    int OLEDWriteData(byte data)
+    {       
+        int ret = 0;
+        final int pin = gpioPin_For_DC;
+
+        if (HardwareControler.setGPIODirection(pin, GPIOEnum.OUT) == -1) {
+            ret = -1;
+        }
+        if (HardwareControler.setGPIOValue(pin, GPIOEnum.HIGH) == -1) {
+            ret = -1;
+        }       
+        if (HardwareControler.SPItransferOneByte(devFD, data, spiDelay, spiSpeed, spiBits) == -1) {
+            ret = -1;        
+        }
+        return ret;
+    }
+
+    int OLEDWriteCmd(byte cmd)
+    {
+        int ret = 0;
+        final int pin = gpioPin_For_DC;
+
+        if (HardwareControler.setGPIODirection(pin, GPIOEnum.OUT) == -1) {
+            ret = -1;
+        }
+        if (HardwareControler.setGPIOValue(pin, GPIOEnum.LOW) == -1) {
+            ret = -1;
+        }
+        
+        if (HardwareControler.SPItransferOneByte(devFD, cmd, spiDelay, spiSpeed, spiBits) == -1) {
+            ret = -1;        
+        }
+        return ret;
+    }
+
+    int OLEDSetPos(int x, int y)
+    { 
+        int ret = 0;
+
+        y = y/8 + y%8;
+        if (OLEDWriteCmd((byte)(0xb0+y)) == -1) {
+            ret = -1;
+        }
+        
+        if (OLEDWriteCmd((byte)((x&0xf0)>>4|0x10)) == -1) {
+            ret = -1;
+        }
+        if (OLEDWriteCmd((byte)((x&0x0f)|0x01)) == -1) {
+            ret = -1;
+        }
+        return ret;
+    } 
+
+    int OLEDReset(int pin) throws InterruptedException
+    {
+        int ret = -1;
+
+        if ((ret = HardwareControler.setGPIODirection(pin, GPIOEnum.OUT)) == -1) {
+            return -1;
+        }
+        if ((ret = HardwareControler.setGPIOValue(pin, GPIOEnum.LOW)) == -1) {
+            return -1;
+        }    
+        Thread.sleep(0, 100);
+        if ((ret = HardwareControler.setGPIOValue(pin, GPIOEnum.HIGH)) == -1) {
+            return -1;
+        }
+        return ret;
+    }
+    
+    int OLEDSPIInit()
+    {
+        if (HardwareControler.setSPIDataMode(devFD, spiMode) != 0) {
+            return -1;
+        }
+        
+        if (HardwareControler.setSPIWriteBitsPerWord(devFD, spiBits) != 0) {
+            return -1;
+        }
+        if (HardwareControler.setSPIMaxSpeed(devFD, spiSpeed) == -1 ) {
+            return -1;
+        }
+        return 0;
+    }
+    
+    void Deinit() {
+        if (devFD >= 0) {
+            HardwareControler.close(devFD);
+            devFD = -1;
+        }
+    }
+
+    int Init(String spiDevPath, int cmdDatPin, int resetPin) 
+    {
+        gpioPin_For_Reset = resetPin;
+        gpioPin_For_DC = cmdDatPin;
+
+        devFD = HardwareControler.open( spiDevPath, FileCtlEnum.O_RDWR );
+        if (devFD < 0) {
+            Log.e(TAG, "Fail to open SPI device: " + spiDevPath);
+            return -1;
+        }
+        Log.d(TAG, "Open " + spiDevPath + " Ok.");
+        if (OLEDSPIInit() == -1) {
+            Deinit();
+            Log.e(TAG, "Fail to init SPI device OLED");
+            return -1;
+        }
+        try {
+            if (OLEDReset(gpioPin_For_Reset) == -1) {
+                Deinit();
+                Log.e(TAG, "Fail to reset OLED");
+                return -1;
+            }
+        } catch  (Exception e) {
+            Log.e(TAG, "Fail to reset OLED");
+            return -1;
+        }
+        if (OLEDWriteCmd((byte)0xae) == -1) {//--turn off oled panel
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+        if (OLEDWriteCmd((byte)0xae) == -1) {//--turn off oled panel
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x00) == -1) {//---set low column address
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x10) == -1) {//---set high column address
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x40) == -1) {//--set start line address  Set Mapping RAM Display       Start Line (0x00~0x3F)
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+        if (OLEDWriteCmd((byte)0x81) == -1) {//--set contrast control register
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+        
+        if (OLEDWriteCmd((byte)0xcf) == -1) { // Set SEG Output Current Brightness
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xa1) == -1) {//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xc8) == -1) {//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xa6) == -1) {//--set normal display
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xa8) == -1) {//--set multiplex ratio(1 to 64)
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x3f) == -1) {//--1/64 duty
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xd3) == -1) {//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x00) == -1) {//-not offset
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xd5) == -1) {//--set display clock divide ratio/oscillator frequency
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x80) == -1) {//--set divide ratio, Set Clock as 100 Frames/Sec
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xd9) == -1) {//--set pre-charge period
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xf1) == -1) {//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xda) == -1) {//--set com pins hardware configuration
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x12) == -1) {
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xdb) == -1) {//--set vcomh
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x40) == -1) {//Set VCOM Deselect Level
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x20) == -1) {//-Set Page Addressing Mode (0x00/0x01/0x02)
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x02) == -1) {//
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x8d) == -1) {//--set Charge Pump enable/disable
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0x14) == -1){//--set(0x10) disable
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+        if (OLEDWriteCmd((byte)0xa4) == -1) {// Disable Entire Display On (0xa4/0xa5)
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xa6) == -1) {// Disable Inverse Display On (0xa6/a7) 
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDWriteCmd((byte)0xaf) == -1) {//--turn on oled panel
+            Deinit();
+            Log.e(TAG, "OLED write cmd failed");
+            return -1;
+        }
+
+
+        if (OLEDSetPos(0, 0) == -1) {
+            Deinit();
+            Log.e(TAG, "OLEDSetPos failed");
+            return -1;
+        }
+
+        return 0;
+    }
+
+    int OLEDDisp8x16Char(int x, int y, byte ch)
+    {
+        int i = 0;
+        final int index = ch-32; 
+
+        if (x<0 || x>(OLED_WIDTH-8) || y<0 || y>(OLED_HEIGHT-16)) {
+            Log.e(TAG, "Unsupported OLED coordinate");
+            return -1;
+        }
+
+        OLEDSetPos(x, y);    
+        for (i=0; i<8; i++) {  
+            OLEDWriteData((byte)OLEDCharMap[index*16+i]);
+        }
+
+        OLEDSetPos(x, y+8);    
+        for (i=0; i<8; i++)     
+            OLEDWriteData((byte)OLEDCharMap[index*16+i+8]); 
+
+        return 0;
+    }
+
+    int OLEDDisp8x16Str(int x, int y, byte[] strBytes)
+    {
+        int xx = x;
+        for (int i = 0; i < strBytes.length; i++) {
+            if (OLEDDisp8x16Char(xx, y, strBytes[i]) == -1) {
+                Log.e(TAG, "Fail to write 8x16 Char to OLED");
+                return -1;
+            }
+            xx=xx+8;
+        }
+        return 0;
+    }
+
+    int OLEDCleanScreen()
+    {
+        int x,y;
+        final byte data = 0x00;
+        int ret = 0;
+        for (y=0; y<8; y++) {
+            OLEDWriteCmd((byte)(0xb0+y));
+            OLEDWriteCmd((byte)(0x00));
+            OLEDWriteCmd((byte)(0x10));
+            for (x=0; x<OLED_WIDTH; x++) {
+                if (OLEDWriteData(data) == -1) {
+                    ret = -1;
+                    break;
+                }
+            }
+        }
+        return ret;
+    } 
+
+}
diff --git a/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/SPI_OLED_Demo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/.classpath b/vendor/friendlyelec/apps/SerialPortDemo/.classpath
new file mode 100644
index 00000000000..7bc01d9a9c6
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/Android.mk b/vendor/friendlyelec/apps/SerialPortDemo/Android.mk
new file mode 100644
index 00000000000..b231590bbb1
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := SerialPortDemo
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/AndroidManifest.xml b/vendor/friendlyelec/apps/SerialPortDemo/AndroidManifest.xml
new file mode 100644
index 00000000000..a48ccf8f5cd
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.friendlyarm.SerialPortDemo"
+        coreApp="true"
+        android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+        
+        <activity android:name="com.friendlyarm.SerialPortDemo.SerialPortDataProcessView"
+                android:label="@string/CommDataViewTitle"
+                android:windowSoftInputMode="adjustPan">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/SerialPortDemo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/SerialPortDemo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/SerialPortDemo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/SerialPortDemo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/res/drawable/icon.png b/vendor/friendlyelec/apps/SerialPortDemo/res/drawable/icon.png
new file mode 100644
index 00000000000..8b04396c127
Binary files /dev/null and b/vendor/friendlyelec/apps/SerialPortDemo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/res/layout/serialport_dataprocessview.xml b/vendor/friendlyelec/apps/SerialPortDemo/res/layout/serialport_dataprocessview.xml
new file mode 100644
index 00000000000..41653154887
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/res/layout/serialport_dataprocessview.xml
@@ -0,0 +1,52 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+    
+    <TextView android:id="@+id/label2" android:layout_width="fill_parent" android:layout_height="wrap_content"
+			 android:text="@string/toDataLabel" />
+    
+    <!-- <linearlayout android:focusable="true" android:focusableInTouchMode="true" android:layout_height="0px" android:layout_width="0px"> -->
+	<EditText android:id="@+id/toEditor" android:layout_width="fill_parent"
+		android:layout_height="60dip" android:inputType="textMultiLine"
+		android:singleLine="false"
+       android:editable="true" android:gravity="top" />
+    <!--  </linearlayout> -->  
+    
+	<Button android:id="@+id/sendButton" android:layout_width="fill_parent"
+		android:layout_height="40dip" android:text="@string/sendButtonLabel">
+	</Button>
+		
+	<TextView android:id="@+id/label1" android:layout_width="fill_parent"
+		android:layout_height="wrap_content" android:text="@string/fromDataLabel"/>
+
+	<com.friendlyarm.Utils.BorderScrollView android:layout_width="fill_parent"
+			android:layout_height="220dip" android:background="#FFFFFF"  
+			android:id="@+id/scroolView"  android:layout_weight="1">
+		<TextView
+			android:id="@+id/fromTextView" android:layout_width="fill_parent"
+			android:layout_height="fill_parent" android:singleLine="false"
+			android:gravity="top" android:background="#FFFFFF"
+			android:textColor="#000000" 
+			/>
+	</com.friendlyarm.Utils.BorderScrollView>
+
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:orientation="vertical"
+        android:gravity="bottom"
+        android:layout_alignParentBottom="true"
+        android:layout_marginTop="20dp">
+       <Button
+           android:onClick="onMoreSamplesPressed"
+            android:id="@+id/btn_morebutton"
+            android:text="@string/moreSamplesButtonText"
+            android:layout_height="wrap_content"
+           android:layout_width="fill_parent">
+        </Button>
+    </LinearLayout>
+	
+</LinearLayout>
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/res/layout/serialport_dataprocessview_landscape.xml b/vendor/friendlyelec/apps/SerialPortDemo/res/layout/serialport_dataprocessview_landscape.xml
new file mode 100644
index 00000000000..0027595b705
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/res/layout/serialport_dataprocessview_landscape.xml
@@ -0,0 +1,66 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:orientation="horizontal" android:layout_width="fill_parent"
+	android:layout_height="fill_parent" android:gravity="center_horizontal">
+
+	<LinearLayout android:orientation="vertical" android:layout_width="400dip"
+		android:layout_height="fill_parent" android:gravity="center_vertical">
+		
+		<TextView android:id="@+id/label1" android:layout_width="fill_parent" android:layout_height="20dip"
+			 android:text="@string/fromDataLabel" />
+			
+		<com.friendlyarm.Utils.BorderScrollView
+			android:layout_width="fill_parent" android:layout_height="fill_parent"
+			android:background="#FFFFFF" android:id="@+id/scroolView"
+			android:layout_weight="9">
+			<TextView android:id="@+id/fromTextView"
+				android:layout_width="fill_parent" android:layout_height="fill_parent"
+				android:singleLine="false" android:gravity="top" android:background="#FFFFFF"
+				android:textColor="#000000"
+				 />
+		</com.friendlyarm.Utils.BorderScrollView>
+		
+		<TextView android:id="@+id/label2" android:layout_width="fill_parent" android:layout_height="20dip"
+			 android:text="@string/toDataLabel" />
+		
+		<!-- <linearlayout android:focusable="true" android:focusableInTouchMode="true" android:layout_height="0px" android:layout_width="0px"> -->
+		<EditText android:id="@+id/toEditor" android:layout_width="fill_parent"
+				android:layout_height="60dip" android:singleLine="false" android:editable="true"
+				 android:gravity="top" />
+		<!--  </linearlayout> -->
+	</LinearLayout>
+
+	<LinearLayout android:orientation="vertical" android:layout_width="fill_parent"
+		android:layout_height="fill_parent" android:gravity="center_horizontal">
+		
+	    <FrameLayout
+			android:layout_width="match_parent"
+			android:layout_height="0dp"
+			android:layout_weight="1">
+	    </FrameLayout>
+
+	    <LinearLayout
+	        android:layout_width="fill_parent"
+	        android:layout_height="wrap_content"
+	        android:layout_centerHorizontal="true"
+	        android:orientation="vertical"
+	        android:gravity="bottom"
+	        android:layout_alignParentBottom="true"
+	        android:layout_marginTop="20dp">
+
+			<Button android:id="@+id/sendButton" android:layout_width="fill_parent"
+				android:layout_height="wrap_content" android:text="@string/sendButtonLabel"
+				android:layout_alignParentBottom="true">
+			</Button>
+
+	       <Button
+	           android:onClick="onMoreSamplesPressed"
+	            android:id="@+id/btn_morebutton"
+	            android:text="@string/moreSamplesButtonText2"
+	            android:layout_height="wrap_content"
+	           android:layout_width="fill_parent">
+	        </Button>
+	    </LinearLayout>
+
+		
+	</LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/res/values/strings.xml b/vendor/friendlyelec/apps/SerialPortDemo/res/values/strings.xml
new file mode 100644
index 00000000000..c8b33f7dcf2
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/res/values/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">SerialPort Demo</string>
+    <string name="SerialPortSettingsTitle">Serial Port Assistant</string>
+    <string name="backButtonText">Back</string>
+    <string name="sendButtonLabel">Send</string>
+    <string name="CommDataViewTitle">Serial Port Assistant</string>
+    <string name="fromDataLabel">Data received:</string>
+    <string name="toDataLabel">Text to Send:</string>
+    <string name="moreSamplesButtonText">More samples? \nClick here</string>
+    <string name="moreSamplesButtonText2">More samples? Click here</string>
+</resources>
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/SerialPortDemo/SerialPortDataProcessView.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/SerialPortDemo/SerialPortDataProcessView.java
new file mode 100644
index 00000000000..72981e4a874
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/SerialPortDemo/SerialPortDataProcessView.java
@@ -0,0 +1,193 @@
+package com.friendlyarm.SerialPortDemo;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.util.Log;
+import android.text.Html;
+import android.widget.Toast;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.BoardType;
+import com.friendlyarm.SerialPortDemo.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+
+public class SerialPortDataProcessView extends Activity implements OnClickListener {
+    private static final String TAG = "SerialPort";
+    private TextView fromTextView = null;
+    private EditText toEditor = null;
+    private final int MAXLINES = 200;
+    private StringBuilder remoteData = new StringBuilder(256 * MAXLINES);
+
+    private String devName = "";
+    private int speed = 115200;
+    private int dataBits = 8;
+    private int stopBits = 1;
+    private int devfd = -1;
+
+    private int mBoardType = HardwareControler.getBoardType();
+
+    public void onMoreSamplesPressed(View view) {
+        Uri uri = Uri.parse("http://wiki.friendlyelec.com/wiki/index.php/FriendlyThings_for_Rockchip");
+        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+        startActivity(intent);
+    }
+
+    @Override
+    public void onDestroy() {
+        timer.cancel();
+        if (devfd != -1) {
+            HardwareControler.close(devfd);
+            devfd = -1;
+        }
+        super.onDestroy();
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+            setContentView(R.layout.serialport_dataprocessview_landscape);
+        } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
+            setContentView(R.layout.serialport_dataprocessview);
+        }
+
+        if (mBoardType > BoardType.RK3588_BASE && mBoardType <= BoardType.RK3588_MAX) {
+            if (mBoardType == BoardType.NanoPC_T6) {
+                // NanoPC-T6 UART6
+                devName = "/dev/ttyS6";
+            } else if (mBoardType == BoardType.NanoPi_R6S || mBoardType == BoardType.NanoPi_R6C) {
+                // NanoPi-R6S/R6C - UART5
+                devName = "/dev/ttyS5";
+            } else {
+                devName = "/dev/ttyS6";
+            }
+        } else if (mBoardType > BoardType.RK3568_BASE && mBoardType <= BoardType.RK3568_MAX) {
+            // NanoPi-R5S UART9
+            devName = "/dev/ttyS9";
+        } else if (mBoardType > BoardType.RK3399_BASE && mBoardType <= BoardType.RK3399_MAX) {
+            // NanoPC-T4 UART
+            devName = "/dev/ttyS4";
+        } else {
+            devName = "/dev/ttyS1";
+        }
+
+        String winTitle = devName + "," + speed + "," + dataBits + "," + stopBits;
+        setTitle(winTitle);
+
+        ((Button)findViewById(R.id.sendButton)).setOnClickListener(this);
+
+        fromTextView = (TextView)findViewById(R.id.fromTextView);
+        toEditor = (EditText)findViewById(R.id.toEditor);
+
+        /* no focus when begin */
+        toEditor.clearFocus();
+        toEditor.setFocusable(false);
+        toEditor.setFocusableInTouchMode(true);
+
+        devfd = HardwareControler.openSerialPort( devName, speed, dataBits, stopBits );
+        if (devfd >= 0) {
+            timer.schedule(task, 0, 500);
+        } else {
+            devfd = -1;
+            fromTextView.append("Fail to open " + devName + "!");
+        }
+    }
+
+    private final int BUFSIZE = 512;
+    private byte[] buf = new byte[BUFSIZE];
+    private Timer timer = new Timer();
+    private Handler handler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case 1:
+                if (HardwareControler.select(devfd, 0, 0) == 1) {
+                    int retSize = HardwareControler.read(devfd, buf, BUFSIZE);
+                    if (retSize > 0) {
+                        String str = new String(buf, 0, retSize);
+                        remoteData.append(str);
+
+                        //Log.d(TAG, "#### LineCount: " + fromTextView.getLineCount() + ", remoteData.length()=" + remoteData.length());
+                        if (fromTextView.getLineCount() > MAXLINES) {
+                            int nLineCount = fromTextView.getLineCount();
+                            int i = 0;
+                            for (i = 0; i < remoteData.length(); i++) {
+                                if (remoteData.charAt(i) == '\n') {
+                                    nLineCount--;
+
+                                    if (nLineCount <= MAXLINES) {
+                                        break;
+                                    }
+                                }
+                            }
+                            remoteData.delete(0, i);
+                            //Log.d(TAG, "#### remoteData.delete(0, " + i + ")");
+                            fromTextView.setText(remoteData.toString());
+                        } else {
+                            fromTextView.append(str);
+                        }
+
+                        ((ScrollView)findViewById(R.id.scroolView)).fullScroll(View.FOCUS_DOWN);
+                    }
+                }
+                break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+    private TimerTask task = new TimerTask() {
+        public void run() {
+            Message message = new Message();
+            message.what = 1;
+            handler.sendMessage(message);
+        }
+    };
+
+    public void onClick(View v)
+    {
+        switch (v.getId()) {
+        case R.id.sendButton:
+            String str = toEditor.getText().toString();
+            if (str.length() > 0) {
+                if (str.charAt(str.length()-1) != '\n') {
+                    str = str + "\n";
+                }
+                int ret = HardwareControler.write(devfd, str.getBytes());
+                if (ret > 0) {
+                    toEditor.setText("");
+
+                    str = ">>> " + str;
+                    if (remoteData.length() > 0) {
+                        if (remoteData.charAt(remoteData.length()-1) != '\n') {
+                            remoteData.append('\n');
+                            fromTextView.append("\n");
+                        }
+                    }
+                    remoteData.append(str);
+                    fromTextView.append(str);
+
+                    ((ScrollView)findViewById(R.id.scroolView)).fullScroll(View.FOCUS_DOWN);
+                } else {
+                    Toast.makeText(this,"Fail to send!",Toast.LENGTH_SHORT).show();
+                }
+            }
+
+            break;
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/Utils/BorderScrollView.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/Utils/BorderScrollView.java
new file mode 100644
index 00000000000..d65e964b01f
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/Utils/BorderScrollView.java
@@ -0,0 +1,30 @@
+package com.friendlyarm.Utils;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.widget.ScrollView;
+
+
+public class BorderScrollView extends ScrollView
+{
+    @Override
+    protected void onDraw(Canvas canvas)
+    {
+        super.onDraw(canvas);
+
+        Paint paint = new Paint();
+        paint.setColor(android.graphics.Color.GRAY);
+
+        canvas.drawLine(0, 0, this.getWidth() - 1, 0, paint);
+        canvas.drawLine(0, 0, 0, this.getHeight() - 1, paint);
+        canvas.drawLine(this.getWidth() - 1, 0, this.getWidth() - 1, this.getHeight() - 1, paint);
+        canvas.drawLine(0, this.getHeight() - 1, this.getWidth() - 1, this.getHeight() - 1, paint);
+    }
+
+    public BorderScrollView(Context context, AttributeSet attrs)
+    {
+        super(context, attrs);
+    }
+}
diff --git a/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/SerialPortDemo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/Android.mk b/vendor/friendlyelec/apps/WatchDogDemo/Android.mk
new file mode 100644
index 00000000000..c0c1cfd2d5b
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := WatchDogDemo
+
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_CERTIFICATE := platform
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := -lfriendlyarm-things
+
+include $(BUILD_PACKAGE)
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/AndroidManifest.xml b/vendor/friendlyelec/apps/WatchDogDemo/AndroidManifest.xml
new file mode 100644
index 00000000000..656af8338aa
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.friendlyarm.WatchDogDemo"
+      coreApp="true"
+      android:sharedUserId="android.uid.system">
+    <!-- Android4.4, Android7.1 -->
+    <uses-sdk
+        android:minSdkVersion="19"
+        android:targetSdkVersion="25"
+        android:maxSdkVersion="25" />
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/icon"
+        android:label="@string/app_name">
+        <activity
+	    android:name="WatchdogSampleActivity"
+            android:label="@string/app_name"
+            android:windowSoftInputMode="stateHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/libs/arm64-v8a/libfriendlyarm-things.so b/vendor/friendlyelec/apps/WatchDogDemo/libs/arm64-v8a/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/WatchDogDemo/libs/arm64-v8a/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/libs/armeabi/libfriendlyarm-things.so b/vendor/friendlyelec/apps/WatchDogDemo/libs/armeabi/libfriendlyarm-things.so
new file mode 100755
index 00000000000..50588b177b2
Binary files /dev/null and b/vendor/friendlyelec/apps/WatchDogDemo/libs/armeabi/libfriendlyarm-things.so differ
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/res/drawable/icon.png b/vendor/friendlyelec/apps/WatchDogDemo/res/drawable/icon.png
new file mode 100644
index 00000000000..0b6b915b08d
Binary files /dev/null and b/vendor/friendlyelec/apps/WatchDogDemo/res/drawable/icon.png differ
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/res/layout/main.xml b/vendor/friendlyelec/apps/WatchDogDemo/res/layout/main.xml
new file mode 100644
index 00000000000..a05b660b178
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/res/layout/main.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/txtWarning"
+        android:id="@+id/text_warning"
+        android:layout_marginTop="10dp"/>
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/text_countdown"
+        android:textSize="32dp"
+        android:layout_marginTop="10dp"/>
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/text_willreset"
+        android:textSize="24dp"
+        android:layout_marginTop="10dp"/>
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/txtStart"
+        android:id="@+id/button_start"
+        android:layout_marginTop="40dp"
+        android:onClick="onStartPressed"/>
+    <Button
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/txtFeed"
+        android:id="@+id/button_feed"
+        android:layout_marginTop="40dp"
+	android:onClick="onFeedPressed"/>
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1">
+    </FrameLayout>
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:orientation="vertical"
+        android:gravity="bottom"
+        android:layout_alignParentBottom="true"
+        android:layout_marginTop="20dp">
+       <Button
+           android:onClick="onMoreSamplesPressed"
+            android:id="@+id/btn_morebutton"
+            android:text="@string/moreSamplesButtonText"
+            android:layout_height="wrap_content"
+           android:layout_width="fill_parent">
+        </Button>
+    </LinearLayout>
+</LinearLayout>
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/res/values/colors.xml b/vendor/friendlyelec/apps/WatchDogDemo/res/values/colors.xml
new file mode 100644
index 00000000000..fc21b8e6a38
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/res/values/colors.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="black">#000000</color>
+    <color name="white">#FFFFFF</color>
+    <color name="dark_grey">#4b4b4b</color>
+    <color name="light_gray">#999999</color>
+    <color name="light_red">#ffadad</color>
+    <color name="light_green">#9dff8a</color>
+    <color name="yellow">#f7de24</color>
+    <color name="light_grey">#868686</color>
+</resources>
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/res/values/strings.xml b/vendor/friendlyelec/apps/WatchDogDemo/res/values/strings.xml
new file mode 100644
index 00000000000..4f8fee453bd
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/res/values/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">Watchdog Sample</string>
+    <string name="txtWarning">Once START, Feed the dog, or else REBOOT</string>
+    <string name="txtStart">Start</string>
+    <string name="txtFeed">Feed</string>
+    <string name="moreSamplesButtonText">More samples? \nClick here</string>
+</resources>
+
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/BoardType.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
new file mode 100644
index 00000000000..c58d71c9d01
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/BoardType.java
@@ -0,0 +1,107 @@
+package com.friendlyarm.FriendlyThings;
+
+public class BoardType {
+    /* getBoardType return value: */
+    public static final int S3C6410_COMMON = 6410;
+    public static final int S5PV210_COMMON = 210;
+    public static final int S5P4412_COMMON = 4412;
+
+    //s5p4418
+    public static final int S5P4418_BASE = 4418;
+    public static final int NanoPi2 = S5P4418_BASE+0;
+    public static final int NanoPC_T2 = S5P4418_BASE+1;
+    public static final int NanoPi_S2 = S5P4418_BASE+2;
+    public static final int Smart4418 = S5P4418_BASE+3;
+    public static final int NanoPi2_Fire = S5P4418_BASE+4;
+    public static final int NanoPi_M2 = S5P4418_BASE+5;
+    public static final int NanoPi_M2A = S5P4418_BASE+7;
+    public static final int Smart4418SDK = S5P4418_BASE+0x103;
+    public static final int S5P4418_MAX = Smart4418SDK;
+
+    //s5p6818
+    public static final int S5P6818_BASE = 6818;
+    public static final int NanoPC_T3 = S5P6818_BASE+1;
+    public static final int NanoPi_M3B = S5P6818_BASE+2;
+    public static final int Smart6818 = S5P6818_BASE+3;
+    public static final int NanoPC_T3T = S5P6818_BASE+4;
+    public static final int NanoPi_Fire3 = S5P6818_BASE+5;
+    public static final int NanoPi_M3 = S5P6818_BASE+7;
+    public static final int S5P6818_MAX = NanoPi_M3;
+
+    //s3c2451
+    public static final int S3C2451_BASE = 2451;
+    public static final int S3C2451_COMMON = S3C2451_BASE+0;
+
+    //allwinner
+    public static final int ALLWINNER_BASE = 7000;
+    public static final int NanoPi_M1 = ALLWINNER_BASE+1;
+    public static final int NanoPi_NEO = ALLWINNER_BASE+2;
+    public static final int NanoPi_NEO_Air = ALLWINNER_BASE+3;
+    public static final int NanoPi_M1_Plus = ALLWINNER_BASE+4;
+    public static final int NanoPi_A64 = ALLWINNER_BASE+5;
+    public static final int NanoPi_NEO2 = ALLWINNER_BASE+6;
+    public static final int NanoPi_M1_Plus2 = ALLWINNER_BASE+7;
+    public static final int NanoPi_NEO_Plus2 = ALLWINNER_BASE+8;
+    public static final int NanoPi_NEO_Core = ALLWINNER_BASE+9;
+    public static final int NanoPi_Duo = ALLWINNER_BASE+10;
+    public static final int NanoPi_NEO_Core2 = ALLWINNER_BASE+11;
+    public static final int NanoPi_K1 = ALLWINNER_BASE+12;
+    public static final int NanoPi_K1_Plus = ALLWINNER_BASE+13;
+    public static final int NanoPi_Hero = ALLWINNER_BASE+14;
+    public static final int NanoPi_Duo2 = ALLWINNER_BASE+15;
+    public static final int NanoPi_R1 = ALLWINNER_BASE+16;
+	public static final int NanoPi_C3 = ALLWINNER_BASE+17;
+	public static final int NanoPi_NEO2_Black = ALLWINNER_BASE+18;
+	public static final int NanoPi_NEO_S = ALLWINNER_BASE+19;
+	public static final int ZeroPi = ALLWINNER_BASE+20;
+	public static final int NanoPi_R1S_H3 = ALLWINNER_BASE+21;
+	public static final int NanoPi_R1S_H5 = ALLWINNER_BASE+22;
+    public static final int ALLWINNER_MAX = NanoPi_R1S_H5;
+
+    //amlogic
+    public static final int AMLOGIC_BASE = 8000;
+    public static final int NanoPi_K2 = AMLOGIC_BASE+1;
+
+    //rk3399
+    public static final int RK3399_BASE = 9000;
+    public static final int NanoPC_T4 = RK3399_BASE+1;
+    public static final int NanoPi_M4 = RK3399_BASE+2;
+    public static final int NanoPi_NEO4 = RK3399_BASE+3;
+    public static final int SOM_RK3399 = RK3399_BASE+4;
+    public static final int NanoPi_M4v2 = RK3399_BASE+5;
+    public static final int NanoPi_M4B = RK3399_BASE+6;
+    public static final int SOM_RK3399v2 = RK3399_BASE+7;
+    public static final int NanoPi_NEO4v2 = RK3399_BASE+8;
+    public static final int NanoPi_R4S = RK3399_BASE+9;
+    public static final int NanoPC_T4B = RK3399_BASE+10;
+    public static final int NanoPi_R4S_Plus = RK3399_BASE+11;
+    public static final int NanoPi_R4SE = RK3399_BASE+12;
+    public static final int RK3399_MAX = NanoPi_R4SE;
+
+    //rk3328
+    public static final int RK3328_BASE = 9500;
+    public static final int NanoPi_R2S = RK3328_BASE+1;
+    public static final int NanoPi_NEO3_Black = RK3328_BASE+2;
+    public static final int NanoPi_NEO3_S = RK3328_BASE+3;
+    public static final int NanoPi_NEO3 = RK3328_BASE+4;
+    public static final int NanoPi_R2Pro = RK3328_BASE+5;
+    public static final int NanoPi_R2C = RK3328_BASE+6;
+    public static final int NanoPi_R2C_Plus = RK3328_BASE+7;
+    public static final int NanoPi_R2S_Plus = RK3328_BASE+8;
+    public static final int Core3328 = RK3328_BASE+9;
+    public static final int RK3328_MAX = Core3328;
+
+    //rk3568
+    public static final int RK3568_BASE = 9600;
+    public static final int NanoPi_R5S = RK3568_BASE+1;
+    public static final int NanoPi_R5C = RK3568_BASE+2;
+    public static final int NanoPi_R5S_LTS = RK3568_BASE+3;
+    public static final int RK3568_MAX = NanoPi_R5S_LTS;
+
+    //rk3588
+    public static final int RK3588_BASE = 9700;
+    public static final int NanoPi_R6S = RK3588_BASE+1;
+    public static final int NanoPC_T6 = RK3588_BASE+2;
+    public static final int NanoPi_R6C = RK3588_BASE+3;
+    public static final int RK3588_MAX = NanoPi_R6C;
+}
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
new file mode 100644
index 00000000000..75ac7542867
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/FileCtlEnum.java
@@ -0,0 +1,23 @@
+package com.friendlyarm.FriendlyThings;
+
+public class FileCtlEnum {
+    /* File Flag */
+    public final static int O_ACCMODE    = 00000003;
+    public final static int O_RDONLY    = 00000000;
+    public final static int O_WRONLY    = 00000001;
+    public final static int O_RDWR        = 00000002;
+    public final static int O_CREAT        = 00000100;    /* not fcntl */
+    public final static int O_EXCL        = 00000200;    /* not fcntl */
+    public final static int O_NOCTTY    = 00000400;    /* not fcntl */
+    public final static int O_TRUNC        = 00001000;    /* not fcntl */
+    public final static int O_APPEND    = 00002000;
+    public final static int O_NONBLOCK    = 00004000;
+    public final static int O_DSYNC        = 00010000;    /* used to be O_SYNC, see below */
+    public final static int FASYNC        = 00020000;    /* fcntl, for BSD compatibility */
+    public final static int O_DIRECT    = 00040000;    /* direct disk access hint */
+    public final static int O_LARGEFILE    = 00100000;
+    public final static int O_DIRECTORY    = 00200000;    /* must be a directory */
+    public final static int O_NOFOLLOW    = 00400000;    /* don't follow links */
+    public final static int O_NOATIME    = 01000000;
+    public final static int O_CLOEXEC    = 02000000;    /* set close_on_exec */
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
new file mode 100644
index 00000000000..c16d6cfedaf
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/GPIOEnum.java
@@ -0,0 +1,43 @@
+package com.friendlyarm.FriendlyThings;
+
+/*
+GPIO signals have paths like /sys/class/gpio/gpio42/ (for GPIO #42)
+and have the following read/write attributes:
+
+    /sys/class/gpio/gpioN/
+
+        "direction" ... reads as either "in" or "out".  This value may
+                normally be written.  Writing as "out" defaults to
+                initializing the value as low.  To ensure glitch free
+                operation, values "low" and "high" may be written to
+                configure the GPIO as an output with that initial value.
+
+                Note that this attribute *will not exist* if the kernel
+                doesn't support changing the direction of a GPIO, or
+                it was exported by kernel code that didn't explicitly
+                allow userspace to reconfigure this GPIO's direction.
+
+        "value" ... reads as either 0 (low) or 1 (high).  If the GPIO
+                is configured as an output, this value may be written;
+                any nonzero value is treated as high.
+
+                If the pin can be configured as interrupt-generating interrupt
+                and if it has been configured to generate interrupts (see the
+                description of "edge"), you can poll(2) on that file and
+                poll(2) will return whenever the interrupt was triggered. If
+                you use poll(2), set the events POLLPRI and POLLERR. If you
+                use select(2), set the file descriptor in exceptfds. After
+                poll(2) returns, either lseek(2) to the beginning of the sysfs
+                file and read the new value or close the file and re-open it
+                to read the value.
+ */
+
+public class GPIOEnum {
+    //Direction
+    public final static int IN = 1; 
+    public final static int OUT = 2; 
+    
+    //Value
+    public final static int LOW = 0;
+    public final static int HIGH = 1;
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
new file mode 100644
index 00000000000..01c886b305e
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/HardwareControler.java
@@ -0,0 +1,89 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+
+public class HardwareControler
+{
+    /* I/O */
+    static public native int open(String devName, int flags);
+    static public native int write(int fd, byte[] data);
+    static public native int read(int fd, byte[] buf, int len);
+    static public native int select(int fd, int sec, int usec);
+    static public native void close(int fd);
+    static public native int ioctlWithIntValue(int fd, int cmd, int value);
+    static public native int ioctl(int fd, int cmd, byte[] buf);
+    
+    /* Serial Port */
+    static public native int openSerialPort( String devName, long baud, int dataBits, int stopBits );
+    static public native int openSerialPortEx( String devName
+            , long baud
+            , int dataBits
+            , int stopBits
+            , String parityBit
+            , String flowCtrl
+            );
+    
+    /* LED */
+    static public native int setLedState( int ledID, int ledState );
+    
+    /* PWM */
+    static public native int PWMPlay(int frequency);
+    static public native int PWMStop();
+    static public native int PWMPlayEx(int gpioPin, int frequency);
+    static public native int PWMStopEx(int gpioPin);
+    
+    /* ADC */
+    static public native int readADC();
+    static public native int readADCWithChannel(int channel);
+    static public native int[] readADCWithChannels(int[] channels);
+    
+    /* I2C */
+    static public native int setI2CSlave(int fd, int slave);
+    static public native int setI2CTimeout(int fd, int timeout);
+    static public native int setI2CRetries(int fd, int retries);
+    static public native int I2CReadByteData(int fd, int pos, int wait_us);
+    static public native int I2CReadByte(int fd, int wait_us);
+    static public native int I2CWriteByteData(int fd, int pos, byte byteData, int wait_us);
+    static public native int I2CWriteByte(int fd, byte byteData, int wait_us);
+
+    /* Discard */ static public native int readByteFromI2C(int fd, int pos, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C(int fd, int pos, byte byteData, int wait_ms);
+    /* Discard */ static public native int writeByteToI2C2(int fd, byte byteData, int wait_ms);
+    
+    /* SPI */
+    static public native int setSPIWriteBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIReadBitsPerWord( int spi_fd, int bits );
+    static public native int setSPIBitOrder( int spi_fd, int order);
+    static public native int setSPIClockDivider( int spi_fd, int divider);
+    static public native int setSPIMaxSpeed( int spi_fd, int spi_speed);
+    static public native int setSPIDataMode( int spi_fd, int mode);
+    static public native int SPItransferOneByte( int spi_fd, byte byteData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int SPItransferBytes(int spi_fd, byte[] writeData, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);    
+    static public native int writeBytesToSPI(int spi_fd, byte[] writeData, int spi_delay, int spi_speed, int spi_bits);
+    static public native int readBytesFromSPI(int spi_fd, byte[] readBuff, int spi_delay, int spi_speed, int spi_bits);
+    
+    /* GPIO */
+    static public native int exportGPIOPin(int pin);
+    static public native int unexportGPIOPin(int pin);
+    //GPIOEnum.LOW or GPIOEnum.HIGH
+    static public native int setGPIOValue(int pin, int value);
+    static public native int getGPIOValue(int pin);
+    //GPIOEnum.IN or GPIOEnum.OUT
+    static public native int setGPIODirection(int pin, int direction);
+    static public native int getGPIODirection(int pin);
+
+    /* OldInterface: for EEPROM */
+    static public native int openI2CDevice();
+    static public native int writeByteDataToI2C(int fd, int pos, byte byteData);
+    static public native int readByteDataFromI2C(int fd, int pos);
+    
+    /* return BoardType.xxx */
+    static public native int getBoardType();
+    
+    static {
+        try {
+            System.loadLibrary("friendlyarm-things");
+        } catch (UnsatisfiedLinkError e) {
+            Log.d("HardwareControler", "libfriendlyarm-things library not found!");
+        }
+    }
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/SPI.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/SPI.java
new file mode 100644
index 00000000000..1c9a0156d1a
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/SPI.java
@@ -0,0 +1,108 @@
+package com.friendlyarm.FriendlyThings;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.SPIEnum;
+import com.friendlyarm.FriendlyThings.GPIOEnum;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+
+public class SPI {
+    private static final String TAG = "com.friendlyarm.FriendlyThings.SPI";
+    private int spi_mode = 0;
+    private int spi_bits = 8;
+    private int spi_delay = 0;
+    private int spi_speed = 500000;
+    private int spi_byte_order = SPIEnum.LSBFIRST;
+    
+    private static final String devName = "/dev/spidev1.0";
+    private int spi_fd = -1;
+    
+    public void begin() {
+        spi_fd = HardwareControler.open( devName, FileCtlEnum.O_RDWR );
+        if (spi_fd >= 0) {
+            Log.d(TAG, "open " + devName + "ok!");
+    
+            /* spi init */
+            HardwareControler.setSPIWriteBitsPerWord( spi_fd, spi_bits );
+            HardwareControler.setSPIReadBitsPerWord( spi_fd, spi_bits );
+        } else {
+            Log.d(TAG, "open " + devName + "failed!");
+            spi_fd = -1;
+        }
+    }
+    
+    public void end() {
+        if (spi_fd != -1) {
+            HardwareControler.close(spi_fd);
+            spi_fd = -1;
+        }
+    }
+    
+    public void setBitOrder(int order) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_byte_order = SPIEnum.MSBFIRST;
+        if(spi_byte_order == SPIEnum.LSBFIRST) {
+            spi_mode |=  SPIEnum.SPI_LSB_FIRST;
+        } else {
+            spi_mode &= ~SPIEnum.SPI_LSB_FIRST;
+        }
+        HardwareControler.setSPIBitOrder( spi_fd, spi_byte_order );
+
+    }
+    
+    public void setClockDivider(int divider) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        spi_speed = 66666666/(2*(divider+1));
+        if(spi_speed > 500000) {    
+            spi_speed = 500000;
+        }
+        HardwareControler.setSPIClockDivider( spi_fd, divider);
+    }
+    
+    public void setDataMode(int mode) {
+        if (spi_fd < 0) {
+            return ;
+        }
+        switch(mode)
+        {
+            case SPIEnum.SPI_MODE0:
+                spi_mode &= ~(SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            case SPIEnum.SPI_MODE1:
+                spi_mode &= ~(SPIEnum.SPI_CPOL);
+                spi_mode |= (SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE2:
+                spi_mode |= (SPIEnum.SPI_CPOL);
+                spi_mode &= ~(SPIEnum.SPI_CPHA);
+                break;
+            case SPIEnum.SPI_MODE3:
+                spi_mode |= (SPIEnum.SPI_CPHA|SPIEnum.SPI_CPOL);
+                break;
+            default:
+                Log.e(TAG, "error data mode");
+        }
+        
+        HardwareControler.setSPIDataMode( spi_fd, spi_mode );
+    }
+    
+    public void setChipSelectPolarity(int cs, int active) {
+        
+    }
+    
+    public void chipSelect(int cs) {
+        
+    }
+    
+    public byte transfer(int value) {
+        if (spi_fd < 0) {
+            return 0;
+        }
+        return (byte) HardwareControler.SPItransferOneByte(spi_fd, (byte) value, spi_delay, spi_speed, spi_bits);
+    }
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
new file mode 100644
index 00000000000..95c7c907f45
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/SPIEnum.java
@@ -0,0 +1,42 @@
+package com.friendlyarm.FriendlyThings;
+public class SPIEnum {
+
+// SPIBitOrder
+    public final static int LSBFIRST = 0;  ///< LSB First
+    public final static int MSBFIRST = 1;   ///< MSB First
+
+// SPIMode
+    public final static int SPI_MODE0 = 0;  ///< CPOL = 0, CPHA = 0
+    public final static int SPI_MODE1 = 1;  ///< CPOL = 0, CPHA = 1
+    public final static int SPI_MODE2 = 2;  ///< CPOL = 1, CPHA = 0
+    public final static int SPI_MODE3 = 3;  ///< CPOL = 1, CPHA = 1
+    
+    
+    public final static int SPI_CPHA = 0x01;
+    public final static int SPI_CPOL = 0x02;
+    public final static int SPI_CS_HIGH = 0x04;
+    public final static int SPI_LSB_FIRST = 0x08;
+    public final static int SPI_3WIRE = 0x10;
+    public final static int SPI_LOOP = 0x20;
+    public final static int SPI_NO_CS = 0x40;
+    public final static int SPI_READY = 0x80;
+
+// SPIClockDivider
+    public final static int SPI_CLOCK_DIV65536 = 0;       ///< 65536 = 256us = 4kHz
+    public final static int SPI_CLOCK_DIV32768 = 32768;   ///< 32768 = 126us = 8kHz
+    public final static int SPI_CLOCK_DIV16384 = 16384;   ///< 16384 = 64us = 15.625kHz
+    public final static int SPI_CLOCK_DIV8192  = 8192;    ///< 8192 = 32us = 31.25kHz
+    public final static int SPI_CLOCK_DIV4096  = 4096;    ///< 4096 = 16us = 62.5kHz
+    public final static int SPI_CLOCK_DIV2048  = 2048;    ///< 2048 = 8us = 125kHz
+    public final static int SPI_CLOCK_DIV1024  = 1024;    ///< 1024 = 4us = 250kHz
+    public final static int SPI_CLOCK_DIV512   = 512;     ///< 512 = 2us = 500kHz
+    public final static int SPI_CLOCK_DIV256   = 256;     ///< 256 = 1us = 1MHz
+    public final static int SPI_CLOCK_DIV128   = 128;     ///< 128 = 500ns = = 2MHz
+    public final static int SPI_CLOCK_DIV64    = 64;      ///< 64 = 250ns = 4MHz
+    public final static int SPI_CLOCK_DIV32    = 32;      ///< 32 = 125ns = 8MHz
+    public final static int SPI_CLOCK_DIV16    = 16;      ///< 16 = 50ns = 20MHz
+    public final static int SPI_CLOCK_DIV8     = 8;       ///< 8 = 25ns = 40MHz
+    public final static int SPI_CLOCK_DIV4     = 4;       ///< 4 = 12.5ns 80MHz
+    public final static int SPI_CLOCK_DIV2     = 2;       ///< 2 = 6.25ns = 160MHz
+    public final static int SPI_CLOCK_DIV1     = 1;       ///< 0 = 256us = 4kHz
+ }
\ No newline at end of file
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
new file mode 100644
index 00000000000..21a99287fb6
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/FriendlyThings/WatchDogEnum.java
@@ -0,0 +1,37 @@
+package com.friendlyarm.FriendlyThings;
+
+public class WatchDogEnum {
+    /* include/uapi/linux/watchdog.h */
+    public final static int WDIOC_GETSUPPORT = 0x80285700;
+    public final static int WDIOC_GETSTATUS = 0x80045701;
+    public final static int WDIOC_GETBOOTSTATUS = 0x80045702;
+    public final static int WDIOC_GETTEMP = 0x80045703;
+    public final static int WDIOC_SETOPTIONS = 0x80045704;
+    public final static int WDIOC_KEEPALIVE = 0x80045705;
+    public final static int WDIOC_SETTIMEOUT = 0xC0045706;
+    public final static int WDIOC_GETTIMEOUT = 0x80045707;
+    public final static int WDIOC_SETPRETIMEOUT = 0xC0045708;
+    public final static int WDIOC_GETPRETIMEOUT = 0x80045709;
+    public final static int WDIOC_GETTIMELEFT = 0x8004570A;
+
+    public final static int WDIOF_UNKNOWN = -1;  /* Unknown flag error */
+    public final static int WDIOS_UNKNOWN = -1;  /* Unknown status error */
+
+    public final static int WDIOF_OVERHEAT = 0x0001;  /* Reset due to CPU overheat */
+    public final static int WDIOF_FANFAULT = 0x0002;  /* Fan failed */
+    public final static int WDIOF_EXTERN1 = 0x0004;  /* External relay 1 */
+    public final static int WDIOF_EXTERN2 = 0x0008;  /* External relay 2 */
+    public final static int WDIOF_POWERUNDER = 0x0010;  /* Power bad/power fault */
+    public final static int WDIOF_CARDRESET = 0x0020;  /* Card previously reset the CPU */
+    public final static int WDIOF_POWEROVER = 0x0040;  /* Power over voltage */
+    public final static int WDIOF_SETTIMEOUT = 0x0080;  /* Set timeout (in seconds) */
+    public final static int WDIOF_MAGICCLOSE = 0x0100;  /* Supports magic close char */
+    public final static int WDIOF_PRETIMEOUT = 0x0200;  /* Pretimeout (in seconds), get/set */
+    public final static int WDIOF_ALARMONLY = 0x0400;  /* Watchdog triggers a management or other external alarm not a reboot */
+    public final static int WDIOF_KEEPALIVEPING = 0x8000;  /* Keep alive ping reply */
+
+    public final static int WDIOS_DISABLECARD = 0x0001;  /* Turn off the watchdog timer */
+    public final static int WDIOS_ENABLECARD = 0x0002;  /* Turn on the watchdog timer */
+    public final static int WDIOS_TEMPPANIC = 0x0004;  /* Kernel panic on temperature trip */
+
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/Utils/CommonFuncs.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/Utils/CommonFuncs.java
new file mode 100644
index 00000000000..000ab68382a
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/Utils/CommonFuncs.java
@@ -0,0 +1,26 @@
+package com.friendlyarm.Utils;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.widget.Toast;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.content.Context;
+import android.content.DialogInterface;
+
+public class CommonFuncs {
+    public static void showAlertDialog(Context context, String message) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setMessage(message)
+                .setCancelable(false)
+                .setPositiveButton("Close",
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, int id) {
+                            }
+                        });
+        AlertDialog alert = builder.create();
+        alert.show();
+    }
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/WatchDogDemo/WatchdogSampleActivity.java b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/WatchDogDemo/WatchdogSampleActivity.java
new file mode 100644
index 00000000000..7a13bcc7fdb
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/src/com/friendlyarm/WatchDogDemo/WatchdogSampleActivity.java
@@ -0,0 +1,133 @@
+package com.friendlyarm.WatchDogDemo;
+
+import com.friendlyarm.FriendlyThings.HardwareControler;
+import com.friendlyarm.FriendlyThings.FileCtlEnum;
+import com.friendlyarm.FriendlyThings.WatchDogEnum;
+import com.friendlyarm.FriendlyThings.BoardType;
+
+import com.friendlyarm.WatchDogDemo.R;
+import com.friendlyarm.Utils.CommonFuncs;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.widget.TextView;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.view.View.OnClickListener;
+import android.widget.CheckBox;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Toast;
+import java.util.Timer;
+import java.util.TimerTask;
+import android.os.Handler;
+import android.os.Message;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import android.net.Uri;
+import android.content.Intent;
+
+public class WatchdogSampleActivity extends Activity {
+    private static final String TAG = "WatchDogDemo";
+    private int mWatchDogFD = -1;
+    Button mStartButton;
+    Button mFeedButton;
+    TextView mCountDownTextView;
+    TextView mWillResetTextView;
+    private Timer mTimer = new Timer();
+    int nWatchDogTimeout = 21;  //rk3399: 1,2,5,10,21
+    int mCountDown = nWatchDogTimeout;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mStartButton = (Button)findViewById(R.id.button_start);
+        mFeedButton = (Button)findViewById(R.id.button_feed);
+        mCountDownTextView = (TextView)findViewById(R.id.text_countdown);
+        mWillResetTextView = (TextView)findViewById(R.id.text_willreset);
+        mCountDownTextView.setText(Integer.toString(mCountDown) + "s");
+    }
+
+    private Handler mHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case 1:
+                mCountDownTextView.setText(Integer.toString(mCountDown) + "s");
+                if (mCountDown == 0) {
+                    mWillResetTextView.setText("Keepalive missed, machine will reset");
+                }
+                break;
+            }
+            super.handleMessage(msg);
+        }
+    };
+
+    private TimerTask mTask = new TimerTask() {
+        public void run() {
+            mCountDown --;
+            if (mCountDown < 0) {
+                mCountDown = 0;
+            }
+            Message message = new Message();
+            message.what = 1;
+            mHandler.sendMessage(message);
+        }
+    };
+
+    public void onStartPressed(View view) {
+        if (mWatchDogFD < 0) {
+            mWatchDogFD = HardwareControler.open("/dev/watchdog", FileCtlEnum.O_WRONLY);
+            if (mWatchDogFD < 0) {
+                Log.d(TAG, "Fail to open /dev/watchdog");
+            } else {
+                mStartButton.setEnabled(false);
+                Log.d(TAG, "Open /dev/watchdog OK");
+
+                ByteBuffer byteBuffer = ByteBuffer.allocate(4);
+                byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
+                byteBuffer.putInt(nWatchDogTimeout);
+                if (HardwareControler.ioctl(mWatchDogFD, WatchDogEnum.WDIOC_SETTIMEOUT, byteBuffer.array()) < 0) {
+                    Log.d(TAG, "Fail to ioctl WDIOC_SETTIMEOUT");
+                } else {
+                    ByteBuffer wrapped = ByteBuffer.wrap(byteBuffer.array()); 
+                    wrapped.order(ByteOrder.LITTLE_ENDIAN);
+                    int num = wrapped.getInt();
+                    Log.d(TAG, "Set Wathdog timeout OK, set value: " + Integer.toString(num));
+                }
+
+                byte[] timeoutGet = { 0, 0, 0, 0 }; 
+                if (HardwareControler.ioctl(mWatchDogFD, WatchDogEnum.WDIOC_GETTIMEOUT, timeoutGet) < 0) {
+                    Log.d(TAG, "Fail to ioctl WDIOC_GETTIMEOUT");
+                } else {
+                    ByteBuffer wrapped = ByteBuffer.wrap(timeoutGet);
+                    wrapped.order(ByteOrder.LITTLE_ENDIAN);
+                    int num = wrapped.getInt();
+                    Log.d(TAG, "get Wathdog timeout OK, current value: " + Integer.toString(num));
+                    mCountDown = nWatchDogTimeout = num;
+                    mCountDownTextView.setText(Long.toString(mCountDown) + "s");
+                }
+                mTimer.schedule(mTask, 0, 1000);
+            }
+        }
+    }
+
+    public void onFeedPressed(View view) {
+        if (mWatchDogFD>0) {
+            HardwareControler.write(mWatchDogFD, "a".getBytes());
+            mCountDown = nWatchDogTimeout;
+            mCountDownTextView.setText(Long.toString(mCountDown) + "s");
+            mWillResetTextView.setText("");
+        }
+    }
+
+    public void onMoreSamplesPressed(View view) {
+           Uri uri = Uri.parse("http://wiki.friendlyelec.com/wiki/index.php/FriendlyThings_for_Rockchip");
+           Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+           startActivity(intent); 
+     }
+}
diff --git a/vendor/friendlyelec/apps/WatchDogDemo/sync.sh b/vendor/friendlyelec/apps/WatchDogDemo/sync.sh
new file mode 100755
index 00000000000..0614251b55a
--- /dev/null
+++ b/vendor/friendlyelec/apps/WatchDogDemo/sync.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+adb root; adb remount; adb sync; adb reboot;
diff --git a/vendor/friendlyelec/apps/device-partial.mk b/vendor/friendlyelec/apps/device-partial.mk
new file mode 100644
index 00000000000..7ed3dbc96cd
--- /dev/null
+++ b/vendor/friendlyelec/apps/device-partial.mk
@@ -0,0 +1,31 @@
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# FriendlyThings examples
+# http://wiki.friendlyelec.com/wiki/index.php/FriendlyThings_for_Rockchip
+PRODUCT_PACKAGES += \
+	libfriendlyarm-things \
+	SerialPortDemo \
+	WatchDogDemo \
+	RTCDemo \
+	Dual-Camera \
+	GPIO_LED_Demo
+
+# PRODUCT_PACKAGES += LCD1602
+# PRODUCT_PACKAGES += ADCDemo
+# PRODUCT_PACKAGES += PWMDemo
+# PRODUCT_PACKAGES += SPI-OLED
+
diff --git a/vendor/friendlyelec/apps/prebuilt/Android.mk b/vendor/friendlyelec/apps/prebuilt/Android.mk
new file mode 100644
index 00000000000..28f19f964be
--- /dev/null
+++ b/vendor/friendlyelec/apps/prebuilt/Android.mk
@@ -0,0 +1,29 @@
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libfriendlyarm-things
+LOCAL_MODULE_OWNER := friendlyarm
+LOCAL_SRC_FILES := libfriendlyarm-things.so
+LOCAL_CHECK_ELF_FILES := false
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+include $(BUILD_PREBUILT)
+
diff --git a/vendor/friendlyelec/apps/prebuilt/libfriendlyarm-things.so b/vendor/friendlyelec/apps/prebuilt/libfriendlyarm-things.so
new file mode 100755
index 00000000000..fa484249fec
Binary files /dev/null and b/vendor/friendlyelec/apps/prebuilt/libfriendlyarm-things.so differ