From bd2906a887f22c415f9b194481607660db2216f6 Mon Sep 17 00:00:00 2001 From: Nikita Mikhailov Date: Mon, 4 Apr 2016 00:33:59 +0600 Subject: OTG: Add usb device manager prototype --- .../keychain/javacard/UsbConnectionManager.java | 135 +++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java new file mode 100644 index 000000000..d140c771c --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/javacard/UsbConnectionManager.java @@ -0,0 +1,135 @@ +package org.sufficientlysecure.keychain.javacard; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.util.Log; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Semaphore; + +public class UsbConnectionManager { + private static final String LOG_TAG = UsbConnectionManager.class.getName(); + private static final String ACTION_USB_PERMISSION = Constants.PACKAGE_NAME + ".USB_PERMITSSION"; + + private Activity mActivity; + private OnDiscoveredUsbDeviceListener mListener; + private final Semaphore mRunning = new Semaphore(1); + private final Set mProcessedDevices = Collections.newSetFromMap(new ConcurrentHashMap()); + + /** + * Receives broadcast when a supported USB device is attached, detached or + * when a permission to communicate to the device has been granted. + */ + private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + String deviceName = usbDevice.getDeviceName(); + + if (ACTION_USB_PERMISSION.equals(action)) { + boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, + false); + Log.d(LOG_TAG, "ACTION_USB_PERMISSION: " + permission + " Device: " + deviceName); + + interceptIntent(intent); + + context.unregisterReceiver(mUsbReceiver); + } + } + }; + + private final Thread mWatchThread = new Thread() { + @Override + public void run() { + final UsbManager usbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE); + + while (true) { + mRunning.acquireUninterruptibly(); + mRunning.release(); + + // + + final UsbDevice device = getDevice(usbManager); + if (device != null && !mProcessedDevices.contains(device)) { + mProcessedDevices.add(device); + + final Intent intent = new Intent(ACTION_USB_PERMISSION); + + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_USB_PERMISSION); + mActivity.registerReceiver(mUsbReceiver, filter); + + usbManager.requestPermission(device, PendingIntent.getBroadcast(mActivity, 0, intent, 0)); + } + + try { + sleep(1000); + } catch (InterruptedException ignored) { + } + } + } + }; + + public UsbConnectionManager(final Activity activity, final OnDiscoveredUsbDeviceListener listener) { + this.mActivity = activity; + this.mListener = listener; + mRunning.acquireUninterruptibly(); + mWatchThread.start(); + } + + public void startListeningForDevices() { + mRunning.release(); + } + + public void stopListeningForDevices() { + mRunning.acquireUninterruptibly(); + } + + public void interceptIntent(final Intent intent) { + if (intent == null || intent.getAction() == null) return; + switch (intent.getAction()) { + case UsbManager.ACTION_USB_DEVICE_ATTACHED: { + final UsbManager usbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE); + final UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + Intent usbI = new Intent(mActivity, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); + usbI.setAction(ACTION_USB_PERMISSION); + usbI.putExtra(UsbManager.EXTRA_DEVICE, device); + PendingIntent pi = PendingIntent.getActivity(mActivity, 0, usbI, PendingIntent.FLAG_CANCEL_CURRENT); + usbManager.requestPermission(device, pi); + break; + } + case ACTION_USB_PERMISSION: { + UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + if (device != null) + mListener.usbDeviceDiscovered(device); + break; + } + default: + break; + } + } + + private static UsbDevice getDevice(UsbManager manager) { + HashMap deviceList = manager.getDeviceList(); + for (UsbDevice device : deviceList.values()) { + Log.d(LOG_TAG, device.getDeviceName() + " " + device.getDeviceId()); + if (device.getVendorId() == 0x1050 && device.getProductId() == 0x0112) { + Log.d(LOG_TAG, device.getDeviceName() + " OK"); + return device; + } + } + return null; + } +} -- cgit v1.2.3