1d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan/* 2d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * Copyright (C) 2016 The Android Open Source Project 3d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * 4d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * Licensed under the Apache License, Version 2.0 (the "License"); 5d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * you may not use this file except in compliance with the License. 6d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * You may obtain a copy of the License at 7d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * 8d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * http://www.apache.org/licenses/LICENSE-2.0 9d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * 10d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * Unless required by applicable law or agreed to in writing, software 11d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * distributed under the License is distributed on an "AS IS" BASIS, 12d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * See the License for the specific language governing permissions and 14d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * limitations under the License. 15d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan */ 16d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanpackage android.car.usb.handler; 17d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 18d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.car.IUsbAoapSupportCheckService; 19d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.ComponentName; 20d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.Context; 21d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.Intent; 22d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.ServiceConnection; 23d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.pm.ActivityInfo; 24d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.pm.PackageManager; 25d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.pm.PackageManager.NameNotFoundException; 26d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.pm.ResolveInfo; 27d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.content.res.XmlResourceParser; 28d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.hardware.usb.UsbDevice; 29d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.hardware.usb.UsbDeviceConnection; 30d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.hardware.usb.UsbInterface; 31d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.hardware.usb.UsbManager; 32d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.os.Handler; 33d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.os.HandlerThread; 34d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.os.IBinder; 35d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.os.Looper; 36d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.os.Message; 37d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.os.RemoteException; 38d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.util.Log; 39d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport android.util.Pair; 40d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport com.android.internal.util.XmlUtils; 41d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport java.io.IOException; 42d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport java.util.ArrayList; 43d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport java.util.LinkedList; 44d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport java.util.List; 45d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport java.util.Queue; 46d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanimport org.xmlpull.v1.XmlPullParser; 47d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 48d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan/** Resolves supported handlers for USB device. */ 49d428549b58b2df5015bff81d79747265ee8be536Kevin Crossanpublic final class UsbDeviceHandlerResolver { 50d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static final String TAG = UsbDeviceHandlerResolver.class.getSimpleName(); 51d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static final boolean LOCAL_LOGD = true; 52d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 53d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan /** 54d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * Callbacks for device resolver. 55d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan */ 56d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public interface UsbDeviceHandlerResolverCallback { 57d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan /** Handlers are resolved */ 58d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan void onHandlersResolveCompleted( 59d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbDevice device, List<UsbDeviceSettings> availableSettings); 60d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan /** Device was dispatched */ 61d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan void onDeviceDispatched(); 62d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 63d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 64d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private final UsbManager mUsbManager; 65d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private final PackageManager mPackageManager; 66d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private final UsbDeviceHandlerResolverCallback mDeviceCallback; 67d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private final Context mContext; 68d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private final HandlerThread mHandlerThread; 69d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private final UsbDeviceResolverHandler mHandler; 70d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 71d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private class DeviceContext { 72d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final UsbDevice usbDevice; 73d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final UsbDeviceConnection connection; 74d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final UsbDeviceSettings settings; 75d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final List<UsbDeviceSettings> activeDeviceSettings; 76d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final Queue<Pair<ResolveInfo, DeviceFilter>> mActiveDeviceOptions = 77d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan new LinkedList<>(); 78d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 79d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private volatile IUsbAoapSupportCheckService mUsbAoapSupportCheckService; 80d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private final ServiceConnection mServiceConnection = new ServiceConnection() { 81d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan @Override 82d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void onServiceConnected(ComponentName className, IBinder service) { 83d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.i(TAG, "onServiceConnected: " + className); 84d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mUsbAoapSupportCheckService = IUsbAoapSupportCheckService.Stub.asInterface(service); 85d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandler.requestOnServiceConnectionStateChanged(DeviceContext.this); 86d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 87d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 88d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan @Override 89d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void onServiceDisconnected(ComponentName className) { 90d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.i(TAG, "onServiceDisconnected: " + className); 91d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mUsbAoapSupportCheckService = null; 92d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandler.requestOnServiceConnectionStateChanged(DeviceContext.this); 93d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 94d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan }; 95d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 96d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public DeviceContext(UsbDevice usbDevice, UsbDeviceSettings settings, 97d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan List<UsbDeviceSettings> activeDeviceSettings) { 98d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan this.usbDevice = usbDevice; 99d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan this.settings = settings; 100d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan this.activeDeviceSettings = activeDeviceSettings; 101d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan connection = UsbUtil.openConnection(mUsbManager, usbDevice); 102d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 103d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 104d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 105d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // This class is used to describe a USB device. 106d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // When used in HashMaps all values must be specified, 107d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // but wildcards can be used for any of the fields in 108d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // the package meta-data. 109d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static class DeviceFilter { 110d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB Vendor ID (or -1 for unspecified) 111d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final int mVendorId; 112d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB Product ID (or -1 for unspecified) 113d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final int mProductId; 114d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device or interface class (or -1 for unspecified) 115d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final int mClass; 116d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device subclass (or -1 for unspecified) 117d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final int mSubclass; 118d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device protocol (or -1 for unspecified) 119d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final int mProtocol; 120d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device manufacturer name string (or null for unspecified) 121d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mManufacturerName; 122d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device product name string (or null for unspecified) 123d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mProductName; 124d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device serial number string (or null for unspecified) 125d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mSerialNumber; 126d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 127d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device in AOAP mode manufacturer 128d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mAoapManufacturer; 129d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device in AOAP mode model 130d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mAoapModel; 131d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device in AOAP mode description string 132d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mAoapDescription; 133d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device in AOAP mode version 134d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mAoapVersion; 135d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device in AOAP mode URI 136d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mAoapUri; 137d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device in AOAP mode serial 138d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mAoapSerial; 139d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // USB device in AOAP mode verification service 140d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public final String mAoapService; 141d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 142d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol, 143d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String manufacturer, String product, String serialnum, 144d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapManufacturer, String aoapModel, String aoapDescription, 145d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapVersion, String aoapUri, String aoapSerial, 146d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapService) { 147d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mVendorId = vid; 148d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mProductId = pid; 149d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mClass = clasz; 150d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mSubclass = subclass; 151d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mProtocol = protocol; 152d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mManufacturerName = manufacturer; 153d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mProductName = product; 154d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mSerialNumber = serialnum; 155d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 156d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapManufacturer = aoapManufacturer; 157d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapModel = aoapModel; 158d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapDescription = aoapDescription; 159d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapVersion = aoapVersion; 160d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapUri = aoapUri; 161d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapSerial = aoapSerial; 162d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapService = aoapService; 163d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 164d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 165d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan DeviceFilter(UsbDevice device) { 166d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mVendorId = device.getVendorId(); 167d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mProductId = device.getProductId(); 168d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mClass = device.getDeviceClass(); 169d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mSubclass = device.getDeviceSubclass(); 170d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mProtocol = device.getDeviceProtocol(); 171d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mManufacturerName = device.getManufacturerName(); 172d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mProductName = device.getProductName(); 173d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mSerialNumber = device.getSerialNumber(); 174d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapManufacturer = null; 175d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapModel = null; 176d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapDescription = null; 177d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapVersion = null; 178d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapUri = null; 179d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapSerial = null; 180d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mAoapService = null; 181d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 182d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 183d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public static DeviceFilter read(XmlPullParser parser, boolean aoapData) { 184d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int vendorId = -1; 185d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int productId = -1; 186d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int deviceClass = -1; 187d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int deviceSubclass = -1; 188d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int deviceProtocol = -1; 189d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String manufacturerName = null; 190d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String productName = null; 191d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String serialNumber = null; 192d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 193d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapManufacturer = null; 194d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapModel = null; 195d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapDescription = null; 196d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapVersion = null; 197d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapUri = null; 198d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapSerial = null; 199d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String aoapService = null; 200d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 201d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int count = parser.getAttributeCount(); 202d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan for (int i = 0; i < count; i++) { 203d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String name = parser.getAttributeName(i); 204d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String value = parser.getAttributeValue(i); 205d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // Attribute values are ints or strings 206d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (!aoapData && "manufacturer-name".equals(name)) { 207d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan manufacturerName = value; 208d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (!aoapData && "product-name".equals(name)) { 209d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan productName = value; 210d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (!aoapData && "serial-number".equals(name)) { 211d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan serialNumber = value; 212d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (aoapData && "manufacturer".equals(name)) { 213d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapManufacturer = value; 214d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (aoapData && "model".equals(name)) { 215d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapModel = value; 216d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (aoapData && "description".equals(name)) { 217d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapDescription = value; 218d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (aoapData && "version".equals(name)) { 219d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapVersion = value; 220d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (aoapData && "uri".equals(name)) { 221d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapUri = value; 222d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (aoapData && "serial".equals(name)) { 223d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapSerial = value; 224d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (aoapData && "service".equals(name)) { 225d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapService = value; 226d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if (!aoapData) { 227d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int intValue = -1; 228d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int radix = 10; 229d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (value != null && value.length() > 2 && value.charAt(0) == '0' 230d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && (value.charAt(1) == 'x' || value.charAt(1) == 'X')) { 231d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // allow hex values starting with 0x or 0X 232d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan radix = 16; 233d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan value = value.substring(2); 234d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 235d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan try { 236d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan intValue = Integer.parseInt(value, radix); 237d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } catch (NumberFormatException e) { 238d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.e(TAG, "invalid number for field " + name, e); 239d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan continue; 240d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 241d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if ("vendor-id".equals(name)) { 242d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan vendorId = intValue; 243d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if ("product-id".equals(name)) { 244d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan productId = intValue; 245d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if ("class".equals(name)) { 246d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceClass = intValue; 247d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if ("subclass".equals(name)) { 248d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceSubclass = intValue; 249d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else if ("protocol".equals(name)) { 250d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceProtocol = intValue; 251d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 252d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 253d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 254d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return new DeviceFilter(vendorId, productId, 255d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceClass, deviceSubclass, deviceProtocol, 256d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan manufacturerName, productName, serialNumber, aoapManufacturer, 257d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapModel, aoapDescription, aoapVersion, aoapUri, aoapSerial, 258d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan aoapService); 259d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 260d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 261d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private boolean matches(int clasz, int subclass, int protocol) { 262d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return ((mClass == -1 || clasz == mClass) 263d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && (mSubclass == -1 || subclass == mSubclass) 264d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && (mProtocol == -1 || protocol == mProtocol)); 265d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 266d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 267d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public boolean matches(UsbDevice device) { 268d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mVendorId != -1 && device.getVendorId() != mVendorId) { 269d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 270d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 271d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mProductId != -1 && device.getProductId() != mProductId) { 272d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 273d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 274d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mManufacturerName != null && device.getManufacturerName() == null) { 275d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 276d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 277d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mProductName != null && device.getProductName() == null) { 278d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 279d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 280d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mSerialNumber != null && device.getSerialNumber() == null) { 281d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 282d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 283d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mManufacturerName != null && device.getManufacturerName() != null 284d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mManufacturerName.equals(device.getManufacturerName())) { 285d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 286d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 287d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mProductName != null && device.getProductName() != null 288d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mProductName.equals(device.getProductName())) { 289d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 290d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 291d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mSerialNumber != null && device.getSerialNumber() != null 292d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mSerialNumber.equals(device.getSerialNumber())) { 293d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 294d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 295d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 296d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // check device class/subclass/protocol 297d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (matches(device.getDeviceClass(), device.getDeviceSubclass(), 298d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan device.getDeviceProtocol())) { 299d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return true; 300d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 301d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 302d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // if device doesn't match, check the interfaces 303d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan int count = device.getInterfaceCount(); 304d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan for (int i = 0; i < count; i++) { 305d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbInterface intf = device.getInterface(i); 306d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(), 307d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan intf.getInterfaceProtocol())) { 308d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return true; 309d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 310d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 311d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 312d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 313d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 314d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 315d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan @Override 316d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public boolean equals(Object obj) { 317d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan // can't compare if we have wildcard strings 318d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mVendorId == -1 || mProductId == -1 319d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || mClass == -1 || mSubclass == -1 || mProtocol == -1) { 320d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 321d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 322d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (obj instanceof DeviceFilter) { 323d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan DeviceFilter filter = (DeviceFilter) obj; 324d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 325d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (filter.mVendorId != mVendorId 326d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || filter.mProductId != mProductId 327d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || filter.mClass != mClass 328d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || filter.mSubclass != mSubclass 329d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || filter.mProtocol != mProtocol) { 330d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 331d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 332d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if ((filter.mManufacturerName != null && mManufacturerName == null) 333d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (filter.mManufacturerName == null && mManufacturerName != null) 334d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (filter.mProductName != null && mProductName == null) 335d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (filter.mProductName == null && mProductName != null) 336d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (filter.mSerialNumber != null && mSerialNumber == null) 337d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (filter.mSerialNumber == null && mSerialNumber != null)) { 338d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 339d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 340d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if ((filter.mManufacturerName != null && mManufacturerName != null 341d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mManufacturerName.equals(filter.mManufacturerName)) 342d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (filter.mProductName != null && mProductName != null 343d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mProductName.equals(filter.mProductName)) 344d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (filter.mSerialNumber != null && mSerialNumber != null 345d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mSerialNumber.equals(filter.mSerialNumber))) { 346d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 347d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 348d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return true; 349d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 350d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (obj instanceof UsbDevice) { 351d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbDevice device = (UsbDevice) obj; 352d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (device.getVendorId() != mVendorId 353d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || device.getProductId() != mProductId 354d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || device.getDeviceClass() != mClass 355d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || device.getDeviceSubclass() != mSubclass 356d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || device.getDeviceProtocol() != mProtocol) { 357d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 358d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 359d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if ((mManufacturerName != null && device.getManufacturerName() == null) 360d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (mManufacturerName == null && device.getManufacturerName() != null) 361d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (mProductName != null && device.getProductName() == null) 362d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (mProductName == null && device.getProductName() != null) 363d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (mSerialNumber != null && device.getSerialNumber() == null) 364d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (mSerialNumber == null && device.getSerialNumber() != null)) { 365d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 366d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 367d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if ((device.getManufacturerName() != null 368d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mManufacturerName.equals(device.getManufacturerName())) 369d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (device.getProductName() != null 370d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mProductName.equals(device.getProductName())) 371d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan || (device.getSerialNumber() != null 372d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan && !mSerialNumber.equals(device.getSerialNumber()))) { 373d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 374d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 375d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return true; 376d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 377d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 378d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 379d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 380d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan @Override 381d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public int hashCode() { 382d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return (((mVendorId << 16) | mProductId) 383d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan ^ ((mClass << 16) | (mSubclass << 8) | mProtocol)); 384d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 385d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 386d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan @Override 387d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public String toString() { 388d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" + mProductId 389d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan + ",mClass=" + mClass + ",mSubclass=" + mSubclass 390d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan + ",mProtocol=" + mProtocol + ",mManufacturerName=" + mManufacturerName 391d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan + ",mProductName=" + mProductName + ",mSerialNumber=" + mSerialNumber + "]"; 392d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 393d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 394d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 395d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public UsbDeviceHandlerResolver(UsbManager manager, Context context, 396d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbDeviceHandlerResolverCallback deviceListener) { 397d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mUsbManager = manager; 398d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mContext = context; 399d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mDeviceCallback = deviceListener; 400d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandlerThread = new HandlerThread(TAG); 401d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandlerThread.start(); 402d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandler = new UsbDeviceResolverHandler(mHandlerThread.getLooper()); 403d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mPackageManager = context.getPackageManager(); 404d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 405d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 406d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan /** 407d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * Releases current object. 408d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan */ 409d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void release() { 410d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (mHandlerThread != null) { 411d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandlerThread.quitSafely(); 412d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 413d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 414d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 415d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan /** 416d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * Resolves handlers for USB device. 417d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan */ 418d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void resolve(UsbDevice device) { 419d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandler.requestResolveHandlers(device); 420d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 421d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 422d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan /** 423d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan * Dispatches device to component. 424d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan */ 425d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public boolean dispatch(UsbDevice device, ComponentName component, boolean inAoap) { 426d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (LOCAL_LOGD) { 427d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.d(TAG, "dispatch: " + device + " component: " + component + " inAoap: " + inAoap); 428d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 429d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 430d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan ActivityInfo activityInfo; 431d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan try { 432d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan activityInfo = mPackageManager.getActivityInfo(component, PackageManager.GET_META_DATA); 433d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } catch (NameNotFoundException e) { 434d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.e(TAG, "Activity not found: " + component); 435d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return false; 436d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 437d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 438d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Intent intent = createDeviceAttachedIntent(device); 439d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (inAoap) { 440d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (AoapInterface.isDeviceInAoapMode(device)) { 441d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mDeviceCallback.onDeviceDispatched(); 442d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else { 443d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan DeviceFilter filter = 444d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan packageMatches(activityInfo, intent.getAction(), device, true); 445d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (filter != null) { 446d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan requestAoapSwitch(device, filter); 447d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return true; 448d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 449d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 450d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 451d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 452d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan intent.setComponent(component); 453d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mUsbManager.grantPermission(device, activityInfo.applicationInfo.uid); 454d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 455d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mContext.startActivity(intent); 456d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandler.requestCompleteDeviceDispatch(); 457d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return true; 458d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 459d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 460d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static Intent createDeviceAttachedIntent(UsbDevice device) { 461d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); 462d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan intent.putExtra(UsbManager.EXTRA_DEVICE, device); 463d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 464d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return intent; 465d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 466d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 467d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private void doHandleResolveHandlers(UsbDevice device) { 468d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (LOCAL_LOGD) { 469d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.d(TAG, "doHandleResolveHandlers: " + device); 470d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 471d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 472d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Intent intent = createDeviceAttachedIntent(device); 473d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan List<Pair<ResolveInfo, DeviceFilter>> matches = getDeviceMatches(device, intent, false); 474d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (LOCAL_LOGD) { 475d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.d(TAG, "matches size: " + matches.size()); 476d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 477d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan List<UsbDeviceSettings> settings = new ArrayList<>(matches.size()); 478d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan for (Pair<ResolveInfo, DeviceFilter> info : matches) { 479d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbDeviceSettings setting = UsbDeviceSettings.constructSettings(device); 480d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan setting.setHandler( 481d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan new ComponentName( 482d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan info.first.activityInfo.packageName, info.first.activityInfo.name)); 483d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan settings.add(setting); 484d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 485d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan DeviceContext deviceContext = 486d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan new DeviceContext(device, UsbDeviceSettings.constructSettings(device), settings); 487d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (AoapInterface.isSupported(deviceContext.connection)) { 488d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceContext.mActiveDeviceOptions.addAll(getDeviceMatches(device, intent, true)); 489d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan queryNextAoapHandler(deviceContext); 490d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else { 491d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceProbingComplete(deviceContext); 492d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 493d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 494d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 495d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private void queryNextAoapHandler(DeviceContext context) { 496d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Pair<ResolveInfo, DeviceFilter> option = context.mActiveDeviceOptions.peek(); 497d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (option == null) { 498d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.w(TAG, "No more options left."); 499d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceProbingComplete(context); 500d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return; 501d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 502d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Intent serviceIntent = new Intent(); 503d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan serviceIntent.setComponent(ComponentName.unflattenFromString(option.second.mAoapService)); 504d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan boolean bound = mContext.bindService(serviceIntent, context.mServiceConnection, 505d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Context.BIND_AUTO_CREATE); 506d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (bound) { 507d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mHandler.requestServiceConnectionTimeout(); 508d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } else { 509d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (LOCAL_LOGD) { 510d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.d(TAG, "Failed to bind to the service"); 511d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 512d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan context.mActiveDeviceOptions.poll(); 513d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan queryNextAoapHandler(context); 514d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 515d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 516d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 517d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private void requestAoapSwitch(UsbDevice device, DeviceFilter filter) { 518d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbDeviceConnection connection = UsbUtil.openConnection(mUsbManager, device); 519d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan try { 520d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbUtil.sendAoapAccessoryStart( 521d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan connection, 522d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan filter.mAoapManufacturer, 523d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan filter.mAoapModel, 524d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan filter.mAoapDescription, 525d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan filter.mAoapVersion, 526d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan filter.mAoapUri, 527d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan filter.mAoapSerial); 528d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } catch (IOException e) { 529d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.w(TAG, "Failed to switch device into AOAP mode", e); 530d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 531d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan connection.close(); 532d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 533d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 534d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private void deviceProbingComplete(DeviceContext context) { 535d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (LOCAL_LOGD) { 536d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.d(TAG, "deviceProbingComplete"); 537d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 538d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mDeviceCallback.onHandlersResolveCompleted(context.usbDevice, context.activeDeviceSettings); 539d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 540d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 541d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private void doHandleServiceConnectionStateChanged(DeviceContext context) { 542d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (LOCAL_LOGD) { 543d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.d(TAG, "doHandleServiceConnectionStateChanged: " 544d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan + context.mUsbAoapSupportCheckService); 545d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 546d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (context.mUsbAoapSupportCheckService != null) { 547d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan boolean deviceSupported = false; 548d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan try { 549d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan deviceSupported = 550d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan context.mUsbAoapSupportCheckService.isDeviceSupported(context.usbDevice); 551d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } catch (RemoteException e) { 552d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.e(TAG, "Call to remote service failed", e); 553d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 554d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (deviceSupported) { 555d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Pair<ResolveInfo, DeviceFilter> option = context.mActiveDeviceOptions.peek(); 556d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 557d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbDeviceSettings setting = UsbDeviceSettings.constructSettings(context.settings); 558d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan setting.setHandler( 559d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan new ComponentName( 560d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan option.first.activityInfo.packageName, option.first.activityInfo.name)); 561d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan setting.setAoap(true); 562d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan context.activeDeviceSettings.add(setting); 563d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 564d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mContext.unbindService(context.mServiceConnection); 565d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 566d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan context.mActiveDeviceOptions.poll(); 567d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan queryNextAoapHandler(context); 568d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 569d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 570d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private List<Pair<ResolveInfo, DeviceFilter>> getDeviceMatches( 571d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan UsbDevice device, Intent intent, boolean forAoap) { 572d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan List<Pair<ResolveInfo, DeviceFilter>> matches = new ArrayList<>(); 573d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan List<ResolveInfo> resolveInfos = 574d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mPackageManager.queryIntentActivities(intent, PackageManager.GET_META_DATA); 575d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan for (ResolveInfo resolveInfo : resolveInfos) { 576d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan DeviceFilter filter = packageMatches(resolveInfo.activityInfo, 577d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan intent.getAction(), device, forAoap); 578d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (filter != null) { 579d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan matches.add(Pair.create(resolveInfo, filter)); 580d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 581d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 582d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return matches; 583d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 584d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 585d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private DeviceFilter packageMatches(ActivityInfo ai, String metaDataName, UsbDevice device, 586d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan boolean forAoap) { 587d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (LOCAL_LOGD) { 588d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.d(TAG, "packageMatches ai: " + ai + "metaDataName: " + metaDataName + " forAoap: " 589d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan + forAoap); 590d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 591d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String filterTagName = forAoap ? "usb-aoap-accessory" : "usb-device"; 592d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan XmlResourceParser parser = null; 593d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan try { 594d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan parser = ai.loadXmlMetaData(mPackageManager, metaDataName); 595d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (parser == null) { 596d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.w(TAG, "no meta-data for " + ai); 597d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return null; 598d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 599d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 600d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan XmlUtils.nextElement(parser); 601d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { 602d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan String tagName = parser.getName(); 603d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (device != null && filterTagName.equals(tagName)) { 604d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan DeviceFilter filter = DeviceFilter.read(parser, forAoap); 605d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (forAoap || filter.matches(device)) { 606d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return filter; 607d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 608d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 609d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan XmlUtils.nextElement(parser); 610d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 611d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } catch (Exception e) { 612d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.w(TAG, "Unable to load component info " + ai.toString(), e); 613d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } finally { 614d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan if (parser != null) parser.close(); 615d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 616d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan return null; 617d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 618d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 619d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private class UsbDeviceResolverHandler extends Handler { 620d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static final int MSG_RESOLVE_HANDLERS = 0; 621d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static final int MSG_SERVICE_CONNECTION_STATE_CHANGE = 1; 622d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static final int MSG_SERVICE_CONNECTION_TIMEOUT = 2; 623d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static final int MSG_COMPLETE_DISPATCH = 3; 624d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 625d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private static final long CONNECT_TIMEOUT_MS = 5000; 626d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 627d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan private UsbDeviceResolverHandler(Looper looper) { 628d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan super(looper); 629d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 630d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 631d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void requestResolveHandlers(UsbDevice device) { 632d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Message msg = obtainMessage(MSG_RESOLVE_HANDLERS, device); 633d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan sendMessage(msg); 634d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 635d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 636d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void requestOnServiceConnectionStateChanged(DeviceContext deviceContext) { 637d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan sendMessage(obtainMessage(MSG_SERVICE_CONNECTION_STATE_CHANGE, deviceContext)); 638d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 639d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 640d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void requestServiceConnectionTimeout() { 641d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan sendEmptyMessageDelayed(MSG_SERVICE_CONNECTION_TIMEOUT, CONNECT_TIMEOUT_MS); 642d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 643d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 644d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void requestCompleteDeviceDispatch() { 645d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan sendEmptyMessage(MSG_COMPLETE_DISPATCH); 646d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 647d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan 648d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan @Override 649d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan public void handleMessage(Message msg) { 650d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan switch (msg.what) { 651d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan case MSG_RESOLVE_HANDLERS: 652d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan doHandleResolveHandlers((UsbDevice) msg.obj); 653d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan break; 654d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan case MSG_SERVICE_CONNECTION_STATE_CHANGE: 655d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan removeMessages(MSG_SERVICE_CONNECTION_TIMEOUT); 656d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan doHandleServiceConnectionStateChanged((DeviceContext) msg.obj); 657d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan break; 658d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan case MSG_SERVICE_CONNECTION_TIMEOUT: 659d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.i(TAG, "Service connection timeout"); 660d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan doHandleServiceConnectionStateChanged(null); 661d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan break; 662d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan case MSG_COMPLETE_DISPATCH: 663d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan mDeviceCallback.onDeviceDispatched(); 664d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan break; 665d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan default: 666d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan Log.w(TAG, "Unsupported message: " + msg); 667d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 668d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 669d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan } 670d428549b58b2df5015bff81d79747265ee8be536Kevin Crossan} 671