package com.fwupgrade.saymanss.deviceplug; 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.UsbDeviceConnection; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.Handler; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public final class CUSBListener { private static final boolean DEBUG = false; private static final String TAG = "USBListener"; private static final String ACTION_USB_PERMISSION_BASE = "com.spca.USB_PERMISSION."; private final String ACTION_USB_PERMISSION = "com.spca.USB_PERMISSION." + hashCode(); public static final String ACTION_USB_DEVICE_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED"; private final ConcurrentHashMap mCtrlBlocks = new ConcurrentHashMap<>(); private final WeakReference mWeakContext; private final UsbManager mUsbManager; private final OnDeviceConnectListener mOnDeviceConnectListener; private PendingIntent mPermissionIntent = null; private List mDeviceFilters = new ArrayList<>(); private final Handler mHandler = new Handler(); private final BroadcastReceiver mUsbReceiver; private volatile int mDeviceCounts; private final Runnable mDeviceCheckRunnable; public void destroy() { unregister(); Set keys = this.mCtrlBlocks.keySet(); if (keys != null) { try { for (UsbDevice key : keys) { UsbControlBlock ctrlBlock = this.mCtrlBlocks.remove(key); ctrlBlock.close(); } } catch (Exception e) { Log.e("USBListener", "destroy:", e); } this.mCtrlBlocks.clear(); } } public synchronized void register() { if (this.mPermissionIntent == null) { Context context = this.mWeakContext.get(); if (context != null) { this.mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(this.ACTION_USB_PERMISSION), 0); //this.mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent("com.android.example.USB_PERMISSION"), 0); IntentFilter filter = new IntentFilter(this.ACTION_USB_PERMISSION); //filter.addAction("android.hardware.usb.action.USB_DEVICE_ATTACHED"); filter.addAction("android.hardware.usb.action.USB_DEVICE_DETACHED"); context.registerReceiver(this.mUsbReceiver, filter); } this.mDeviceCounts = 0; // this.mHandler.postDelayed(this.mDeviceCheckRunnable, 1000L); } } public synchronized void unregister() { if (this.mPermissionIntent != null) { Context context = this.mWeakContext.get(); if (context != null) context.unregisterReceiver(this.mUsbReceiver); this.mPermissionIntent = null; } this.mDeviceCounts = 0; this.mHandler.removeCallbacks(this.mDeviceCheckRunnable); } public synchronized boolean isRegistered() { return (this.mPermissionIntent != null); } public void setDeviceFilter(CDeviceFilter filter) { this.mDeviceFilters.clear(); this.mDeviceFilters.add(filter); } public void setDeviceFilter(List filters) { this.mDeviceFilters.clear(); this.mDeviceFilters.addAll(filters); } public int getDeviceCount() { return getDeviceList().size(); } public List getDeviceList() { return getDeviceList(this.mDeviceFilters); } public List getDeviceList(List filters) { HashMap deviceList = this.mUsbManager.getDeviceList(); List result = new ArrayList<>(); if (deviceList != null) if (filters == null || filters.isEmpty()) { result.addAll(deviceList.values()); } else { Iterator iterator = deviceList.values().iterator(); while (iterator.hasNext()) { UsbDevice device = iterator.next(); label19: for (CDeviceFilter filter : filters) { if (filter != null) { if (filter.matches(device)) break label19; continue; } result.add(device); } } } return result; } public List getDeviceList(CDeviceFilter filter) { HashMap deviceList = this.mUsbManager.getDeviceList(); List result = new ArrayList<>(); if (deviceList != null) { Iterator iterator = deviceList.values().iterator(); while (iterator.hasNext()) { UsbDevice device = iterator.next(); if (filter == null || filter.matches(device)) result.add(device); } } return result; } public Iterator getDevices() { Iterator iterator = null; HashMap list = this.mUsbManager.getDeviceList(); if (list != null) iterator = list.values().iterator(); return iterator; } public boolean hasPermission(UsbDevice device) { return (device != null && this.mUsbManager.hasPermission(device)); } public synchronized void requestPermission(UsbDevice device) { if (this.mPermissionIntent != null) { if (device != null) { if (this.mUsbManager.hasPermission(device)) { procConnect(device); } else { this.mUsbManager.requestPermission(device, this.mPermissionIntent); } } else { procCancel(device); } } else { procCancel(device); } } public CUSBListener(Context context, OnDeviceConnectListener listener) { this.mUsbReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (CUSBListener.this.ACTION_USB_PERMISSION.equals(action)) { Log.d(TAG, "ACTION_USB_PERMISSION"); synchronized (CUSBListener.this) { UsbDevice device = (UsbDevice)intent.getParcelableExtra("device"); if (intent.getBooleanExtra("permission", false)) { if (device != null) CUSBListener.this.procConnect(device); } else { CUSBListener.this.procCancel(device); } } } else if ("android.hardware.usb.action.USB_DEVICE_ATTACHED".equals(action)) { Log.d(TAG, "android.hardware.usb.action.USB_DEVICE_ATTACHED"); UsbDevice device = (UsbDevice)intent.getParcelableExtra("device"); CUSBListener.this.procAttach(device); } else if ("android.hardware.usb.action.USB_DEVICE_DETACHED".equals(action)) { Log.d(TAG, "android.hardware.usb.action.USB_DEVICE_DETACHED"); UsbDevice device = (UsbDevice)intent.getParcelableExtra("device"); if (device != null) { UsbControlBlock ctrlBlock = null; ctrlBlock = (UsbControlBlock)CUSBListener.this.mCtrlBlocks.remove(device); if (ctrlBlock != null) ctrlBlock.close(); CUSBListener.this.mDeviceCounts = 0; CUSBListener.this.procDettach(device); } } } }; this.mDeviceCounts = 0; this.mDeviceCheckRunnable = new Runnable() { public void run() { int n = CUSBListener.this.getDeviceCount(); if (n != CUSBListener.this.mDeviceCounts && n > CUSBListener.this.mDeviceCounts) { CUSBListener.this.mDeviceCounts = n; if (CUSBListener.this.mOnDeviceConnectListener != null) { Log.d(TAG, "onAttach empty"); CUSBListener.this.mOnDeviceConnectListener.onAttach(null); } } CUSBListener.this.mHandler.postDelayed(this, 2000L); } }; this.mWeakContext = new WeakReference<>(context); this.mUsbManager = (UsbManager)context.getSystemService("usb"); this.mOnDeviceConnectListener = listener; } private final void procConnect(final UsbDevice device) { this.mHandler.post(new Runnable() { public void run() { boolean createNew; UsbControlBlock ctrlBlock = (UsbControlBlock)CUSBListener.this.mCtrlBlocks.get(device); if (ctrlBlock == null) { ctrlBlock = new UsbControlBlock(CUSBListener.this, device); CUSBListener.this.mCtrlBlocks.put(device, ctrlBlock); createNew = true; } else { createNew = false; } if (CUSBListener.this.mOnDeviceConnectListener != null) { UsbControlBlock ctrlB = ctrlBlock; CUSBListener.this.mOnDeviceConnectListener.onConnect(device, ctrlB, createNew); } } }); } private final void procCancel(UsbDevice device) { if (this.mOnDeviceConnectListener != null) this.mHandler.post(new Runnable() { public void run() { CUSBListener.this.mOnDeviceConnectListener.onCancel(); } }); } private final void procAttach(final UsbDevice device) { if (this.mOnDeviceConnectListener != null) this.mHandler.post(new Runnable() { public void run() { Log.d(TAG, "procAttach"); CUSBListener.this.mOnDeviceConnectListener.onAttach(device); } }); } private final void procDettach(final UsbDevice device) { if (this.mOnDeviceConnectListener != null) this.mHandler.post(new Runnable() { public void run() { CUSBListener.this.mOnDeviceConnectListener.onDettach(device); } }); } public static interface OnDeviceConnectListener { void onAttach(UsbDevice param1UsbDevice); void onDettach(UsbDevice param1UsbDevice); void onConnect(UsbDevice param1UsbDevice, UsbControlBlock param1UsbControlBlock, boolean param1Boolean); void onDisconnect(UsbDevice param1UsbDevice, UsbControlBlock param1UsbControlBlock); void onCancel(); } public static final class UsbControlBlock { private final WeakReference mWeakMonitor; private final WeakReference mWeakDevice; protected UsbDeviceConnection mConnection; private final int mBusNum; private final int mDevNum; private final SparseArray mInterfaces = new SparseArray(); public UsbControlBlock(CUSBListener listener, UsbDevice device) { this.mWeakMonitor = new WeakReference<>(listener); this.mWeakDevice = new WeakReference<>(device); this.mConnection = listener.mUsbManager.openDevice(device); String name = device.getDeviceName(); String[] v = !TextUtils.isEmpty(name) ? name.split("/") : null; int busnum = 0; int devnum = 0; if (v != null) { busnum = Integer.parseInt(v[v.length - 2]); devnum = Integer.parseInt(v[v.length - 1]); } this.mBusNum = busnum; this.mDevNum = devnum; if (this.mConnection == null) Log.e("USBListener", "could not connect to device " + name); } public UsbDevice getDevice() { return this.mWeakDevice.get(); } public String getDeviceName() { UsbDevice device = this.mWeakDevice.get(); return (device != null) ? device.getDeviceName() : ""; } public UsbDeviceConnection getUsbDeviceConnection() { return this.mConnection; } public synchronized int getFileDescriptor() { return (this.mConnection != null) ? this.mConnection.getFileDescriptor() : -1; } public byte[] getRawDescriptors() { return (this.mConnection != null) ? this.mConnection.getRawDescriptors() : null; } public int getVenderId() { UsbDevice device = this.mWeakDevice.get(); return (device != null) ? device.getVendorId() : 0; } public int getProductId() { UsbDevice device = this.mWeakDevice.get(); return (device != null) ? device.getProductId() : 0; } public int getBcdDevice() { byte[] descriptor = this.mConnection.getRawDescriptors(); int bcd = descriptor[13] << 8 | descriptor[12]; return bcd; } public synchronized String getSerial() { return (this.mConnection != null) ? this.mConnection.getSerial() : null; } public int getBusNum() { return this.mBusNum; } public int getDevNum() { return this.mDevNum; } public synchronized UsbInterface open(int interfaceIndex) { UsbDevice device = this.mWeakDevice.get(); UsbInterface intf = null; intf = (UsbInterface)this.mInterfaces.get(interfaceIndex); if (intf == null) { intf = device.getInterface(interfaceIndex); if (intf != null) synchronized (this.mInterfaces) { this.mInterfaces.append(interfaceIndex, intf); } } return intf; } public void close(int interfaceIndex) { UsbInterface intf = null; synchronized (this.mInterfaces) { intf = (UsbInterface)this.mInterfaces.get(interfaceIndex); if (intf != null) { this.mInterfaces.delete(interfaceIndex); this.mConnection.releaseInterface(intf); } } } public synchronized void close() { if (this.mConnection != null) { int n = this.mInterfaces.size(); for (int i = 0; i < n; i++) { int key = this.mInterfaces.keyAt(i); UsbInterface intf = (UsbInterface)this.mInterfaces.get(key); this.mConnection.releaseInterface(intf); } this.mConnection.close(); this.mConnection = null; CUSBListener listener = this.mWeakMonitor.get(); if (listener != null) { if (listener.mOnDeviceConnectListener != null) { UsbDevice device = this.mWeakDevice.get(); listener.mOnDeviceConnectListener.onDisconnect(device, this); } listener.mCtrlBlocks.remove(getDevice()); } } } } }