Java tutorial
/* * Copyright (C) 2016 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 org.chromium.latency.walt; 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.UsbManager; import android.support.v4.content.LocalBroadcastManager; import java.util.HashMap; import java.util.Locale; public abstract class BaseUsbConnection { private static final String USB_PERMISSION_RESPONSE_INTENT = "usb-permission-response"; private static final String CONNECT_INTENT = "org.chromium.latency.walt.CONNECT"; protected SimpleLogger logger; protected Context context; private LocalBroadcastManager broadcastManager; private BroadcastReceiver currentConnectReceiver; private WaltConnection.ConnectionStateListener connectionStateListener; private UsbManager usbManager; protected UsbDevice usbDevice = null; protected UsbDeviceConnection usbConnection; public BaseUsbConnection(Context context) { this.context = context; usbManager = (UsbManager) this.context.getSystemService(Context.USB_SERVICE); logger = SimpleLogger.getInstance(context); broadcastManager = LocalBroadcastManager.getInstance(context); } public abstract int getVid(); public abstract int getPid(); // Used to distinguish between bootloader and normal mode that differ by PID // TODO: change intent strings to reduce dependence on PID protected abstract boolean isCompatibleUsbDevice(UsbDevice usbDevice); public void onDisconnect() { if (connectionStateListener != null) { connectionStateListener.onDisconnect(); } } public void onConnect() { if (connectionStateListener != null) { connectionStateListener.onConnect(); } } private String getConnectIntent() { return CONNECT_INTENT + getVid() + ":" + getPid(); } private String getUsbPermissionResponseIntent() { return USB_PERMISSION_RESPONSE_INTENT + getVid() + ":" + getPid(); } public boolean isConnected() { return usbConnection != null; } public void registerConnectCallback(final Runnable r) { if (currentConnectReceiver != null) { broadcastManager.unregisterReceiver(currentConnectReceiver); currentConnectReceiver = null; } if (isConnected()) { r.run(); return; } currentConnectReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { broadcastManager.unregisterReceiver(this); r.run(); } }; broadcastManager.registerReceiver(currentConnectReceiver, new IntentFilter(getConnectIntent())); } public void connect() { UsbDevice usbDevice = findUsbDevice(); connect(usbDevice); } public void connect(UsbDevice usbDevice) { if (usbDevice == null) { logger.log("Device not found."); return; } if (!isCompatibleUsbDevice(usbDevice)) { logger.log("Not a valid device"); return; } this.usbDevice = usbDevice; // Request permission // This displays a dialog asking user for permission to use the device. // No dialog is displayed if the permission was already given before or the app started as a // result of intent filter when the device was plugged in. PendingIntent permissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(getUsbPermissionResponseIntent()), 0); context.registerReceiver(respondToUsbPermission, new IntentFilter(getUsbPermissionResponseIntent())); logger.log("Requesting permission for USB device."); usbManager.requestPermission(this.usbDevice, permissionIntent); } public void disconnect() { onDisconnect(); usbConnection.close(); usbConnection = null; usbDevice = null; context.unregisterReceiver(disconnectReceiver); } private BroadcastReceiver disconnectReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); if (isConnected() && BaseUsbConnection.this.usbDevice.equals(usbDevice)) { logger.log("WALT was detached"); disconnect(); } } }; private BroadcastReceiver respondToUsbPermission = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (usbDevice == null) { logger.log("USB device was not properly opened"); return; } if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) && usbDevice.equals(intent.getParcelableExtra(UsbManager.EXTRA_DEVICE))) { usbConnection = usbManager.openDevice(usbDevice); BaseUsbConnection.this.context.registerReceiver(disconnectReceiver, new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED)); onConnect(); broadcastManager.sendBroadcast(new Intent(getConnectIntent())); } else { logger.log("Could not get permission to open the USB device"); } BaseUsbConnection.this.context.unregisterReceiver(respondToUsbPermission); } }; public UsbDevice findUsbDevice() { logger.log(String.format("Looking for TeensyUSB VID=0x%x PID=0x%x", getVid(), getPid())); HashMap<String, UsbDevice> deviceHash = usbManager.getDeviceList(); if (deviceHash.size() == 0) { logger.log("No connected USB devices found"); return null; } logger.log("Found " + deviceHash.size() + " connected USB devices:"); UsbDevice usbDevice = null; for (String key : deviceHash.keySet()) { UsbDevice dev = deviceHash.get(key); String msg = String.format(Locale.US, "USB Device: %s, VID:PID - %x:%x, %d interfaces", key, dev.getVendorId(), dev.getProductId(), dev.getInterfaceCount()); if (isCompatibleUsbDevice(dev)) { usbDevice = dev; msg = "Using " + msg; } else { msg = "Skipping " + msg; } logger.log(msg); } return usbDevice; } public void setConnectionStateListener(WaltConnection.ConnectionStateListener connectionStateListener) { this.connectionStateListener = connectionStateListener; } }