diff --git a/samples/ServiceLayerTester/AndroidManifest.xml b/samples/ServiceLayerTester/AndroidManifest.xml
new file mode 100644
index 0000000..47bf4d7
--- /dev/null
+++ b/samples/ServiceLayerTester/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/ic_launcher-web.png b/samples/ServiceLayerTester/ic_launcher-web.png
new file mode 100644
index 0000000..a18cbb4
Binary files /dev/null and b/samples/ServiceLayerTester/ic_launcher-web.png differ
diff --git a/samples/ServiceLayerTester/proguard-project.txt b/samples/ServiceLayerTester/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/samples/ServiceLayerTester/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/samples/ServiceLayerTester/project.properties b/samples/ServiceLayerTester/project.properties
new file mode 100644
index 0000000..22f08ec
--- /dev/null
+++ b/samples/ServiceLayerTester/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=Giesecke & Devrient GmbH:Open Mobile API (with SL):18
diff --git a/samples/ServiceLayerTester/res/drawable-hdpi/ic_launcher.png b/samples/ServiceLayerTester/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..288b665
Binary files /dev/null and b/samples/ServiceLayerTester/res/drawable-hdpi/ic_launcher.png differ
diff --git a/samples/ServiceLayerTester/res/drawable-mdpi/ic_launcher.png b/samples/ServiceLayerTester/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..6ae570b
Binary files /dev/null and b/samples/ServiceLayerTester/res/drawable-mdpi/ic_launcher.png differ
diff --git a/samples/ServiceLayerTester/res/drawable-xhdpi/ic_launcher.png b/samples/ServiceLayerTester/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..d4fb7cd
Binary files /dev/null and b/samples/ServiceLayerTester/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/samples/ServiceLayerTester/res/drawable-xxhdpi/ic_launcher.png b/samples/ServiceLayerTester/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..85a6081
Binary files /dev/null and b/samples/ServiceLayerTester/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/samples/ServiceLayerTester/res/layout/activity_main.xml b/samples/ServiceLayerTester/res/layout/activity_main.xml
new file mode 100644
index 0000000..c9f39f6
--- /dev/null
+++ b/samples/ServiceLayerTester/res/layout/activity_main.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/res/layout/test_activity.xml b/samples/ServiceLayerTester/res/layout/test_activity.xml
new file mode 100644
index 0000000..3c88c46
--- /dev/null
+++ b/samples/ServiceLayerTester/res/layout/test_activity.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/res/menu/activity_main.xml b/samples/ServiceLayerTester/res/menu/activity_main.xml
new file mode 100644
index 0000000..77f358b
--- /dev/null
+++ b/samples/ServiceLayerTester/res/menu/activity_main.xml
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/res/values-v11/styles.xml b/samples/ServiceLayerTester/res/values-v11/styles.xml
new file mode 100644
index 0000000..541752f
--- /dev/null
+++ b/samples/ServiceLayerTester/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/res/values-v14/styles.xml b/samples/ServiceLayerTester/res/values-v14/styles.xml
new file mode 100644
index 0000000..f20e015
--- /dev/null
+++ b/samples/ServiceLayerTester/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/res/values/strings.xml b/samples/ServiceLayerTester/res/values/strings.xml
new file mode 100644
index 0000000..88a5af0
--- /dev/null
+++ b/samples/ServiceLayerTester/res/values/strings.xml
@@ -0,0 +1,15 @@
+
+
+
+ Service Layer Tester
+ Settings
+ Hello world!
+ Discovery API
+ File Management API
+ PKCS15 API
+ Authentication API
+ Secure Storage API
+ End
+ Start test
+
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/res/values/styles.xml b/samples/ServiceLayerTester/res/values/styles.xml
new file mode 100644
index 0000000..4a10ca4
--- /dev/null
+++ b/samples/ServiceLayerTester/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/MainActivity.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/MainActivity.java
new file mode 100644
index 0000000..0a4f539
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/MainActivity.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2013 Giesecke & Devrient GmbH.
+ *
+ * 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.gieseckedevrient.android.servicelayertester;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.View;
+
+/**
+*
+* Main activity of the Application.
+*/
+public class MainActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ // getMenuInflater().inflate(R.menu.activity_main, menu);
+ return true;
+ }
+
+ /**
+ *
+ * Method called when Discovery Provider API button is pressed.
+ *
+ * @param view View responsible of this event.
+ */
+ public void onClickDiscovery(View view) {
+ Intent i = new Intent(this, TestActivity.class);
+ i.putExtra("providerType", ProviderType.DISCOVERY);
+ startActivity(i);
+ }
+
+ /**
+ *
+ * Method called when Secure Storage Provider API button is pressed.
+ *
+ * @param view View responsible of this event.
+ */
+ public void onClickSecureStorageProvider(View view) {
+ Intent i = new Intent(this, TestActivity.class);
+ i.putExtra("providerType", ProviderType.SECURE_STORAGE);
+ startActivity(i);
+ }
+
+ /**
+ *
+ * Method called when PKCS15 Provider API button is pressed.
+ *
+ * @param view View responsible of this event.
+ */
+ public void onClickPKCS15(View view) {
+ Intent i = new Intent(this, TestActivity.class);
+ i.putExtra("providerType", ProviderType.PKCS15);
+ startActivity(i);
+ }
+
+ /**
+ *
+ * Method called when File View Provider API button is pressed.
+ *
+ * @param view View responsible of this event.
+ */
+ public void onClickFileView(View view) {
+ Intent i = new Intent(this, TestActivity.class);
+ i.putExtra("providerType", ProviderType.FILE_MANAGEMENT);
+ startActivity(i);
+ }
+
+ /**
+ *
+ * Method called when Authentication API button is pressed.
+ *
+ * @param view View responsible of this event.
+ */
+ public void onClickAuthentication(View view) {
+ Intent i = new Intent(this, TestActivity.class);
+ i.putExtra("providerType", ProviderType.AUTHENTICATION);
+ startActivity(i);
+ }
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/ProviderType.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/ProviderType.java
new file mode 100644
index 0000000..02985ae
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/ProviderType.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2013 Giesecke & Devrient GmbH.
+ *
+ * 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.gieseckedevrient.android.servicelayertester;
+
+/**
+*
+* Class used to identify the different types of API Provider Tests.
+*
+* @author openmobileapis
+*
+*/
+public final class ProviderType {
+
+ /** Id used for Discovery Provider API Test. */
+ public static final int DISCOVERY = 0;
+ /** Id used for Authentication Provider API Test. */
+ public static final int AUTHENTICATION = 1;
+ /** Id used for File View Provider API Test. */
+ public static final int FILE_MANAGEMENT = 2;
+ /** Id used for PKCS15 Provider API Test. */
+ public static final int PKCS15 = 3;
+ /** Id used for Secure Storage Provider API Test. */
+ public static final int SECURE_STORAGE = 4;
+
+ /**
+ *
+ * Constructor of the class.
+ *
+ */
+ private ProviderType() {
+ }
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/TestActivity.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/TestActivity.java
new file mode 100644
index 0000000..5e0bb12
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/TestActivity.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2013 Giesecke & Devrient GmbH.
+ *
+ * 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.gieseckedevrient.android.servicelayertester;
+
+import org.simalliance.openmobileapi.SEService;
+import org.simalliance.openmobileapi.SEService.CallBack;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.gieseckedevrient.android.servicelayertester.testrunners.AuthenticationTestRunner;
+import com.gieseckedevrient.android.servicelayertester.testrunners.DiscoveryTestRunner;
+import com.gieseckedevrient.android.servicelayertester.testrunners.FileManagementTestRunner;
+import com.gieseckedevrient.android.servicelayertester.testrunners.Pkcs15TestRunner;
+import com.gieseckedevrient.android.servicelayertester.testrunners.SecureStorageTestRunner;
+
+/**
+ * Activity loaded when a specific test is selected.
+ * Test execution is launched from this Activity.
+*/
+public class TestActivity extends Activity implements CallBack {
+ /**
+ * Id used to identify the different types of API Provider Tests.
+ */
+ private int providerType;
+ /**
+ * The SEService to be used.
+ */
+ private SEService seService;
+
+ /**
+ * Button.
+ */
+ private Button buttonStart;
+ /**
+ * TextView.
+ */
+ private TextView textViewLog;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.test_activity);
+ // Init UI elements
+ buttonStart = (Button) findViewById(R.id.start_test);
+ textViewLog = (TextView) findViewById(R.id.log);
+ // Disable button
+ buttonStart.setEnabled(false);
+ // Get Provider Type
+ providerType = getIntent().getIntExtra("providerType", -1);
+ // Init seService
+ seService = new SEService(getApplicationContext(), this);
+ writeLine("Connecting to SmartCardService...");
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ seService.shutdown();
+ }
+ @Override
+ public void serviceConnected(SEService arg0) {
+ writeLine("Done!");
+ buttonStart.setEnabled(true);
+ }
+
+ /**
+ * Method that calls the thread to start the test execution.
+ * It shows a message if a test execution is still running
+ * when it is called.
+ */
+ public void startTest(View v) {
+ textViewLog.setText("");
+ buttonStart.setEnabled(false);
+ switch (providerType) {
+ case ProviderType.DISCOVERY:
+ new DiscoveryTestRunner(seService, this).start();
+ break;
+ case ProviderType.AUTHENTICATION:
+ new AuthenticationTestRunner(seService, this).start();
+ break;
+ case ProviderType.FILE_MANAGEMENT:
+ new FileManagementTestRunner(seService, this).start();
+ break;
+ case ProviderType.SECURE_STORAGE:
+ new SecureStorageTestRunner(seService, this).start();
+ break;
+ case ProviderType.PKCS15:
+ new Pkcs15TestRunner(seService, this).start();
+ break;
+ default:
+ return;
+ }
+ }
+
+ /**
+ * Writes a line into the log window.
+ *
+ * @param newLine The text to be written.
+ */
+ private void writeLine(final String newLine) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ String text = textViewLog.getText() + newLine + "\n";
+ textViewLog.setText(text);
+ }
+ });
+ }
+
+ public void logInfo(String text) {
+ writeLine(text);
+ }
+
+ public void logError(String text) {
+ writeLine("ERROR:");
+ writeLine(text);
+ }
+
+ /**
+ * Executed when the test run ends.
+ */
+ public void testEnded(final boolean testSucceeded) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (testSucceeded) {
+ writeLine("Test succeeded.");
+ } else {
+ writeLine("Test failed.");
+ }
+ buttonStart.setEnabled(true);
+ }
+ });
+ }
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/Util.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/Util.java
new file mode 100644
index 0000000..8f4a4df
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/Util.java
@@ -0,0 +1,24 @@
+package com.gieseckedevrient.android.servicelayertester;
+
+public class Util {
+ /**
+ * Forms an hex-encoded String of the specified byte array.
+ *
+ * @param byteArray The byte array to be hex-encoded.
+ *
+ * @return An hex-encoded String of the specified byte array.
+ */
+ public static String byteArrayToHexString(byte[] byteArray) {
+ if (byteArray == null) {
+ return "";
+ }
+
+ StringBuffer sb = new StringBuffer();
+
+ for (byte b : byteArray) {
+ sb.append(String.format("%02X ", b & 0xFF));
+ }
+
+ return sb.substring(0, sb.length() - 1).toString();
+ }
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/AuthenticationTestRunner.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/AuthenticationTestRunner.java
new file mode 100644
index 0000000..f96758c
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/AuthenticationTestRunner.java
@@ -0,0 +1,95 @@
+package com.gieseckedevrient.android.servicelayertester.testrunners;
+
+import org.simalliance.openmobileapi.AuthenticationProvider;
+import org.simalliance.openmobileapi.AuthenticationProvider.PinID;
+import org.simalliance.openmobileapi.SEService;
+
+import com.gieseckedevrient.android.servicelayertester.TestActivity;
+
+public class AuthenticationTestRunner extends TestRunner {
+ byte[] aid = {
+ (byte) 0xD2, (byte) 0x76, (byte) 0x00,
+ (byte) 0x01, (byte) 0x18, (byte) 0x00,
+ (byte) 0x03, (byte) 0xFF, (byte) 0x34,
+ (byte) 0x00, (byte) 0x7E, (byte) 0x89,
+ (byte) 0xAA, (byte) 0x00, (byte) 0x80,
+ (byte) 0x09
+ };
+
+ PinID pinId;
+ byte[] pin = new byte[] {
+ (byte) 0x31, (byte) 0x31, (byte) 0x31, (byte) 0x31
+ };
+ byte[] pin2 = new byte[] {
+ (byte) 0x32, (byte) 0x32, (byte) 0x32, (byte) 0x32
+ };
+ byte[] resetPin = {
+ (byte) 0x31, (byte) 0x31, (byte) 0x31, (byte) 0x31,
+ (byte) 0x31, (byte) 0x31, (byte) 0x31, (byte) 0x31
+ };
+
+ public AuthenticationTestRunner(SEService seService, TestActivity activity) {
+ super(seService, activity);
+ }
+
+ @Override
+ public void run() {
+ mActivity.logInfo("Connecting to Authentication applet...");
+ try {
+ mChannel = openChannelToApplet(aid);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ if (mChannel == null) {
+ endTest("Authentication applet not found,"
+ + " make sure it is installed.");
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ mActivity.logInfo("Initialising AuthenticationProvider...");
+ AuthenticationProvider provider;
+ try {
+ provider = new AuthenticationProvider(mChannel);
+ mActivity.logInfo("Done!");
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ pinId = provider.new PinID(1, true);
+
+ mActivity.logInfo("Verifying local pin...");
+ try {
+ if (provider.verifyPin(pinId, pin)) {
+ mActivity.logInfo("Success.");
+ } else {
+ mActivity.logInfo("Failure.");
+ }
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ mActivity.logInfo("Changing local pin...");
+ try {
+ provider.changePin(pinId, pin, pin2);
+ mActivity.logInfo("Done!");
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ mActivity.logInfo("Resetting local pin...");
+ try {
+ provider.resetPin(pinId, resetPin, pin);
+ mActivity.logInfo("Done!");
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ endTest();
+ }
+
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/DiscoveryTestRunner.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/DiscoveryTestRunner.java
new file mode 100644
index 0000000..24a2a6e
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/DiscoveryTestRunner.java
@@ -0,0 +1,43 @@
+package com.gieseckedevrient.android.servicelayertester.testrunners;
+
+import java.io.IOException;
+
+import org.simalliance.openmobileapi.Channel;
+import org.simalliance.openmobileapi.SEService;
+
+import com.gieseckedevrient.android.servicelayertester.TestActivity;
+
+public class DiscoveryTestRunner extends TestRunner {
+ byte[] aid = {
+ (byte) 0xD2, (byte) 0x76, (byte) 0x00,
+ (byte) 0x01, (byte) 0x18, (byte) 0x00,
+ (byte) 0x02, (byte) 0xFF, (byte) 0x49,
+ (byte) 0x50, (byte) 0x25, (byte) 0x89,
+ (byte) 0xC0, (byte) 0x01, (byte) 0x9B,
+ (byte) 0x01
+ };
+
+ public DiscoveryTestRunner(SEService seService, TestActivity activity) {
+ super(seService, activity);
+ }
+
+ @Override
+ public void run() {
+ mActivity.logInfo("Starting discovery process...");
+ try {
+ mChannel = openChannelToApplet(aid);
+ if (mChannel != null) {
+ mActivity.logInfo("Done!");
+ } else {
+ endTest("HelloSmartCard applet not found,"
+ + " make sure it is installed.");
+ return;
+ }
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ endTest();
+ }
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/FileManagementTestRunner.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/FileManagementTestRunner.java
new file mode 100644
index 0000000..dea7116
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/FileManagementTestRunner.java
@@ -0,0 +1,100 @@
+package com.gieseckedevrient.android.servicelayertester.testrunners;
+
+import org.simalliance.openmobileapi.FileViewProvider;
+import org.simalliance.openmobileapi.SEService;
+
+import com.gieseckedevrient.android.servicelayertester.TestActivity;
+import com.gieseckedevrient.android.servicelayertester.Util;
+
+public class FileManagementTestRunner extends TestRunner {
+ byte[] aid = {
+ (byte) 0xD2, (byte) 0x76, (byte) 0x00,
+ (byte) 0x01, (byte) 0x18, (byte) 0x00,
+ (byte) 0x02, (byte) 0xFF, (byte) 0x34,
+ (byte) 0x00, (byte) 0x75, (byte) 0x89,
+ (byte) 0xAA, (byte) 0x00, (byte) 0x76,
+ (byte) 0x19
+ };
+
+ int FID_DF = 0x2000;
+
+ int SFI_EF = 21;
+
+ public FileManagementTestRunner(SEService seService, TestActivity activity) {
+ super(seService, activity);
+ }
+
+ @Override
+ public void run() {
+ mActivity.logInfo("Connecting to File Management applet...");
+ try {
+ mChannel = openChannelToApplet(aid);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ if (mChannel == null) {
+ endTest("File Management applet not found,"
+ + " make sure it is installed.");
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ mActivity.logInfo("Initialising FileViewProvider...");
+ FileViewProvider provider = new FileViewProvider(mChannel);
+ mActivity.logInfo("Done!");
+
+ mActivity.logInfo("Selecting directory...");
+ try {
+ provider.selectByFID(FID_DF);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ mActivity.logInfo("Reading binary file...");
+ byte[] content;
+ try {
+ content = provider.readBinary(SFI_EF, 0, 0);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("File content is:");
+ mActivity.logInfo(Util.byteArrayToHexString(content));
+
+ byte[] newContent = new byte[] {
+ (byte) 0xA0, (byte) 0xA1, (byte) 0xA2, (byte) 0xA3,
+ (byte) 0xA4, (byte) 0xA5, (byte) 0xA6, (byte) 0xA7,
+ (byte) 0xA8, (byte) 0xA9,
+ };
+ mActivity.logInfo("Writting file...");
+ try {
+ provider.writeBinary(SFI_EF, newContent, 0, newContent.length);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("New content is:");
+ try {
+ mActivity.logInfo(Util.byteArrayToHexString(
+ provider.readBinary(SFI_EF, 0, 0)));
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ mActivity.logInfo("Restoring file...");
+ try {
+ provider.writeBinary(SFI_EF, content, 0, content.length);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ endTest();
+ }
+
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/Pkcs15TestRunner.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/Pkcs15TestRunner.java
new file mode 100644
index 0000000..bf40dd4
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/Pkcs15TestRunner.java
@@ -0,0 +1,101 @@
+/**
+ *
+ */
+package com.gieseckedevrient.android.servicelayertester.testrunners;
+
+import java.io.IOException;
+
+import org.simalliance.openmobileapi.Channel;
+import org.simalliance.openmobileapi.PKCS15Provider;
+import org.simalliance.openmobileapi.Reader;
+import org.simalliance.openmobileapi.SEService;
+
+import com.gieseckedevrient.android.servicelayertester.TestActivity;
+import com.gieseckedevrient.android.servicelayertester.Util;
+
+/**
+ * @author openmobileapis
+ *
+ */
+public class Pkcs15TestRunner extends TestRunner {
+ byte[] AID_PKCS15 = { (byte) 0xA0, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+ (byte) 0x63, (byte) 0x50, (byte) 0x4B, (byte) 0x43, (byte) 0x53,
+ (byte) 0x2D, (byte) 0x31, (byte) 0x35 };
+ byte[] AID_CARD_MANAGER = { (byte) 0xA0, (byte) 0x00, (byte) 0x00,
+ (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
+
+ /**
+ * @param seService
+ * @param activity
+ */
+ public Pkcs15TestRunner(SEService seService, TestActivity activity) {
+ super(seService, activity);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.gieseckedevrient.android.servicelayertester.testrunners.TestRunner
+ * #run()
+ */
+ @Override
+ public void run() {
+ Channel mChannel;
+ PKCS15Provider provider;
+ try {
+ mActivity.logInfo("Trying to connect to PKCS#15 applet...");
+ mChannel = openChannelToApplet(AID_PKCS15);
+ if (mChannel != null) {
+ mActivity.logInfo("Done!");
+ mActivity.logInfo("Initialising PKCS15Provider...");
+ try {
+ provider = new PKCS15Provider(mChannel);
+ mActivity.logInfo("Done!");
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ } else {
+ provider = null;
+ mChannel = null;
+ mActivity.logError("PKCS#15 applet not found.");
+ mActivity.logInfo("Searching for a PKCS#15 file structure...");
+ Reader[] readers = mSeService.getReaders();
+ for (Reader r : readers) {
+ if (r.isSecureElementPresent()) {
+ try {
+ mActivity.logInfo("Opening channel...");
+ mChannel = r.openSession().openLogicalChannel(
+ AID_CARD_MANAGER);
+ mActivity.logInfo("Done!");
+ if (mChannel != null) {
+ mActivity.logInfo(
+ "Initialising PKCS#15 provider...");
+ provider = new PKCS15Provider(mChannel);
+ mActivity.logInfo("Done!");
+ break;
+ }
+ } catch (Exception e) {
+ mActivity.logError(e.getMessage()
+ + "\nSee log for details.");
+ mChannel = null;
+ }
+ }
+ }
+ if (provider == null) {
+ endTest("No PKCS#15 file structure found.");
+ return;
+ }
+ }
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ // Read the ODF
+ mActivity.logInfo("ODF content is:");
+ mActivity.logInfo(Util.byteArrayToHexString(provider.getODF()));
+ endTest();
+ }
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/SecureStorageTestRunner.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/SecureStorageTestRunner.java
new file mode 100644
index 0000000..e24f3a5
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/SecureStorageTestRunner.java
@@ -0,0 +1,108 @@
+package com.gieseckedevrient.android.servicelayertester.testrunners;
+
+import java.io.IOException;
+
+import org.simalliance.openmobileapi.SEService;
+import org.simalliance.openmobileapi.SecureStorageProvider;
+
+import com.gieseckedevrient.android.servicelayertester.TestActivity;
+import com.gieseckedevrient.android.servicelayertester.Util;
+
+public class SecureStorageTestRunner extends TestRunner {
+
+ byte[] aid = {
+ (byte) 0xD2, (byte) 0x76, (byte) 0x00,
+ (byte) 0x01, (byte) 0x18, (byte) 0x00,
+ (byte) 0x03, (byte) 0xFF, (byte) 0x34,
+ (byte) 0x00, (byte) 0x7E, (byte) 0x89,
+ (byte) 0xAA, (byte) 0x00, (byte) 0x7F,
+ (byte) 0x09
+ };
+
+ public SecureStorageTestRunner(SEService seService, TestActivity activity) {
+ super(seService, activity);
+ }
+
+ @Override
+ public void run() {
+ mActivity.logInfo("Connecting to Secure Storage applet...");
+ try {
+ mChannel = openChannelToApplet(aid);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ if (mChannel == null) {
+ endTest("Secure Storage applet not found,"
+ + " make sure it is installed.");
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ mActivity.logInfo("Initialising SecureStorageProvider...");
+ SecureStorageProvider provider;
+ try {
+ provider = new SecureStorageProvider(mChannel);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ String title = "Entry1";
+ byte[] content = new byte[] {
+ (byte) 0xA0, (byte) 0xA1, (byte) 0xA2, (byte) 0xA3,
+ (byte) 0xA4, (byte) 0xA5, (byte) 0xA6, (byte) 0xA7,
+ (byte) 0xA8, (byte) 0xA9,
+ };
+ mActivity.logInfo("Creating SeS entry...");
+ try {
+ provider.create(title, content);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ mActivity.logInfo("Entry content is:");
+ try {
+ mActivity.logInfo(Util.byteArrayToHexString(provider.read(title)));
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ byte[] newContent = new byte[] {
+ (byte) 0xB0, (byte) 0xB1, (byte) 0xB2, (byte) 0xB3,
+ (byte) 0xB4, (byte) 0xB5, (byte) 0xB6, (byte) 0xB7,
+ (byte) 0xB8, (byte) 0xB9,
+ };
+ mActivity.logInfo("Updating entry...");
+ try {
+ provider.update(title, newContent);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("Done!");
+
+ mActivity.logInfo("New entry content is:");
+ try {
+ mActivity.logInfo(Util.byteArrayToHexString(provider.read(title)));
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+
+ mActivity.logInfo("Deleting entry...");
+ try {
+ provider.delete(title);
+ } catch (Exception e) {
+ endTest(e);
+ return;
+ }
+ mActivity.logInfo("Done!");
+ endTest();
+ }
+
+}
diff --git a/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/TestRunner.java b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/TestRunner.java
new file mode 100644
index 0000000..c9dad88
--- /dev/null
+++ b/samples/ServiceLayerTester/src/com/gieseckedevrient/android/servicelayertester/testrunners/TestRunner.java
@@ -0,0 +1,98 @@
+package com.gieseckedevrient.android.servicelayertester.testrunners;
+
+import java.io.IOException;
+
+import org.simalliance.openmobileapi.Channel;
+import org.simalliance.openmobileapi.Reader;
+import org.simalliance.openmobileapi.SEDiscovery;
+import org.simalliance.openmobileapi.SERecognizerByAID;
+import org.simalliance.openmobileapi.SEService;
+
+import com.gieseckedevrient.android.servicelayertester.TestActivity;
+
+public abstract class TestRunner extends Thread {
+ /**
+ * The SEService that will be used.
+ */
+ protected SEService mSeService;
+
+ /**
+ * The Channel that will be used.
+ */
+ protected Channel mChannel;
+
+ /**
+ * The calling activity.
+ */
+ protected TestActivity mActivity;
+
+ /**
+ * Initializes a new instance of the TestRunner class.
+ *
+ * @param seService The SEService to use.
+ * @param activity The calling activity.
+ */
+ public TestRunner(SEService seService, TestActivity activity) {
+ mSeService = seService;
+ mActivity = activity;
+ }
+
+ /**
+ * Opens a Channel to the SE which contains the specified AID.
+ *
+ * @param aid The AID of the desired applet.
+ *
+ * @return An open channel to the specified applet.
+ *
+ * @throws IllegalArgumentException If the specified aid is not correct.
+ * @throws IOException Lower-level API exception.
+ */
+ public Channel openChannelToApplet(byte[] aid)
+ throws IllegalArgumentException, IOException {
+ SERecognizerByAID seRecognizerByAid = new SERecognizerByAID(aid);
+ SEDiscovery seDiscovery = new SEDiscovery(
+ mSeService, seRecognizerByAid);
+ Reader reader = seDiscovery.getFirstMatch();
+ if (reader == null) {
+ return null;
+ }
+
+ return reader.openSession().openLogicalChannel(aid);
+ }
+
+ @Override
+ public abstract void run();
+
+ /**
+ * Ends the test.
+ */
+ public void endTest() {
+ if (mChannel != null && !mChannel.isClosed()) {
+ mChannel.close();
+ }
+ mActivity.testEnded(true);
+ }
+
+ /**
+ * Ends the test.
+ */
+ public void endTest(String errorMessage) {
+ if (mChannel != null && !mChannel.isClosed()) {
+ mChannel.close();
+ }
+ mActivity.logError(errorMessage);
+ mActivity.testEnded(false);
+ }
+
+ /**
+ * Ends the test.
+ */
+ public void endTest(Exception e) {
+ if (mChannel != null && !mChannel.isClosed()) {
+ mChannel.close();
+ }
+ e.printStackTrace();
+ mActivity.logError(e.getMessage() + "\nSee log for details.");
+ mActivity.testEnded(false);
+ }
+}