1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.hardware.usb.aoaphosttest; 17 18 import android.app.Activity; 19 import android.content.BroadcastReceiver; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.IntentFilter; 23 import android.hardware.usb.UsbAccessory; 24 import android.hardware.usb.UsbConstants; 25 import android.hardware.usb.UsbDevice; 26 import android.hardware.usb.UsbDeviceConnection; 27 import android.hardware.usb.UsbEndpoint; 28 import android.hardware.usb.UsbInterface; 29 import android.hardware.usb.UsbManager; 30 import android.os.Bundle; 31 import android.os.Handler; 32 import android.os.HandlerThread; 33 import android.os.Process; 34 import android.text.TextUtils; 35 import android.util.Log; 36 37 import libcore.io.IoUtils; 38 39 public class UsbAoapHostTestActivity extends Activity { 40 41 private static final String TAG = UsbAoapHostTestActivity.class.getSimpleName(); 42 43 private UsbManager mUsbManager; 44 private UsbStateReceiver mReceiver; 45 private UsbDevice mUsbDevice; 46 private UsbDeviceConnection mUsbConnection; 47 private ReaderThread mReaderThread; 48 49 @Override onCreate(Bundle savedInstanceState)50 protected void onCreate(Bundle savedInstanceState) { 51 super.onCreate(savedInstanceState); 52 53 setContentView(R.layout.host); 54 55 mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE); 56 IntentFilter filter = new IntentFilter(); 57 filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 58 mReceiver = new UsbStateReceiver(); 59 registerReceiver(mReceiver, filter); 60 61 Intent intent = getIntent(); 62 if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) { 63 mUsbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); 64 mUsbConnection = mUsbManager.openDevice(mUsbDevice); 65 mReaderThread = new ReaderThread(mUsbDevice, mUsbConnection); 66 mReaderThread.start(); 67 } else { 68 finish(); 69 } 70 } 71 72 @Override onDestroy()73 protected void onDestroy() { 74 super.onDestroy(); 75 unregisterReceiver(mReceiver); 76 if (mUsbConnection != null) { 77 mUsbConnection.close(); 78 } 79 if (mReaderThread != null) { 80 mReaderThread.requestToQuit(); 81 try { 82 mReaderThread.join(1000); 83 } catch (InterruptedException e) { 84 } 85 if (mReaderThread.isAlive()) { // reader thread stuck 86 throw new RuntimeException("ReaderThread still alive"); 87 } 88 } 89 } 90 isDevicesMatching(UsbDevice l, UsbDevice r)91 private static boolean isDevicesMatching(UsbDevice l, UsbDevice r) { 92 if (l.getVendorId() == r.getVendorId() && l.getProductId() == r.getProductId() && 93 TextUtils.equals(l.getSerialNumber(), r.getSerialNumber())) { 94 return true; 95 } 96 return false; 97 } 98 99 private class ReaderThread extends Thread { 100 private boolean mShouldQuit = false; 101 private final UsbDevice mDevice; 102 private final UsbDeviceConnection mUsbConnection; 103 private final UsbEndpoint mBulkIn; 104 private final UsbEndpoint mBulkOut; 105 private final byte[] mBuffer = new byte[16384]; 106 ReaderThread(UsbDevice device, UsbDeviceConnection conn)107 private ReaderThread(UsbDevice device, UsbDeviceConnection conn) { 108 super("AOAP"); 109 mDevice = device; 110 mUsbConnection = conn; 111 UsbInterface iface = mDevice.getInterface(0); 112 // Setup bulk endpoints. 113 UsbEndpoint bulkIn = null; 114 UsbEndpoint bulkOut = null; 115 for (int i = 0; i < iface.getEndpointCount(); i++) { 116 UsbEndpoint ep = iface.getEndpoint(i); 117 if (ep.getDirection() == UsbConstants.USB_DIR_IN) { 118 if (bulkIn == null) { 119 bulkIn = ep; 120 } 121 } else { 122 if (bulkOut == null) { 123 bulkOut = ep; 124 } 125 } 126 } 127 if (bulkIn == null || bulkOut == null) { 128 throw new IllegalStateException("Unable to find bulk endpoints"); 129 } 130 mBulkIn = bulkIn; 131 mBulkOut = bulkOut; 132 } 133 requestToQuit()134 private synchronized void requestToQuit() { 135 mShouldQuit = true; 136 } 137 shouldQuit()138 private synchronized boolean shouldQuit() { 139 return mShouldQuit; 140 } 141 142 @Override run()143 public void run() { 144 while (!shouldQuit()) { 145 int read = mUsbConnection.bulkTransfer(mBulkIn, mBuffer, mBuffer.length, 146 Integer.MAX_VALUE); 147 if (read < 0) { 148 throw new RuntimeException("bulkTransfer failed, read = " + read); 149 } 150 } 151 } 152 } 153 154 private class UsbStateReceiver extends BroadcastReceiver { 155 @Override onReceive(Context context, Intent intent)156 public void onReceive(Context context, Intent intent) { 157 if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) { 158 UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); 159 if (isDevicesMatching(mUsbDevice, device)) { 160 finish(); 161 } 162 } 163 } 164 } 165 } 166