use HCE mode of Samsung Accessories for emulation
This commit is contained in:
@@ -90,9 +90,7 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/debug" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/animated-vector-drawable/23.2.1/jars" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/animated-vector-drawable/23.2.1/jars" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.2.1/jars" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.2.1/jars" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.2.1/jars" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.2.1/jars" />
|
||||||
@@ -108,14 +106,12 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/tmp" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||||
@@ -127,8 +123,8 @@
|
|||||||
<orderEntry type="library" exported="" name="design-23.2.1" level="project" />
|
<orderEntry type="library" exported="" name="design-23.2.1" level="project" />
|
||||||
<orderEntry type="library" exported="" name="jcardsim-3.0.4-SNAPSHOT-android" level="project" />
|
<orderEntry type="library" exported="" name="jcardsim-3.0.4-SNAPSHOT-android" level="project" />
|
||||||
<orderEntry type="library" exported="" name="animated-vector-drawable-23.2.1" level="project" />
|
<orderEntry type="library" exported="" name="animated-vector-drawable-23.2.1" level="project" />
|
||||||
<orderEntry type="library" exported="" name="core-3.2.1" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="support-annotations-23.2.1" level="project" />
|
<orderEntry type="library" exported="" name="support-annotations-23.2.1" level="project" />
|
||||||
|
<orderEntry type="library" exported="" name="core-3.2.1" level="project" />
|
||||||
<orderEntry type="library" exported="" name="recyclerview-v7-23.2.1" level="project" />
|
<orderEntry type="library" exported="" name="recyclerview-v7-23.2.1" level="project" />
|
||||||
<orderEntry type="library" exported="" name="accessory-v2.3.2" level="project" />
|
<orderEntry type="library" exported="" name="accessory-v2.3.2" level="project" />
|
||||||
<orderEntry type="library" exported="" name="support-vector-drawable-23.2.1" level="project" />
|
<orderEntry type="library" exported="" name="support-vector-drawable-23.2.1" level="project" />
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ dependencies {
|
|||||||
compile 'com.android.support:appcompat-v7:23.0.1'
|
compile 'com.android.support:appcompat-v7:23.0.1'
|
||||||
compile 'com.android.support:support-v4:23.0.1'
|
compile 'com.android.support:support-v4:23.0.1'
|
||||||
compile 'com.android.support:design:23.2.1'
|
compile 'com.android.support:design:23.2.1'
|
||||||
|
|
||||||
compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
|
compile 'com.journeyapps:zxing-android-embedded:3.2.0@aar'
|
||||||
compile 'com.google.zxing:core:3.2.1'
|
compile 'com.google.zxing:core:3.2.1'
|
||||||
compile group: 'com.madgag.spongycastle', name: 'core', version: '1.51.0.0'
|
compile 'com.madgag.spongycastle:core:1.51.0.0'
|
||||||
|
compile files('libs/sdk-v1.0.0.jar')
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
ACardEmulator/app/libs/accessory-v2.3.2.jar
Normal file
BIN
ACardEmulator/app/libs/accessory-v2.3.2.jar
Normal file
Binary file not shown.
BIN
ACardEmulator/app/libs/sdk-v1.0.0.jar
Normal file
BIN
ACardEmulator/app/libs/sdk-v1.0.0.jar
Normal file
Binary file not shown.
@@ -7,6 +7,13 @@
|
|||||||
<uses-permission android:name="android.permission.NFC" />
|
<uses-permission android:name="android.permission.NFC" />
|
||||||
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
|
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="com.samsung.accessory.permission.ACCESSORY_FRAMEWORK" />
|
||||||
|
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
|
||||||
|
<uses-permission android:name="com.samsung.WATCH_APP_TYPE.Companion" />
|
||||||
|
<uses-permission android:name="com.samsung.wmanager.ENABLE_NOTIFICATION" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
@@ -37,7 +44,7 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<service android:name=".EmulatorService"
|
<service android:name=".EmulatorHostApduService"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:permission="android.permission.BIND_NFC_SERVICE">
|
android:permission="android.permission.BIND_NFC_SERVICE">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@@ -47,6 +54,24 @@
|
|||||||
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
|
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
|
||||||
android:resource="@xml/aid_list"/>
|
android:resource="@xml/aid_list"/>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service android:name=".SmartcardProviderService" />
|
||||||
|
<receiver android:name="com.samsung.android.sdk.accessory.RegisterUponInstallReceiver" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.samsung.accessory.action.REGISTER_AGENT" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
<receiver android:name="com.samsung.android.sdk.accessory.ServiceConnectionIndicationBroadcastReceiver" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.samsung.accessory.action.SERVICE_CONNECTION_REQUESTED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
<meta-data
|
||||||
|
android:name="AccessoryServicesLocation"
|
||||||
|
android:value="/res/xml/accessoryservices.xml" />
|
||||||
|
<meta-data
|
||||||
|
android:name="GearAppType"
|
||||||
|
android:value="tpk" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Frank Morgner
|
||||||
|
*
|
||||||
|
* This file is part of ACardEmulator.
|
||||||
|
*
|
||||||
|
* ACardEmulator is free software: you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* ACardEmulator is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* ACardEmulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.vsmartcard.acardemulator;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.nfc.cardemulation.HostApduService;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.vsmartcard.acardemulator.emulators.EmulatorSingleton;
|
||||||
|
|
||||||
|
public class EmulatorHostApduService extends HostApduService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
EmulatorSingleton.createEmulator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] processCommandApdu(byte[] capdu, Bundle extras) {
|
||||||
|
return EmulatorSingleton.process(this, capdu);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDeactivated(int reason) {
|
||||||
|
Intent i = new Intent(EmulatorSingleton.TAG);
|
||||||
|
|
||||||
|
Log.d("", "End transaction");
|
||||||
|
switch (reason) {
|
||||||
|
case DEACTIVATION_LINK_LOSS:
|
||||||
|
i.putExtra(EmulatorSingleton.EXTRA_DESELECT, "link lost");
|
||||||
|
EmulatorSingleton.deactivate();
|
||||||
|
break;
|
||||||
|
case DEACTIVATION_DESELECTED:
|
||||||
|
EmulatorSingleton.deactivate();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,8 @@ import android.view.View;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.vsmartcard.acardemulator.emulators.EmulatorSingleton;
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@@ -48,12 +50,12 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
private BroadcastReceiver bReceiver = new BroadcastReceiver() {
|
private BroadcastReceiver bReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (intent.getAction().equals(EmulatorService.TAG)) {
|
if (intent.getAction().equals(EmulatorSingleton.TAG)) {
|
||||||
String capdu = intent.getStringExtra(EmulatorService.EXTRA_CAPDU);
|
String capdu = intent.getStringExtra(EmulatorSingleton.EXTRA_CAPDU);
|
||||||
String rapdu = intent.getStringExtra(EmulatorService.EXTRA_RAPDU);
|
String rapdu = intent.getStringExtra(EmulatorSingleton.EXTRA_RAPDU);
|
||||||
String error = intent.getStringExtra(EmulatorService.EXTRA_ERROR);
|
String error = intent.getStringExtra(EmulatorSingleton.EXTRA_ERROR);
|
||||||
String deselect = intent.getStringExtra(EmulatorService.EXTRA_DESELECT);
|
String deselect = intent.getStringExtra(EmulatorSingleton.EXTRA_DESELECT);
|
||||||
String install = intent.getStringExtra(EmulatorService.EXTRA_INSTALL);
|
String install = intent.getStringExtra(EmulatorSingleton.EXTRA_INSTALL);
|
||||||
if (install != null)
|
if (install != null)
|
||||||
textViewVPCDStatus.append(getResources().getString(R.string.status_install) + ":" + install + "\n");
|
textViewVPCDStatus.append(getResources().getString(R.string.status_install) + ":" + install + "\n");
|
||||||
if (capdu != null)
|
if (capdu != null)
|
||||||
@@ -102,7 +104,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
if (emulator != getString(R.string.vicc)) {
|
if (emulator != getString(R.string.vicc)) {
|
||||||
Snackbar.make(view, "Scheduled re-installation of all applets...", Snackbar.LENGTH_LONG)
|
Snackbar.make(view, "Scheduled re-installation of all applets...", Snackbar.LENGTH_LONG)
|
||||||
.setAction("Action", null).show();
|
.setAction("Action", null).show();
|
||||||
EmulatorService.destroySimulator(getApplicationContext());
|
EmulatorSingleton.destroyEmulator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -116,7 +118,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(this);
|
LocalBroadcastManager bManager = LocalBroadcastManager.getInstance(this);
|
||||||
IntentFilter intentFilter = new IntentFilter();
|
IntentFilter intentFilter = new IntentFilter();
|
||||||
intentFilter.addAction(EmulatorService.TAG);
|
intentFilter.addAction(EmulatorSingleton.TAG);
|
||||||
bManager.registerReceiver(bReceiver, intentFilter);
|
bManager.registerReceiver(bReceiver, intentFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -200,6 +200,8 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bindPreferenceSummaryToValue(findPreference("nfc"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
|
||||||
|
* the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
* * Neither the name of Samsung Electronics Co., Ltd. nor the names of its contributors may be used to endorse
|
||||||
|
* or promote products derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.vsmartcard.acardemulator;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.samsung.android.sdk.SsdkUnsupportedException;
|
||||||
|
import com.samsung.android.sdk.accessory.*;
|
||||||
|
import com.vsmartcard.acardemulator.emulators.EmulatorSingleton;
|
||||||
|
|
||||||
|
public class SmartcardProviderService extends SAAgent {
|
||||||
|
private static final String TAG = "HelloAccessory(P)";
|
||||||
|
private static final int HELLOACCESSORY_CHANNEL_ID = 104;
|
||||||
|
private static final Class<ServiceConnection> SASOCKET_CLASS = ServiceConnection.class;
|
||||||
|
private final IBinder mBinder = new LocalBinder();
|
||||||
|
private ServiceConnection mConnectionHandler = null;
|
||||||
|
Handler mHandler = new Handler();
|
||||||
|
|
||||||
|
public SmartcardProviderService() {
|
||||||
|
super(TAG, SASOCKET_CLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
SA mAccessory = new SA();
|
||||||
|
try {
|
||||||
|
mAccessory.initialize(this);
|
||||||
|
EmulatorSingleton.createEmulator(this);
|
||||||
|
} catch (SsdkUnsupportedException e) {
|
||||||
|
// try to handle SsdkUnsupportedException
|
||||||
|
if (processUnsupportedException(e) == true) {
|
||||||
|
EmulatorSingleton.createEmulator(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (Exception e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
/*
|
||||||
|
* Your application can not use Samsung Accessory SDK. Your application should work smoothly
|
||||||
|
* without using this SDK, or you may want to notify user and close your application gracefully
|
||||||
|
* (release resources, stop Service threads, close UI thread, etc.)
|
||||||
|
*/
|
||||||
|
stopSelf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return mBinder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFindPeerAgentsResponse(SAPeerAgent[] peerAgents, int result) {
|
||||||
|
Log.d(TAG, "onFindPeerAgentResponse : result =" + result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onServiceConnectionRequested(SAPeerAgent peerAgent) {
|
||||||
|
if (peerAgent != null) {
|
||||||
|
Toast.makeText(getBaseContext(), "connection accepted", Toast.LENGTH_SHORT).show();
|
||||||
|
acceptServiceConnectionRequest(peerAgent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onServiceConnectionResponse(SAPeerAgent peerAgent, SASocket socket, int result) {
|
||||||
|
if (result == SAAgent.CONNECTION_SUCCESS) {
|
||||||
|
if (socket != null) {
|
||||||
|
mConnectionHandler = (ServiceConnection) socket;
|
||||||
|
}
|
||||||
|
} else if (result == SAAgent.CONNECTION_ALREADY_EXIST) {
|
||||||
|
Log.e(TAG, "onServiceConnectionResponse, CONNECTION_ALREADY_EXIST");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onAuthenticationResponse(SAPeerAgent peerAgent, SAAuthenticationToken authToken, int error) {
|
||||||
|
/*
|
||||||
|
* The authenticatePeerAgent(peerAgent) API may not be working properly depending on the firmware
|
||||||
|
* version of accessory device. Please refer to another sample application for Security.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onError(SAPeerAgent peerAgent, String errorMessage, int errorCode) {
|
||||||
|
super.onError(peerAgent, errorMessage, errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processUnsupportedException(SsdkUnsupportedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
int errType = e.getType();
|
||||||
|
if (errType == SsdkUnsupportedException.VENDOR_NOT_SUPPORTED
|
||||||
|
|| errType == SsdkUnsupportedException.DEVICE_NOT_SUPPORTED) {
|
||||||
|
/*
|
||||||
|
* Your application can not use Samsung Accessory SDK. You application should work smoothly
|
||||||
|
* without using this SDK, or you may want to notify user and close your app gracefully (release
|
||||||
|
* resources, stop Service threads, close UI thread, etc.)
|
||||||
|
*/
|
||||||
|
stopSelf();
|
||||||
|
} else if (errType == SsdkUnsupportedException.LIBRARY_NOT_INSTALLED) {
|
||||||
|
Log.e(TAG, "You need to install Samsung Accessory SDK to use this application.");
|
||||||
|
} else if (errType == SsdkUnsupportedException.LIBRARY_UPDATE_IS_REQUIRED) {
|
||||||
|
Log.e(TAG, "You need to update Samsung Accessory SDK to use this application.");
|
||||||
|
} else if (errType == SsdkUnsupportedException.LIBRARY_UPDATE_IS_RECOMMENDED) {
|
||||||
|
Log.e(TAG, "We recommend that you update your Samsung Accessory SDK before using this application.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LocalBinder extends Binder {
|
||||||
|
public SmartcardProviderService getService() {
|
||||||
|
return SmartcardProviderService.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ServiceConnection extends SASocket {
|
||||||
|
public ServiceConnection() {
|
||||||
|
super(ServiceConnection.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(int channelId, String errorMessage, int errorCode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(int channelId, byte[] data) {
|
||||||
|
if (mConnectionHandler == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final byte[] response = EmulatorSingleton.process(getApplicationContext(), data);
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
mConnectionHandler.send(HELLOACCESSORY_CHANNEL_ID, response);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onServiceConnectionLost(int reason) {
|
||||||
|
mConnectionHandler = null;
|
||||||
|
EmulatorSingleton.deactivate();
|
||||||
|
mHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Toast.makeText(getBaseContext(), "connection lost", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,28 +17,19 @@
|
|||||||
* ACardEmulator. If not, see <http://www.gnu.org/licenses/>.
|
* ACardEmulator. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.vsmartcard.acardemulator;
|
package com.vsmartcard.acardemulator.emulators;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.nfc.cardemulation.HostApduService;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.StrictMode;
|
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import com.vsmartcard.acardemulator.R;
|
||||||
import java.net.InetAddress;
|
import com.vsmartcard.acardemulator.Util;
|
||||||
import java.net.Socket;
|
|
||||||
|
|
||||||
import com.vsmartcard.acardemulator.emulators.Emulator;
|
|
||||||
import com.vsmartcard.acardemulator.emulators.JCEmulator;
|
|
||||||
import com.vsmartcard.acardemulator.emulators.VICCEmulator;
|
|
||||||
|
|
||||||
public class EmulatorService extends HostApduService {
|
|
||||||
|
|
||||||
|
public class EmulatorSingleton {
|
||||||
public static final String TAG = "com.vsmartcard.acardemulator.EmulatorService";
|
public static final String TAG = "com.vsmartcard.acardemulator.EmulatorService";
|
||||||
public static final String EXTRA_CAPDU = "MSG_CAPDU";
|
public static final String EXTRA_CAPDU = "MSG_CAPDU";
|
||||||
public static final String EXTRA_RAPDU = "MSG_RAPDU";
|
public static final String EXTRA_RAPDU = "MSG_RAPDU";
|
||||||
@@ -49,22 +40,35 @@ public class EmulatorService extends HostApduService {
|
|||||||
private static Emulator emulator = null;
|
private static Emulator emulator = null;
|
||||||
private static boolean do_destroy = false;
|
private static boolean do_destroy = false;
|
||||||
|
|
||||||
@Override
|
private static void destroyEmulatorIfRequested(Context context) {
|
||||||
public void onCreate () {
|
if (do_destroy) {
|
||||||
super.onCreate();
|
emulator.destroy();
|
||||||
|
emulator = null;
|
||||||
|
do_destroy = false;
|
||||||
|
Intent i = new Intent(TAG);
|
||||||
|
i.putExtra(EXTRA_DESELECT, "Uninstalled all applets.");
|
||||||
|
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destroyEmulator() {
|
||||||
|
do_destroy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void createEmulator(Context context) {
|
||||||
// force reloading applets if requested
|
// force reloading applets if requested
|
||||||
do_destroy();
|
destroyEmulatorIfRequested(context);
|
||||||
|
|
||||||
if (emulator == null) {
|
if (emulator == null) {
|
||||||
Log.d("", "Begin transaction");
|
Log.d("", "Begin transaction");
|
||||||
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(this);
|
SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
String str_emulator = SP.getString("emulator", "");
|
String str_emulator = SP.getString("emulator", "");
|
||||||
if (str_emulator.equals(getString(R.string.vicc))) {
|
if (str_emulator.equals(context.getString(R.string.vicc))) {
|
||||||
emulator = new VICCEmulator(
|
emulator = new VICCEmulator(
|
||||||
SP.getString("hostname", VICCEmulator.DEFAULT_HOSTNAME),
|
SP.getString("hostname", VICCEmulator.DEFAULT_HOSTNAME),
|
||||||
Integer.parseInt(SP.getString("port", Integer.toString(VICCEmulator.DEFAULT_PORT))));
|
Integer.parseInt(SP.getString("port", Integer.toString(VICCEmulator.DEFAULT_PORT))));
|
||||||
} else {
|
} else {
|
||||||
emulator = new JCEmulator(this,
|
emulator = new JCEmulator(context,
|
||||||
SP.getBoolean("activate_helloworld", false),
|
SP.getBoolean("activate_helloworld", false),
|
||||||
SP.getBoolean("activate_openpgp", false),
|
SP.getBoolean("activate_openpgp", false),
|
||||||
SP.getBoolean("activate_oath", false),
|
SP.getBoolean("activate_oath", false),
|
||||||
@@ -74,55 +78,19 @@ public class EmulatorService extends HostApduService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void destroySimulator(Context context) {
|
public static byte[] process(Context context, byte[] capdu) {
|
||||||
do_destroy = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void do_destroy() {
|
|
||||||
if (do_destroy) {
|
|
||||||
emulator.destroy();
|
|
||||||
emulator = null;
|
|
||||||
do_destroy = false;
|
|
||||||
Intent i = new Intent(TAG);
|
|
||||||
i.putExtra(EXTRA_DESELECT, "Uninstalled all applets.");
|
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
do_destroy();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] processCommandApdu(byte[] capdu, Bundle extras) {
|
|
||||||
byte[] rapdu = emulator.process(capdu);
|
byte[] rapdu = emulator.process(capdu);
|
||||||
|
|
||||||
Intent i = new Intent(TAG);
|
Intent i = new Intent(TAG);
|
||||||
i.putExtra(EXTRA_CAPDU, Util.byteArrayToHexString(capdu));
|
i.putExtra(EXTRA_CAPDU, Util.byteArrayToHexString(capdu));
|
||||||
if (rapdu != null)
|
if (rapdu != null)
|
||||||
i.putExtra(EXTRA_RAPDU, Util.byteArrayToHexString(rapdu));
|
i.putExtra(EXTRA_RAPDU, Util.byteArrayToHexString(rapdu));
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
|
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
|
||||||
|
|
||||||
return rapdu;
|
return rapdu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static void deactivate() {
|
||||||
public void onDeactivated(int reason) {
|
emulator.deactivate();
|
||||||
Intent i = new Intent(TAG);
|
|
||||||
|
|
||||||
Log.d("", "End transaction");
|
|
||||||
switch (reason) {
|
|
||||||
case DEACTIVATION_LINK_LOSS:
|
|
||||||
i.putExtra(EXTRA_DESELECT, "link lost");
|
|
||||||
emulator.deactivate();
|
|
||||||
break;
|
|
||||||
case DEACTIVATION_DESELECTED:
|
|
||||||
emulator.deactivate();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalBroadcastManager.getInstance(this).sendBroadcast(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,6 @@ import com.licel.jcardsim.base.SimulatorRuntime;
|
|||||||
import com.licel.jcardsim.samples.HelloWorldApplet;
|
import com.licel.jcardsim.samples.HelloWorldApplet;
|
||||||
import com.licel.jcardsim.utils.AIDUtil;
|
import com.licel.jcardsim.utils.AIDUtil;
|
||||||
import com.mysmartlogon.gidsApplet.GidsApplet;
|
import com.mysmartlogon.gidsApplet.GidsApplet;
|
||||||
import com.vsmartcard.acardemulator.EmulatorService;
|
|
||||||
import com.vsmartcard.acardemulator.R;
|
import com.vsmartcard.acardemulator.R;
|
||||||
import com.vsmartcard.acardemulator.Util;
|
import com.vsmartcard.acardemulator.Util;
|
||||||
|
|
||||||
@@ -100,11 +99,11 @@ public class JCEmulator implements Emulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent i = new Intent(EmulatorService.TAG);
|
Intent i = new Intent(EmulatorSingleton.TAG);
|
||||||
if (!extra_error.isEmpty())
|
if (!extra_error.isEmpty())
|
||||||
i.putExtra(EmulatorService.EXTRA_ERROR, extra_error);
|
i.putExtra(EmulatorSingleton.EXTRA_ERROR, extra_error);
|
||||||
if (!extra_install.isEmpty())
|
if (!extra_install.isEmpty())
|
||||||
i.putExtra(EmulatorService.EXTRA_INSTALL, extra_install);
|
i.putExtra(EmulatorSingleton.EXTRA_INSTALL, extra_install);
|
||||||
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
|
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,14 @@
|
|||||||
</string-array>
|
</string-array>
|
||||||
<string name="jcardsim">Builtin Java Card Simulator</string>
|
<string name="jcardsim">Builtin Java Card Simulator</string>
|
||||||
<string name="vicc">Remote Virtual Smart Card</string>
|
<string name="vicc">Remote Virtual Smart Card</string>
|
||||||
|
|
||||||
|
<string-array name="strNFC">
|
||||||
|
<item>@string/nfc</item>
|
||||||
|
<item>@string/gear</item>
|
||||||
|
</string-array>
|
||||||
|
<string name="nfc">Builtin NFC</string>
|
||||||
|
<string name="gear">Samsung Accessory</string>
|
||||||
|
|
||||||
<string name="vicc_config_info">If you choose the virtual smart card (VICC) as emulator, you need to start the it on your computer with the `--reversed` flag and configure the connection parameters here accordingly.</string>
|
<string name="vicc_config_info">If you choose the virtual smart card (VICC) as emulator, you need to start the it on your computer with the `--reversed` flag and configure the connection parameters here accordingly.</string>
|
||||||
<string name="hint_vicc_port">VICC Port</string>
|
<string name="hint_vicc_port">VICC Port</string>
|
||||||
<string name="hint_vicc_hostname">VICC Hostname</string>
|
<string name="hint_vicc_hostname">VICC Hostname</string>
|
||||||
|
|||||||
51
ACardEmulator/app/src/main/res/xml/accessoryservices.xml
Normal file
51
ACardEmulator/app/src/main/res/xml/accessoryservices.xml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<!DOCTYPE resources [
|
||||||
|
<!ELEMENT resources (application)>
|
||||||
|
<!ELEMENT application (serviceProfile)+>
|
||||||
|
<!ATTLIST application name CDATA #REQUIRED>
|
||||||
|
<!ELEMENT serviceProfile (supportedTransports, serviceChannel+) >
|
||||||
|
<!ATTLIST application xmlns:android CDATA #IMPLIED>
|
||||||
|
<!ATTLIST serviceProfile xmlns:android CDATA #IMPLIED>
|
||||||
|
<!ATTLIST serviceProfile serviceImpl CDATA #REQUIRED>
|
||||||
|
<!ATTLIST serviceProfile role (PROVIDER | CONSUMER | provider | consumer) #REQUIRED>
|
||||||
|
<!ATTLIST serviceProfile name CDATA #REQUIRED>
|
||||||
|
<!ATTLIST serviceProfile id CDATA #REQUIRED>
|
||||||
|
<!ATTLIST serviceProfile version CDATA #REQUIRED>
|
||||||
|
<!ATTLIST serviceProfile serviceLimit (ANY | ONE_ACCESSORY | ONE_PEERAGENT | any | one_accessory | one_peeragent) #IMPLIED>
|
||||||
|
<!ATTLIST serviceProfile serviceTimeout CDATA #IMPLIED>
|
||||||
|
<!ELEMENT supportedTransports (transport)+>
|
||||||
|
<!ATTLIST supportedTransports xmlns:android CDATA #IMPLIED>
|
||||||
|
<!ELEMENT transport EMPTY>
|
||||||
|
<!ATTLIST transport xmlns:android CDATA #IMPLIED>
|
||||||
|
<!ATTLIST transport type (TRANSPORT_WIFI | TRANSPORT_BT | TRANSPORT_BLE | TRANSPORT_USB |
|
||||||
|
transport_wifi | transport_bt | transport_ble | transport_usb) #REQUIRED>
|
||||||
|
<!ELEMENT serviceChannel EMPTY>
|
||||||
|
<!ATTLIST serviceChannel xmlns:android CDATA #IMPLIED>
|
||||||
|
<!ATTLIST serviceChannel id CDATA #REQUIRED>
|
||||||
|
<!ATTLIST serviceChannel dataRate (LOW | HIGH | low | high) #REQUIRED>
|
||||||
|
<!ATTLIST serviceChannel priority (LOW | MEDIUM | HIGH | low | medium | high) #REQUIRED>
|
||||||
|
<!ATTLIST serviceChannel reliability (ENABLE | DISABLE | enable | disable ) #REQUIRED>
|
||||||
|
]>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<application name="HelloAccessoryProvider" >
|
||||||
|
<serviceProfile
|
||||||
|
id="/sample/hello"
|
||||||
|
name="helloaccessory"
|
||||||
|
role="provider"
|
||||||
|
serviceImpl="com.vsmartcard.acardemulator.SmartcardProviderService"
|
||||||
|
version="1.0"
|
||||||
|
serviceLimit="ANY"
|
||||||
|
serviceTimeout="10">
|
||||||
|
<supportedTransports>
|
||||||
|
<transport type="TRANSPORT_BT" />
|
||||||
|
<transport type="TRANSPORT_WIFI" />
|
||||||
|
</supportedTransports>
|
||||||
|
<serviceChannel
|
||||||
|
id="104"
|
||||||
|
dataRate="low"
|
||||||
|
priority="low"
|
||||||
|
reliability= "enable"/>
|
||||||
|
</serviceProfile>
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -81,4 +81,11 @@
|
|||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:key="nfc"
|
||||||
|
android:title="NFC communication hardware"
|
||||||
|
android:defaultValue="@string/nfc"
|
||||||
|
android:entries="@array/strNFC"
|
||||||
|
android:entryValues="@array/strNFC" />
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
Reference in New Issue
Block a user