NFC host card emulation samples (reader + writer)

Demonstrates how to implement a virtual loyalty card using NFC HCE,
along with a virtual terminal for reading this loyalty card.

Change-Id: Ifb1a47208148ee3867980ea90a50b6df474f808c
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/.gitignore b/connectivity/nfc/CardEmulation/CardEmulationSample/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 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.
+src/template/
+src/common/
+build.gradle
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/README-fragmentview.txt b/connectivity/nfc/CardEmulation/CardEmulationSample/README-fragmentview.txt
new file mode 100644
index 0000000..38d903f
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/README-fragmentview.txt
@@ -0,0 +1,37 @@
+<!--
+        Copyright 2013 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.
+-->
+
+Steps to implement FragmentView template:
+-in template-params.xml.ftl:
+    -add the following line to common imports
+        <common src="activities"/>
+
+-Add a Fragment to show behavior.  In your MainActivity.java class, it will reference a Fragment
+ called (yourProjectName)Fragment.java.  Create that file in your project, using the "main" source
+ folder instead of "common" or "templates".
+   For instance, if your package name is com.example.foo, create the file
+   src/main/java/com/example/foo/FooFragment.java
+
+
+-Within this fragment, make sure that the onCreate method has the line
+ "setHasOptionsMenu(true);", to enable the fragment to handle menu events.
+
+-In order to override menu events, override onOptionsItemSelected.
+
+-refer to sampleSamples/fragmentViewSample for a reference implementation of a
+project built on this template.
+
+
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/proguard-project.txt b/connectivity/nfc/CardEmulation/CardEmulationSample/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/AndroidManifest.xml b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4a4af08
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/AndroidManifest.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.cardemulation"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <!-- Card emulation was introduced in API 19. -->
+    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+    <uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
+    <uses-permission android:name="android.permission.NFC" />
+
+    <application android:allowBackup="true"
+        android:label="@string/app_name"
+        android:icon="@drawable/ic_launcher"
+        android:theme="@style/AppTheme">
+
+        <!-- Basic UI for sample discoverability. -->
+        <activity android:name=".MainActivity"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <!-- BEGIN_INCLUDE(CardEmulationManifest) -->
+        <!-- Service for handling communication with NFC terminal. -->
+        <service android:name=".CardService"
+                 android:exported="true"
+                 android:permission="android.permission.BIND_NFC_SERVICE">
+            <!-- Intent filter indicating that we support card emulation. -->
+            <intent-filter>
+                <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+            <!-- Required XML configuration file, listing the AIDs that we are emulating cards
+                 for. This defines what protocols our card emulation service supports. -->
+            <meta-data android:name="android.nfc.cardemulation.host_apdu_service"
+                       android:resource="@xml/aid_list"/>
+        </service>
+        <!-- END_INCLUDE(CardEmulationManifest) -->
+    </application>
+
+
+</manifest>
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/AccountStorage.java b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/AccountStorage.java
new file mode 100644
index 0000000..56a69a0
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/AccountStorage.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package com.example.android.cardemulation;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.util.Log;
+
+/**
+ * Utility class for persisting account numbers to disk.
+ *
+ * <p>The default SharedPreferences instance is used as the backing storage. Values are cached
+ * in memory for performance.
+ *
+ * <p>This class is thread-safe.
+ */
+public class AccountStorage {
+    private static final String PREF_ACCOUNT_NUMBER = "account_number";
+    private static final String DEFAULT_ACCOUNT_NUMBER = "00000000";
+    private static final String TAG = "AccountStorage";
+    private static String sAccount = null;
+    private static final Object sAccountLock = new Object();
+
+    public static void SetAccount(Context c, String s) {
+        synchronized(sAccountLock) {
+            Log.i(TAG, "Setting account number: " + s);
+            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+            prefs.edit().putString(PREF_ACCOUNT_NUMBER, s);
+            sAccount = s;
+        }
+    }
+
+    public static String GetAccount(Context c) {
+        synchronized (sAccountLock) {
+            if (sAccount == null) {
+                SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
+                String account = prefs.getString(PREF_ACCOUNT_NUMBER, DEFAULT_ACCOUNT_NUMBER);
+                sAccount = account;
+            }
+            return sAccount;
+        }
+    }
+}
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/CardEmulationFragment.java b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/CardEmulationFragment.java
new file mode 100644
index 0000000..f26efda
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/CardEmulationFragment.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package com.example.android.cardemulation;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+/**
+ * Generic UI for sample discovery.
+ */
+public class CardEmulationFragment extends Fragment {
+
+    public static final String TAG = "CardEmulationFragment";
+
+    /** Called when sample is created. Displays generic UI with welcome text. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        View v = inflater.inflate(R.layout.main_fragment, container, false);
+        EditText account = (EditText) v.findViewById(R.id.card_account_field);
+        account.setText(AccountStorage.GetAccount(getActivity()));
+        account.addTextChangedListener(new AccountUpdater());
+        return v;
+    }
+
+
+    private class AccountUpdater implements TextWatcher {
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+            // Not implemented.
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            // Not implemented.
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+            String account = s.toString();
+            AccountStorage.SetAccount(getActivity(), account);
+        }
+    }
+}
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/CardService.java b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/CardService.java
new file mode 100644
index 0000000..a409d28
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/java/com/example/android/cardemulation/CardService.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package com.example.android.cardemulation;
+
+import android.nfc.cardemulation.HostApduService;
+import android.os.Bundle;
+import com.example.android.common.logger.Log;
+
+import java.util.Arrays;
+
+/**
+ * This is a sample APDU Service which demonstrates how to interface with the card emulation support
+ * added in Android 4.4, KitKat.
+ *
+ * <p>This sample replies to any requests sent with the string "Hello World". In real-world
+ * situations, you would need to modify this code to implement your desired communication
+ * protocol.
+ *
+ * <p>This sample will be invoked for any terminals selecting AIDs of 0xF11111111, 0xF22222222, or
+ * 0xF33333333. See src/main/res/xml/aid_list.xml for more details.
+ *
+ * <p class="note">Note: This is a low-level interface. Unlike the NdefMessage many developers
+ * are familiar with for implementing Android Beam in apps, card emulation only provides a
+ * byte-array based communication channel. It is left to developers to implement higher level
+ * protocol support as needed.
+ */
+public class CardService extends HostApduService {
+    private static final String TAG = "CardService";
+    // AID for our loyalty card service.
+    private static final String SAMPLE_LOYALTY_CARD_AID = "F222222222";
+    // ISO-DEP command HEADER for selecting an AID.
+    // Format: [Class | Instruction | Parameter 1 | Parameter 2]
+    private static final String SELECT_APDU_HEADER = "00A40400";
+    // "OK" status word sent in response to SELECT AID command (0x9000)
+    private static final byte[] SELECT_OK_SW = HexStringToByteArray("9000");
+    // "UNKNOWN" status word sent in response to invalid APDU command (0x0000)
+    private static final byte[] UNKNOWN_CMD_SW = HexStringToByteArray("0000");
+    private static final byte[] SELECT_APDU = BuildSelectApdu(SAMPLE_LOYALTY_CARD_AID);
+
+    /**
+     * Called if the connection to the NFC card is lost, in order to let the application know the
+     * cause for the disconnection (either a lost link, or another AID being selected by the
+     * reader).
+     *
+     * @param reason Either DEACTIVATION_LINK_LOSS or DEACTIVATION_DESELECTED
+     */
+    @Override
+    public void onDeactivated(int reason) { }
+
+    /**
+     * This method will be called when a command APDU has been received from a remote device. A
+     * response APDU can be provided directly by returning a byte-array in this method. In general
+     * response APDUs must be sent as quickly as possible, given the fact that the user is likely
+     * holding his device over an NFC reader when this method is called.
+     *
+     * <p class="note">If there are multiple services that have registered for the same AIDs in
+     * their meta-data entry, you will only get called if the user has explicitly selected your
+     * service, either as a default or just for the next tap.
+     *
+     * <p class="note">This method is running on the main thread of your application. If you
+     * cannot return a response APDU immediately, return null and use the {@link
+     * #sendResponseApdu(byte[])} method later.
+     *
+     * @param commandApdu The APDU that received from the remote device
+     * @param extras A bundle containing extra data. May be null.
+     * @return a byte-array containing the response APDU, or null if no response APDU can be sent
+     * at this point.
+     */
+    // BEGIN_INCLUDE(processCommandApdu)
+    @Override
+    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
+        Log.i(TAG, "Received APDU: " + ByteArrayToHexString(commandApdu));
+        // If the APDU matches the SELECT AID command for this service,
+        // send the loyalty card account number, followed by a SELECT_OK status trailer (0x9000).
+        if (Arrays.equals(SELECT_APDU, commandApdu)) {
+            String account = AccountStorage.GetAccount(this);
+            byte[] accountBytes = account.getBytes();
+            Log.i(TAG, "Sending account number: " + account);
+            return ConcatArrays(accountBytes, SELECT_OK_SW);
+        } else {
+            return UNKNOWN_CMD_SW;
+        }
+    }
+    // END_INCLUDE(processCommandApdu)
+
+    /**
+     * Build APDU for SELECT AID command. This command indicates which service a reader is
+     * interested in communicating with. See ISO 7816-4.
+     *
+     * @param aid Application ID (AID) to select
+     * @return APDU for SELECT AID command
+     */
+    public static byte[] BuildSelectApdu(String aid) {
+        // Format: [CLASS | INSTRUCTION | PARAMETER 1 | PARAMETER 2 | LENGTH | DATA]
+        return HexStringToByteArray(SELECT_APDU_HEADER + String.format("%02X",
+                aid.length() / 2) + aid);
+    }
+
+    /**
+     * Utility method to convert a byte array to a hexadecimal string.
+     *
+     * @param bytes Bytes to convert
+     * @return String, containing hexadecimal representation.
+     */
+    public static String ByteArrayToHexString(byte[] bytes) {
+        final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+        char[] hexChars = new char[bytes.length * 2]; // Each byte has two hex characters (nibbles)
+        int v;
+        for (int j = 0; j < bytes.length; j++) {
+            v = bytes[j] & 0xFF; // Cast bytes[j] to int, treating as unsigned value
+            hexChars[j * 2] = hexArray[v >>> 4]; // Select hex character from upper nibble
+            hexChars[j * 2 + 1] = hexArray[v & 0x0F]; // Select hex character from lower nibble
+        }
+        return new String(hexChars);
+    }
+
+    /**
+     * Utility method to convert a hexadecimal string to a byte string.
+     *
+     * <p>Behavior with input strings containing non-hexadecimal characters is undefined.
+     *
+     * @param s String containing hexadecimal characters to convert
+     * @return Byte array generated from input
+     * @throws java.lang.IllegalArgumentException if input length is incorrect
+     */
+    public static byte[] HexStringToByteArray(String s) throws IllegalArgumentException {
+        int len = s.length();
+        if (len % 2 == 1) {
+            throw new IllegalArgumentException("Hex string must have even number of characters");
+        }
+        byte[] data = new byte[len / 2]; // Allocate 1 byte per 2 hex characters
+        for (int i = 0; i < len; i += 2) {
+            // Convert each character into a integer (base-16), then bit-shift into place
+            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                    + Character.digit(s.charAt(i+1), 16));
+        }
+        return data;
+    }
+
+    /**
+     * Utility method to concatenate two byte arrays.
+     * @param first First array
+     * @param rest Any remaining arrays
+     * @return Concatenated copy of input arrays
+     */
+    public static byte[] ConcatArrays(byte[] first, byte[]... rest) {
+        int totalLength = first.length;
+        for (byte[] array : rest) {
+            totalLength += array.length;
+        }
+        byte[] result = Arrays.copyOf(first, totalLength);
+        int offset = first.length;
+        for (byte[] array : rest) {
+            System.arraycopy(array, 0, result, offset, array.length);
+            offset += array.length;
+        }
+        return result;
+    }
+}
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-hdpi/ic_launcher.png b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..0cebab5
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-mdpi/ic_launcher.png b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..bccac40
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xhdpi/ic_launcher.png b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..1a6a328
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xxhdpi/card_background.png b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xxhdpi/card_background.png
new file mode 100644
index 0000000..86a7ba7
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xxhdpi/card_background.png
Binary files differ
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xxhdpi/ic_launcher.png b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..063dd25
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/layout/main_fragment.xml b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/layout/main_fragment.xml
new file mode 100644
index 0000000..2c69743
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/layout/main_fragment.xml
@@ -0,0 +1,65 @@
+<!--
+Copyright (C) 2013 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.
+-->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="380dp"
+    android:layout_height="242.25dp"
+    android:layout_gravity="center"
+    android:layout_margin="20dp">
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:src="@drawable/card_background"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="20dp"
+        android:layout_gravity="center"
+        android:clickable="true">
+        <TextView
+            android:id="@+id/card_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/card_title"
+            android:fontFamily="sans-serif-condensed"
+            android:textStyle="bold"
+            android:textSize="32dp"
+            />
+        <TextView
+            android:id="@+id/card_account_label"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/account_number"
+            android:fontFamily="sans-serif"
+            android:textStyle="bold"
+            android:textSize="18dp"
+            android:layout_marginTop="40dp"
+            />
+        <EditText
+            android:id="@+id/card_account_field"
+            android:width="360dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif-condensed"
+            android:textStyle="bold"
+            android:textSize="42dp"
+            android:singleLine="true"
+            android:inputType="number" />
+    </LinearLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/values/strings.xml b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/values/strings.xml
new file mode 100644
index 0000000..f708284
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+    <string name="service_name">CardEmulation Sample</string>
+    <string name="card_title">Sample Loyalty Card</string>
+    <string name="account_number">Account Number</string>
+</resources>
\ No newline at end of file
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/xml/aid_list.xml b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/xml/aid_list.xml
new file mode 100644
index 0000000..15ed754
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/src/main/res/xml/aid_list.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2013 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.
+-->
+
+<!-- This file defines which AIDs this application should emulate cards for.
+
+     Vendor-specific AIDs should always start with an "F", according to the ISO 7816 spec. We
+     recommended vendor-specific AIDs be at least 6 characters long, to provide sufficient
+     uniqueness. Note, however, that longer AIDs may impose a burden on non-Android NFC terminals.
+     AIDs may not exceed 32 characters (16 bytes).
+
+     Additionally, AIDs must always contain an even number of characters, in hexadecimal format.
+
+     In order to avoid prompting the user to select which service they want to use when the device
+     is scanned, this app must be selected as the default handler for an AID group by the user, or
+     the terminal must select *all* AIDs defined in the category simultaneously ("exact match").
+-->
+<!-- BEGIN_INCLUDE(CardEmulationXML) -->
+<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:description="@string/service_name"
+    android:requireDeviceUnlock="false">
+    <!--
+    If category="payment" is used for any aid-groups, you must also add an android:apduServiceBanner
+    attribute above, like so:
+
+    android:apduServiceBanner="@drawable/settings_banner"
+
+     apduServiceBanner should be 260x96 dp. In pixels, that works out to...
+       - drawable-xxhdpi: 780x288 px
+       - drawable-xhdpi:  520x192 px
+       - drawable-hdpi:   390x144 px
+       - drawable-mdpi:   260x96  px
+
+    The apduServiceBanner is displayed in the "Tap & Pay" menu in the system Settings app, and
+    is only displayed for apps which implement the "payment" AID category.
+
+    Since this sample is implementing a non-standard card type (a loyalty card, specifically), we
+    do not need to define a banner.
+
+    Important: category="payment" should only be used for industry-standard payment cards. If you are
+        implementing a closed-loop payment system (e.g. stored value cards for a specific merchant
+        or transit system), use category="other". This is because only one "payment" card may be
+        active at a time, whereas all "other" cards are active simultaneously (subject to AID
+        dispatch).
+    -->
+
+    <aid-group android:description="@string/card_title" android:category="other">
+        <aid-filter android:name="F222222222"/>
+    </aid-group>
+<!-- END_INCLUDE(CardEmulationXML) -->
+</host-apdu-service>
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/tests/AndroidManifest.xml b/connectivity/nfc/CardEmulation/CardEmulationSample/tests/AndroidManifest.xml
new file mode 100644
index 0000000..447d041
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/tests/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2013 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.
+  -->
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="${sample.package}.tests"
+          android:versionCode="1"
+          android:versionName="1.0">
+
+    <uses-sdk
+            android:minSdkVersion="19"
+            android:targetSdkVersion="19" />
+
+    <!-- We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases. -->
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!--
+    Specifies the instrumentation test runner used to run the tests.
+    -->
+    <instrumentation
+            android:name="android.test.InstrumentationTestRunner"
+            android:targetPackage="com.example.android.cardemulation"
+            android:label="Tests for com.example.android.cardemulation" />
+
+</manifest>
\ No newline at end of file
diff --git a/connectivity/nfc/CardEmulation/CardEmulationSample/tests/src/com/example/android/cardemulation/tests/SampleTests.java b/connectivity/nfc/CardEmulation/CardEmulationSample/tests/src/com/example/android/cardemulation/tests/SampleTests.java
new file mode 100644
index 0000000..b9828c2
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/CardEmulationSample/tests/src/com/example/android/cardemulation/tests/SampleTests.java
@@ -0,0 +1,169 @@
+/*
+* Copyright 2013 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.
+*/
+/*
+* Copyright (C) 2013 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.
+*/
+package com.example.android.cardemulation.tests;
+
+import com.example.android.cardemulation.*;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+* Tests for CardEmulation sample.
+*/
+public class SampleTests extends ActivityInstrumentationTestCase2<MainActivity> {
+
+    private MainActivity mTestActivity;
+    private CardEmulationFragment mTestFragment;
+
+    public SampleTests() {
+        super(MainActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Starts the activity under test using the default Intent with:
+        // action = {@link Intent#ACTION_MAIN}
+        // flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+        // All other fields are null or empty.
+        mTestActivity = getActivity();
+        mTestFragment = (CardEmulationFragment)
+            mTestActivity.getSupportFragmentManager().getFragments().get(1);
+    }
+
+    /**
+    * Test if the test fixture has been set up correctly.
+    */
+    public void testPreconditions() {
+        //Try to add a message to add context to your assertions. These messages will be shown if
+        //a tests fails and make it easy to understand why a test failed
+        assertNotNull("mTestActivity is null", mTestActivity);
+        assertNotNull("mTestFragment is null", mTestFragment);
+    }
+
+    /**
+     * Test converting from a hex string to binary.
+     */
+    public void testHexToBinary() {
+        final byte[] testData = {(byte) 0xc0, (byte) 0xff, (byte) 0xee};
+        final byte[] output = CardService.HexStringToByteArray("C0FFEE");
+        for (int i = 0; i < testData.length; i++) {
+            assertEquals(testData[i], output[i]);
+        }
+    }
+
+    /**
+     * Test converting from binary to a hex string
+     */
+    public void testBinaryToHex() {
+        final byte[] input = {(byte) 0xc0, (byte) 0xff, (byte) 0xee};
+        final String output = CardService.ByteArrayToHexString(input);
+        assertEquals("C0FFEE", output);
+    }
+
+    /**
+     * Verify that account number is returned in response to APDU.
+     */
+    public void testRequestAccoutNumber() {
+        AccountStorage.SetAccount(this.getActivity(), "1234");
+        final byte[] command = {(byte) 0x00, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x05,
+                (byte) 0xF2, (byte) 0x22, (byte) 0x22, (byte) 0x22, (byte) 0x22};
+        final byte[] expectedResponse = {(byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34,
+                (byte) 0x90, (byte) 0x00};
+        final CardService cs = new CardService();
+        final byte[] output = cs.processCommandApdu(command, null);
+
+        assertEquals(expectedResponse.length, output.length);
+        for (int i = 0; i < expectedResponse.length; i++) {
+            assertEquals(expectedResponse[i], output[i]);
+        }
+
+    }
+
+
+    /**
+     * Verify that account number is returned in response to APDU.
+     */
+    public void testInvalidCommand() {
+        AccountStorage.SetAccount(this.getActivity(), "1234");
+        final byte[] command = {(byte) 0x01, (byte) 0xA4, (byte) 0x04, (byte) 0x00, (byte) 0x05,
+                (byte) 0xF2, (byte) 0x22, (byte) 0x22, (byte) 0x22, (byte) 0x22};
+        final byte[] expectedResponse = {(byte) 0x00, (byte) 0x00};
+        final CardService cs = new CardService();
+        final byte[] output = cs.processCommandApdu(command, null);
+
+        assertEquals(expectedResponse.length, output.length);
+        for (int i = 0; i < expectedResponse.length; i++) {
+            assertEquals(expectedResponse[i], output[i]);
+        }
+    }
+
+    /**
+     * Test functionality fo ConcatArrays method.
+     */
+    public void testArrayConcat() {
+        final byte[] a = {(byte) 0x01, (byte) 0x02};
+        final byte[] b = {(byte) 0x03, (byte) 0x04};
+        final byte[] c = {(byte) 0x05, (byte) 0x06};
+        final byte[] expected = {(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05,
+                (byte) 0x06};
+        final byte[] result = CardService.ConcatArrays(a, b, c);
+
+        assertEquals(expected.length, result.length);
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(expected[i], result[i]);
+        }
+    }
+
+    /**
+     * Test setting and getting account number
+     */
+    public void testSetAccountNumber() {
+        final String account = "3456";
+        AccountStorage.SetAccount(getActivity(), account);
+        this.assertEquals(account, AccountStorage.GetAccount(getActivity()));
+    }
+
+    /**
+     * Test building SELECT APDU from AID string.
+     */
+    public void testBuildSelectApdu() {
+        final String aid = "1234";
+        final byte[] expectedResult = {(byte) 0x00, (byte) 0xA4, 04, (byte) 0x00, (byte) 0x02,
+                (byte) 0x12, (byte) 0x34};
+        final byte[] result = CardService.BuildSelectApdu(aid);
+
+        assertEquals(expectedResult.length, result.length);
+        for (int i = 0; i < expectedResult.length; i++) {
+            assertEquals(expectedResult[i], result[i]);
+        }
+    }
+}
\ No newline at end of file
diff --git a/connectivity/nfc/CardEmulation/build.gradle b/connectivity/nfc/CardEmulation/build.gradle
new file mode 100644
index 0000000..c7f6491
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/build.gradle
@@ -0,0 +1,8 @@
+
+// BEGIN_EXCLUDE
+apply from: "../../../../../build/build.gradle"
+samplegen {
+  pathToBuild "../../../../../build"
+  pathToSamplesCommon "../../../common"
+}
+// END_EXCLUDE
diff --git a/connectivity/nfc/CardEmulation/buildSrc/build.gradle b/connectivity/nfc/CardEmulation/buildSrc/build.gradle
new file mode 100644
index 0000000..7cebf71
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/buildSrc/build.gradle
@@ -0,0 +1,15 @@
+repositories {
+    mavenCentral()
+}
+dependencies {
+    compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+    main {
+        groovy {
+            srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+        }
+    }
+}
+
diff --git a/connectivity/nfc/CardEmulation/gradle/wrapper/gradle-wrapper.jar b/connectivity/nfc/CardEmulation/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/connectivity/nfc/CardEmulation/gradle/wrapper/gradle-wrapper.properties b/connectivity/nfc/CardEmulation/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..861eddc
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.8-bin.zip
diff --git a/connectivity/nfc/CardEmulation/gradlew b/connectivity/nfc/CardEmulation/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/connectivity/nfc/CardEmulation/gradlew.bat b/connectivity/nfc/CardEmulation/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off

+@rem ##########################################################################

+@rem

+@rem  Gradle startup script for Windows

+@rem

+@rem ##########################################################################

+

+@rem Set local scope for the variables with windows NT shell

+if "%OS%"=="Windows_NT" setlocal

+

+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

+set DEFAULT_JVM_OPTS=

+

+set DIRNAME=%~dp0

+if "%DIRNAME%" == "" set DIRNAME=.

+set APP_BASE_NAME=%~n0

+set APP_HOME=%DIRNAME%

+

+@rem Find java.exe

+if defined JAVA_HOME goto findJavaFromJavaHome

+

+set JAVA_EXE=java.exe

+%JAVA_EXE% -version >NUL 2>&1

+if "%ERRORLEVEL%" == "0" goto init

+

+echo.

+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:findJavaFromJavaHome

+set JAVA_HOME=%JAVA_HOME:"=%

+set JAVA_EXE=%JAVA_HOME%/bin/java.exe

+

+if exist "%JAVA_EXE%" goto init

+

+echo.

+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:init

+@rem Get command-line arguments, handling Windowz variants

+

+if not "%OS%" == "Windows_NT" goto win9xME_args

+if "%@eval[2+2]" == "4" goto 4NT_args

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

+if "x%~1" == "x" goto execute

+

+set CMD_LINE_ARGS=%*

+goto execute

+

+:4NT_args

+@rem Get arguments from the 4NT Shell from JP Software

+set CMD_LINE_ARGS=%$

+

+:execute

+@rem Setup the command line

+

+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

+

+@rem Execute Gradle

+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

+

+:end

+@rem End local scope for the variables with windows NT shell

+if "%ERRORLEVEL%"=="0" goto mainEnd

+

+:fail

+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

+rem the _cmd.exe /c_ return code!

+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

+exit /b 1

+

+:mainEnd

+if "%OS%"=="Windows_NT" endlocal

+

+:omega

diff --git a/connectivity/nfc/CardEmulation/settings.gradle b/connectivity/nfc/CardEmulation/settings.gradle
new file mode 100644
index 0000000..32b4942
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/settings.gradle
@@ -0,0 +1 @@
+include 'CardEmulationSample'
diff --git a/connectivity/nfc/CardEmulation/template-params.xml b/connectivity/nfc/CardEmulation/template-params.xml
new file mode 100644
index 0000000..6613121
--- /dev/null
+++ b/connectivity/nfc/CardEmulation/template-params.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 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.
+-->
+<sample>
+    <name>CardEmulation</name>
+    <group>Connectivity</group>
+    <package>com.example.android.cardemulation</package>
+
+    <!-- change minSdk if needed-->
+    <minSdk>19</minSdk>
+
+    <strings>
+        <intro>
+            <![CDATA[
+            This sample demonstrates how to emulate an NFC card, using the "host card emulation"
+            feature added in Android 4.4. This sample makes the device appear as a loyalty card
+            whenever the screen is on and the user taps their device on an appropriately configured
+            NFC reader.
+
+            The "CardReader" sample can be used to read the loyalty card implemented in this sample.
+            ]]>
+        </intro>
+    </strings>
+
+    <template src="base"/>
+    <template src="FragmentView"/>
+    <common src="activities"/>
+    <common src="logger"/>
+
+</sample>
diff --git a/connectivity/nfc/CardReader/CardReaderSample/.gitignore b/connectivity/nfc/CardReader/CardReaderSample/.gitignore
new file mode 100644
index 0000000..6eb878d
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/.gitignore
@@ -0,0 +1,16 @@
+# Copyright 2013 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.
+src/template/
+src/common/
+build.gradle
diff --git a/connectivity/nfc/CardReader/CardReaderSample/README-fragmentview.txt b/connectivity/nfc/CardReader/CardReaderSample/README-fragmentview.txt
new file mode 100644
index 0000000..38d903f
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/README-fragmentview.txt
@@ -0,0 +1,37 @@
+<!--
+        Copyright 2013 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.
+-->
+
+Steps to implement FragmentView template:
+-in template-params.xml.ftl:
+    -add the following line to common imports
+        <common src="activities"/>
+
+-Add a Fragment to show behavior.  In your MainActivity.java class, it will reference a Fragment
+ called (yourProjectName)Fragment.java.  Create that file in your project, using the "main" source
+ folder instead of "common" or "templates".
+   For instance, if your package name is com.example.foo, create the file
+   src/main/java/com/example/foo/FooFragment.java
+
+
+-Within this fragment, make sure that the onCreate method has the line
+ "setHasOptionsMenu(true);", to enable the fragment to handle menu events.
+
+-In order to override menu events, override onOptionsItemSelected.
+
+-refer to sampleSamples/fragmentViewSample for a reference implementation of a
+project built on this template.
+
+
diff --git a/connectivity/nfc/CardReader/CardReaderSample/proguard-project.txt b/connectivity/nfc/CardReader/CardReaderSample/proguard-project.txt
new file mode 100644
index 0000000..0d8f171
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/proguard-project.txt
@@ -0,0 +1,20 @@
+ To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/AndroidManifest.xml b/connectivity/nfc/CardReader/CardReaderSample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a8ebd13
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/AndroidManifest.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.example.android.cardreader"
+    android:versionCode="1"
+    android:versionName="1.0">
+
+    <!-- NFC Reader Mode was added in API 19. -->
+    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19" />
+    <uses-permission android:name="android.permission.NFC" />
+    <uses-feature android:name="android.hardware.nfc" android:required="true" />
+
+    <application android:allowBackup="true"
+        android:label="@string/app_name"
+        android:icon="@drawable/ic_launcher"
+        android:theme="@style/AppTheme">
+        <activity android:name=".MainActivity"
+                  android:label="@string/app_name"
+                  android:launchMode="singleTop">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+
+            <!-- NFC-related intent filter. Allows application to handle messages from any
+                 NFC-A devices discovered. Other Android devices are required to support NFC-A.
+                 See: res/xml/nfc_tech_filter.xml -->
+            <intent-filter>
+                <action android:name="android.nfc.action.TECH_DISCOVERED" />
+            </intent-filter>
+            <meta-data
+                android:name="android.nfc.action.TECH_DISCOVERED"
+                android:resource="@xml/nfc_tech_filter" />
+        </activity>
+    </application>
+
+
+</manifest>
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/java/com/example/android/cardreader/CardReaderFragment.java b/connectivity/nfc/CardReader/CardReaderSample/src/main/java/com/example/android/cardreader/CardReaderFragment.java
new file mode 100644
index 0000000..3f27e9b
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/java/com/example/android/cardreader/CardReaderFragment.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+package com.example.android.cardreader;
+
+import android.app.Activity;
+import android.nfc.NfcAdapter;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import com.example.android.common.logger.Log;
+
+/**
+ * Generic UI for sample discovery.
+ */
+public class CardReaderFragment extends Fragment implements LoyaltyCardReader.AccountCallback {
+
+    public static final String TAG = "CardReaderFragment";
+    // Recommend NfcAdapter flags for reading from other Android devices. Indicates that this
+    // activity is interested in NFC-A devices (including other Android devices), and that the
+    // system should not check for the presence of NDEF-formatted data (e.g. Android Beam).
+    public static int READER_FLAGS =
+            NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK;
+    public LoyaltyCardReader mLoyaltyCardReader;
+    private TextView mAccountField;
+
+    /** Called when sample is created. Displays generic UI with welcome text. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        // Inflate the layout for this fragment
+        View v = inflater.inflate(R.layout.main_fragment, container, false);
+        if (v != null) {
+            mAccountField = (TextView) v.findViewById(R.id.card_account_field);
+            mAccountField.setText("Waiting...");
+
+            mLoyaltyCardReader = new LoyaltyCardReader(this);
+
+            // Disable Android Beam and register our card reader callback
+            enableReaderMode();
+        }
+
+        return v;
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        disableReaderMode();
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        enableReaderMode();
+    }
+
+    private void enableReaderMode() {
+        Log.i(TAG, "Enabling reader mode");
+        Activity activity = getActivity();
+        NfcAdapter nfc = NfcAdapter.getDefaultAdapter(activity);
+        if (nfc != null) {
+            nfc.enableReaderMode(activity, mLoyaltyCardReader, READER_FLAGS, null);
+        }
+    }
+
+    private void disableReaderMode() {
+        Log.i(TAG, "Disabling reader mode");
+        Activity activity = getActivity();
+        NfcAdapter nfc = NfcAdapter.getDefaultAdapter(activity);
+        if (nfc != null) {
+            nfc.disableReaderMode(activity);
+        }
+    }
+
+    @Override
+    public void onAccountReceived(final String account) {
+        // This callback is run on a background thread, but updates to UI elements must be performed
+        // on the UI thread.
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mAccountField.setText(account);
+            }
+        });
+    }
+}
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/java/com/example/android/cardreader/LoyaltyCardReader.java b/connectivity/nfc/CardReader/CardReaderSample/src/main/java/com/example/android/cardreader/LoyaltyCardReader.java
new file mode 100644
index 0000000..c29bdfd
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/java/com/example/android/cardreader/LoyaltyCardReader.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+package com.example.android.cardreader;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.nfc.tech.IsoDep;
+
+import com.example.android.common.logger.Log;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+
+/**
+ * Callback class, invoked when an NFC card is scanned while the device is running in reader mode.
+ *
+ * Reader mode can be invoked by calling NfcAdapter
+ */
+public class LoyaltyCardReader implements NfcAdapter.ReaderCallback {
+    private static final String TAG = "LoyaltyCardReader";
+    // AID for our loyalty card service.
+    private static final String SAMPLE_LOYALTY_CARD_AID = "F222222222";
+    // ISO-DEP command HEADER for selecting an AID.
+    // Format: [Class | Instruction | Parameter 1 | Parameter 2]
+    private static final String SELECT_APDU_HEADER = "00A40400";
+    // "OK" status word sent in response to SELECT AID command (0x9000)
+    private static final byte[] SELECT_OK_SW = {(byte) 0x90, (byte) 0x00};
+
+    // Weak reference to prevent retain loop. mAccountCallback is responsible for exiting
+    // foreground mode before it becomes invalid (e.g. during onPause() or onStop()).
+    private WeakReference<AccountCallback> mAccountCallback;
+
+    public interface AccountCallback {
+        public void onAccountReceived(String account);
+    }
+
+    public LoyaltyCardReader(AccountCallback accountCallback) {
+        mAccountCallback = new WeakReference<AccountCallback>(accountCallback);
+    }
+
+    /**
+     * Callback when a new tag is discovered by the system.
+     *
+     * <p>Communication with the card should take place here.
+     *
+     * @param tag Discovered tag
+     */
+    @Override
+    public void onTagDiscovered(Tag tag) {
+        Log.i(TAG, "New tag discovered");
+        // Android's Host-based Card Emulation (HCE) feature implements the ISO-DEP (ISO 14443-4)
+        // protocol.
+        //
+        // In order to communicate with a device using HCE, the discovered tag should be processed
+        // using the IsoDep class.
+        IsoDep isoDep = IsoDep.get(tag);
+        if (isoDep != null) {
+            try {
+                // Connect to the remote NFC device
+                isoDep.connect();
+                // Build SELECT AID command for our loyalty card service.
+                // This command tells the remote device which service we wish to communicate with.
+                Log.i(TAG, "Requesting remote AID: " + SAMPLE_LOYALTY_CARD_AID);
+                byte[] command = BuildSelectApdu(SAMPLE_LOYALTY_CARD_AID);
+                // Send command to remote device
+                Log.i(TAG, "Sending: " + ByteArrayToHexString(command));
+                byte[] result = isoDep.transceive(command);
+                // If AID is successfully selected, 0x9000 is returned as the status word (last 2
+                // bytes of the result) by convention. Everything before the status word is
+                // optional payload, which is used here to hold the account number.
+                int resultLength = result.length;
+                byte[] statusWord = {result[resultLength-2], result[resultLength-1]};
+                byte[] payload = Arrays.copyOf(result, resultLength-2);
+                if (Arrays.equals(SELECT_OK_SW, statusWord)) {
+                    // The remote NFC device will immediately respond with its stored account number
+                    String accountNumber = new String(payload, "UTF-8");
+                    Log.i(TAG, "Received: " + accountNumber);
+                    // Inform CardReaderFragment of received account number
+                    mAccountCallback.get().onAccountReceived(accountNumber);
+                }
+            } catch (IOException e) {
+                Log.e(TAG, "Error communicating with card: " + e.toString());
+            }
+        }
+    }
+
+    /**
+     * Build APDU for SELECT AID command. This command indicates which service a reader is
+     * interested in communicating with. See ISO 7816-4.
+     *
+     * @param aid Application ID (AID) to select
+     * @return APDU for SELECT AID command
+     */
+    public static byte[] BuildSelectApdu(String aid) {
+        // Format: [CLASS | INSTRUCTION | PARAMETER 1 | PARAMETER 2 | LENGTH | DATA]
+        return HexStringToByteArray(SELECT_APDU_HEADER + String.format("%02X", aid.length() / 2) + aid);
+    }
+
+    /**
+     * Utility class to convert a byte array to a hexadecimal string.
+     *
+     * @param bytes Bytes to convert
+     * @return String, containing hexadecimal representation.
+     */
+    public static String ByteArrayToHexString(byte[] bytes) {
+        final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+        char[] hexChars = new char[bytes.length * 2];
+        int v;
+        for ( int j = 0; j < bytes.length; j++ ) {
+            v = bytes[j] & 0xFF;
+            hexChars[j * 2] = hexArray[v >>> 4];
+            hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+        }
+        return new String(hexChars);
+    }
+
+    /**
+     * Utility class to convert a hexadecimal string to a byte string.
+     *
+     * <p>Behavior with input strings containing non-hexadecimal characters is undefined.
+     *
+     * @param s String containing hexadecimal characters to convert
+     * @return Byte array generated from input
+     */
+    public static byte[] HexStringToByteArray(String s) {
+        int len = s.length();
+        byte[] data = new byte[len / 2];
+        for (int i = 0; i < len; i += 2) {
+            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+                    + Character.digit(s.charAt(i+1), 16));
+        }
+        return data;
+    }
+
+}
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-hdpi/ic_launcher.png b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..b1efaf4
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-mdpi/ic_launcher.png b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..f5f9244
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xhdpi/ic_launcher.png b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..5d07b3f
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xxhdpi/card_background.png b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xxhdpi/card_background.png
new file mode 100644
index 0000000..86a7ba7
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xxhdpi/card_background.png
Binary files differ
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xxhdpi/ic_launcher.png b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..6ef21e1
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/layout/main_fragment.xml b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/layout/main_fragment.xml
new file mode 100644
index 0000000..1e3886c
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/layout/main_fragment.xml
@@ -0,0 +1,64 @@
+<!--
+Copyright (C) 2013 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="380dp"
+    android:layout_height="242.25dp"
+    android:layout_gravity="center"
+    android:layout_margin="20dp">
+    <ImageView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:src="@drawable/card_background"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:padding="20dp"
+        android:layout_gravity="center"
+        android:clickable="true">
+        <TextView
+            android:id="@+id/card_title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/card_title"
+            android:fontFamily="sans-serif-condensed"
+            android:textStyle="bold"
+            android:textSize="32dp"
+            />
+        <TextView
+            android:id="@+id/card_account_label"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/account_number"
+            android:fontFamily="sans-serif"
+            android:textStyle="bold"
+            android:textSize="18dp"
+            android:layout_marginTop="40dp"
+            />
+        <TextView
+            android:id="@+id/card_account_field"
+            android:width="360dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif-condensed"
+            android:textStyle="bold"
+            android:textSize="42dp"
+            android:singleLine="true"
+            />
+    </LinearLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/values/strings.xml b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/values/strings.xml
new file mode 100644
index 0000000..b1b1a49
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2013 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.
+-->
+
+<resources>
+    <string name="card_title">Sample Loyalty Card</string>
+    <string name="account_number">Account Number</string>
+</resources>
\ No newline at end of file
diff --git a/connectivity/nfc/CardReader/CardReaderSample/src/main/res/xml/nfc_tech_filter.xml b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/xml/nfc_tech_filter.xml
new file mode 100644
index 0000000..dcfc979
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/src/main/res/xml/nfc_tech_filter.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- This file is used as part of the filter for incoming NFC TECH_DISCOVERED intents. -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- Android's host card emulation feature only supports the IsoDep protocol. -->
+    <tech-list>
+        <tech>android.nfc.tech.IsoDep</tech>
+    </tech-list>
+</resources>
\ No newline at end of file
diff --git a/connectivity/nfc/CardReader/CardReaderSample/tests/AndroidManifest.xml b/connectivity/nfc/CardReader/CardReaderSample/tests/AndroidManifest.xml
new file mode 100644
index 0000000..1098859
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/tests/AndroidManifest.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 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.
+-->
+
+
+
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2013 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.
+  -->
+<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.example.android.cardreader.tests"
+          android:versionCode="1"
+          android:versionName="1.0">
+
+    <uses-sdk
+            android:minSdkVersion="19"
+            android:targetSdkVersion="19" />
+
+    <!-- We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases. -->
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!--
+    Specifies the instrumentation test runner used to run the tests.
+    -->
+    <instrumentation
+            android:name="android.test.InstrumentationTestRunner"
+            android:targetPackage="com.example.android.cardreader"
+            android:label="Tests for com.example.android.cardreader" />
+
+</manifest>
\ No newline at end of file
diff --git a/connectivity/nfc/CardReader/CardReaderSample/tests/src/com/example/android/cardreader/tests/SampleTests.java b/connectivity/nfc/CardReader/CardReaderSample/tests/src/com/example/android/cardreader/tests/SampleTests.java
new file mode 100644
index 0000000..d9d2cc5
--- /dev/null
+++ b/connectivity/nfc/CardReader/CardReaderSample/tests/src/com/example/android/cardreader/tests/SampleTests.java
@@ -0,0 +1,110 @@
+/*
+* Copyright 2013 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.
+*/
+
+
+
+/*
+* Copyright (C) 2013 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.
+*/
+package com.example.android.cardreader.tests;
+
+import com.example.android.cardreader.*;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+* Tests for CardReader sample.
+*/
+public class SampleTests extends ActivityInstrumentationTestCase2<MainActivity> {
+
+    private MainActivity mTestActivity;
+    private CardReaderFragment mTestFragment;
+
+    public SampleTests() {
+        super(MainActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Starts the activity under test using the default Intent with:
+        // action = {@link Intent#ACTION_MAIN}
+        // flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+        // All other fields are null or empty.
+        mTestActivity = getActivity();
+        mTestFragment = (CardReaderFragment)
+            mTestActivity.getSupportFragmentManager().getFragments().get(1);
+    }
+
+    /**
+    * Test if the test fixture has been set up correctly.
+    */
+    public void testPreconditions() {
+        //Try to add a message to add context to your assertions. These messages will be shown if
+        //a tests fails and make it easy to understand why a test failed
+        assertNotNull("mTestActivity is null", mTestActivity);
+        assertNotNull("mTestFragment is null", mTestFragment);
+    }
+
+    /**
+     * Test building SELECT APDU from AID string.
+     */
+    public void testBuildSelectApdu() {
+        final String aid = "1234";
+        final byte[] expectedResult = {(byte) 0x00, (byte) 0xA4, 04, (byte) 0x00, (byte) 0x02,
+                (byte) 0x12, (byte) 0x34};
+        final byte[] result = LoyaltyCardReader.BuildSelectApdu(aid);
+
+        assertEquals(expectedResult.length, result.length);
+        for (int i = 0; i < expectedResult.length; i++) {
+            assertEquals(expectedResult[i], result[i]);
+        }
+    }
+
+    /**
+     * Test converting from a hex string to binary.
+     */
+    public void testHexToBinary() {
+        final byte[] testData = {(byte) 0xc0, (byte) 0xff, (byte) 0xee};
+        final byte[] output = LoyaltyCardReader.HexStringToByteArray("C0FFEE");
+        for (int i = 0; i < testData.length; i++) {
+            assertEquals(testData[i], output[i]);
+        }
+    }
+
+    /**
+     * Test converting from binary to a hex string
+     */
+    public void testBinaryToHex() {
+        final byte[] input = {(byte) 0xc0, (byte) 0xff, (byte) 0xee};
+        final String output = LoyaltyCardReader.ByteArrayToHexString(input);
+        assertEquals("C0FFEE", output);
+    }
+
+}
\ No newline at end of file
diff --git a/connectivity/nfc/CardReader/build.gradle b/connectivity/nfc/CardReader/build.gradle
new file mode 100644
index 0000000..be1fa82
--- /dev/null
+++ b/connectivity/nfc/CardReader/build.gradle
@@ -0,0 +1,14 @@
+
+
+
+
+// BEGIN_EXCLUDE
+import com.example.android.samples.build.SampleGenPlugin
+apply plugin: SampleGenPlugin
+
+samplegen {
+  pathToBuild "../../../../../build"
+  pathToSamplesCommon "../../../common"
+}
+apply from: "../../../../../build/build.gradle"
+// END_EXCLUDE
diff --git a/connectivity/nfc/CardReader/buildSrc/build.gradle b/connectivity/nfc/CardReader/buildSrc/build.gradle
new file mode 100644
index 0000000..e344a8c
--- /dev/null
+++ b/connectivity/nfc/CardReader/buildSrc/build.gradle
@@ -0,0 +1,18 @@
+
+
+
+repositories {
+    mavenCentral()
+}
+dependencies {
+    compile 'org.freemarker:freemarker:2.3.20'
+}
+
+sourceSets {
+    main {
+        groovy {
+            srcDir new File(rootDir, "../../../../../../build/buildSrc/src/main/groovy")
+        }
+    }
+}
+
diff --git a/connectivity/nfc/CardReader/gradle/wrapper/gradle-wrapper.jar b/connectivity/nfc/CardReader/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..8c0fb64
--- /dev/null
+++ b/connectivity/nfc/CardReader/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/connectivity/nfc/CardReader/gradle/wrapper/gradle-wrapper.properties b/connectivity/nfc/CardReader/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..1cfd865
--- /dev/null
+++ b/connectivity/nfc/CardReader/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Jan 02 15:37:05 PST 2014
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=http\://services.gradle.org/distributions/gradle-1.8-all.zip
diff --git a/connectivity/nfc/CardReader/gradlew b/connectivity/nfc/CardReader/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/connectivity/nfc/CardReader/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/connectivity/nfc/CardReader/gradlew.bat b/connectivity/nfc/CardReader/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/connectivity/nfc/CardReader/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off

+@rem ##########################################################################

+@rem

+@rem  Gradle startup script for Windows

+@rem

+@rem ##########################################################################

+

+@rem Set local scope for the variables with windows NT shell

+if "%OS%"=="Windows_NT" setlocal

+

+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

+set DEFAULT_JVM_OPTS=

+

+set DIRNAME=%~dp0

+if "%DIRNAME%" == "" set DIRNAME=.

+set APP_BASE_NAME=%~n0

+set APP_HOME=%DIRNAME%

+

+@rem Find java.exe

+if defined JAVA_HOME goto findJavaFromJavaHome

+

+set JAVA_EXE=java.exe

+%JAVA_EXE% -version >NUL 2>&1

+if "%ERRORLEVEL%" == "0" goto init

+

+echo.

+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:findJavaFromJavaHome

+set JAVA_HOME=%JAVA_HOME:"=%

+set JAVA_EXE=%JAVA_HOME%/bin/java.exe

+

+if exist "%JAVA_EXE%" goto init

+

+echo.

+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:init

+@rem Get command-line arguments, handling Windowz variants

+

+if not "%OS%" == "Windows_NT" goto win9xME_args

+if "%@eval[2+2]" == "4" goto 4NT_args

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

+if "x%~1" == "x" goto execute

+

+set CMD_LINE_ARGS=%*

+goto execute

+

+:4NT_args

+@rem Get arguments from the 4NT Shell from JP Software

+set CMD_LINE_ARGS=%$

+

+:execute

+@rem Setup the command line

+

+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

+

+@rem Execute Gradle

+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

+

+:end

+@rem End local scope for the variables with windows NT shell

+if "%ERRORLEVEL%"=="0" goto mainEnd

+

+:fail

+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

+rem the _cmd.exe /c_ return code!

+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

+exit /b 1

+

+:mainEnd

+if "%OS%"=="Windows_NT" endlocal

+

+:omega

diff --git a/connectivity/nfc/CardReader/settings.gradle b/connectivity/nfc/CardReader/settings.gradle
new file mode 100644
index 0000000..d1d7333
--- /dev/null
+++ b/connectivity/nfc/CardReader/settings.gradle
@@ -0,0 +1,4 @@
+
+
+
+include 'CardReaderSample'
diff --git a/connectivity/nfc/CardReader/template-params.xml b/connectivity/nfc/CardReader/template-params.xml
new file mode 100644
index 0000000..bd79926
--- /dev/null
+++ b/connectivity/nfc/CardReader/template-params.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 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.
+-->
+
+
+
+<sample>
+    <name>CardReader</name>
+    <group>Connectivity</group>
+    <package>com.example.android.cardreader</package>
+
+    <!-- change minSdk if needed-->
+    <minSdk>19</minSdk>
+
+    <strings>
+        <intro>
+            <![CDATA[
+            This sample demonstrates how to implement a low-level NFC card reader, for reading cards
+            that do not contain NDEF or Android Beam data. This sample is designed to read the virtual
+            loyalty card implemented in the "CardEmulation" sample.\n\n
+
+            In particular, this sample demonstrates how to disable Android Beam, select which AIDs the
+            reader is interested, and establish communication with the card
+            ]]>
+        </intro>
+    </strings>
+
+    <template src="base"/>
+    <template src="FragmentView"/>
+    <common src="activities"/>
+    <common src="logger"/>
+
+</sample>