1badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park/* 2badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * Copyright (C) 2016 The Android Open Source Project 3badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * 4badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * Licensed under the Apache License, Version 2.0 (the "License"); 5badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * you may not use this file except in compliance with the License. 6badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * You may obtain a copy of the License at 7badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * 8badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * http://www.apache.org/licenses/LICENSE-2.0 9badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * 10badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * Unless required by applicable law or agreed to in writing, software 11badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * distributed under the License is distributed on an "AS IS" BASIS, 12badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * See the License for the specific language governing permissions and 14badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park * limitations under the License. 15badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park */ 16badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkpackage com.android.hardware.usb.externalmanagementtest; 17badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 18badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.content.BroadcastReceiver; 19badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.content.Context; 20badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.content.Intent; 21badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.content.IntentFilter; 22badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.hardware.usb.UsbDevice; 23badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.hardware.usb.UsbDeviceConnection; 24badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.hardware.usb.UsbManager; 25badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.os.Handler; 26badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.os.HandlerThread; 27badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.os.Looper; 28badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.os.Message; 29badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport android.util.Log; 30badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 31badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport java.util.LinkedList; 32badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 33badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkimport dalvik.system.CloseGuard; 34badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 35badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Parkpublic class UsbDeviceStateController { 36badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 37badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public interface UsbDeviceStateListener { 38badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park void onDeviceResetComplete(UsbDevice device); 39badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park void onAoapStartComplete(UsbDevice devie); 40badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 41badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 42badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private static final String TAG = UsbDeviceStateController.class.getSimpleName(); 43badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 44badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private static final int MAX_USB_STATE_CHANGE_WAIT = 5; 45badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private static final long USB_STATE_CHANGE_WAIT_TIMEOUT_MS = 500; 46badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 47badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final Context mContext; 48badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final UsbDeviceStateListener mListener; 49badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final UsbManager mUsbManager; 50badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final HandlerThread mHandlerThread; 51badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final UsbStateHandler mHandler; 52badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final UsbDeviceBroadcastReceiver mUsbStateBroadcastReceiver; 53badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final CloseGuard mCloseGuard = CloseGuard.get(); 54badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 55badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final Object mUsbConnectionChangeWait = new Object(); 56badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final LinkedList<UsbDevice> mDevicesRemoved = new LinkedList<>(); 57badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final LinkedList<UsbDevice> mDevicesAdded = new LinkedList<>(); 58badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private boolean mShouldQuit = false; 59badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 60badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public UsbDeviceStateController(Context context, UsbDeviceStateListener listener, 61badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbManager usbManager) { 62badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mContext = context; 63badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mListener = listener; 64badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbManager = usbManager; 65badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mHandlerThread = new HandlerThread(TAG); 66badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mHandlerThread.start(); 67badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mCloseGuard.open("release"); 68badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mHandler = new UsbStateHandler(mHandlerThread.getLooper()); 69badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbStateBroadcastReceiver = new UsbDeviceBroadcastReceiver(); 70badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 71badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 72badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public void init() { 73badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park IntentFilter filter = new IntentFilter(); 74badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); 75badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); 76badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mContext.registerReceiver(mUsbStateBroadcastReceiver, filter); 77badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 78badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 79badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public void release() { 80badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mCloseGuard.close(); 81badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mContext.unregisterReceiver(mUsbStateBroadcastReceiver); 82badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park synchronized (mUsbConnectionChangeWait) { 83badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mShouldQuit = true; 84badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbConnectionChangeWait.notifyAll(); 85badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 86badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mHandlerThread.quit(); 87badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 88badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 89badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park @Override 90badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park protected void finalize() throws Throwable { 91badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park try { 92492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath if (mCloseGuard != null) { 93492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath mCloseGuard.warnIfOpen(); 94492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath } 95492e9e851cadca62df84eaff1a3c1ba788492fbaNarayan Kamath 96badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park release(); 97badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } finally { 98badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park super.finalize(); 99badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 100badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 101badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 102badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public void startDeviceReset(UsbDevice device) { 103badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mHandler.requestDeviceReset(device); 104badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 105badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 106badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public void startAoap(AoapSwitchRequest request) { 107badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mHandler.requestAoap(request); 108badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 109badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 110badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private void doHandleDeviceReset(UsbDevice device) { 111badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park boolean isInAoap = AoapInterface.isDeviceInAoapMode(device); 112badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDevice completedDevice = null; 113badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (isInAoap) { 114badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park completedDevice = resetUsbDeviceAndConfirmModeChange(device); 115badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } else { 116badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDeviceConnection conn = openConnection(device); 117badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (conn == null) { 118badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park throw new RuntimeException("cannot open conneciton for device: " + device); 119badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } else { 120badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park try { 121badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (!conn.resetDevice()) { 122badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park throw new RuntimeException("resetDevice failed for devie: " + device); 123badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } else { 124badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park completedDevice = device; 125badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 126badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } finally { 127badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park conn.close(); 128badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 129badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 130badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 131badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mListener.onDeviceResetComplete(completedDevice); 132badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 133badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 134badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private void doHandleAoapStart(AoapSwitchRequest request) { 135badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDevice device = request.device; 136badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park boolean isInAoap = AoapInterface.isDeviceInAoapMode(device); 137badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (isInAoap) { 138badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park device = resetUsbDeviceAndConfirmModeChange(device); 139badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (device == null) { 140badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mListener.onAoapStartComplete(null); 141badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return; 142badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 143badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 144badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDeviceConnection connection = openConnection(device); 145badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_MANUFACTURER, 146badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park request.manufacturer); 147badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_MODEL, 148badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park request.model); 149badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_DESCRIPTION, 150badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park request.description); 151badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_VERSION, 152badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park request.version); 153badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_URI, request.uri); 154badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_SERIAL, request.serial); 155badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park AoapInterface.sendAoapStart(connection); 156badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park device = resetUsbDeviceAndConfirmModeChange(device); 157badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (device == null) { 158badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mListener.onAoapStartComplete(null); 159badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 160badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (!AoapInterface.isDeviceInAoapMode(device)) { 161badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park Log.w(TAG, "Device not in AOAP mode after switching: " + device); 162badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mListener.onAoapStartComplete(device); 163badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 164badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mListener.onAoapStartComplete(device); 165badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 166badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 167badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private UsbDevice resetUsbDeviceAndConfirmModeChange(UsbDevice device) { 168badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park int retry = 0; 169badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park boolean removalDetected = false; 170badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park while (retry < MAX_USB_STATE_CHANGE_WAIT) { 171badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDeviceConnection connNow = openConnection(device); 172badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (connNow == null) { 173badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park removalDetected = true; 174badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park break; 175badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 176badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park connNow.resetDevice(); 177badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park connNow.close(); 178badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park synchronized (mUsbConnectionChangeWait) { 179badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park try { 180badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbConnectionChangeWait.wait(USB_STATE_CHANGE_WAIT_TIMEOUT_MS); 181badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } catch (InterruptedException e) { 182badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park break; 183badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 184badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (mShouldQuit) { 185badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return null; 186badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 187badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (isDeviceRemovedLocked(device)) { 188badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park removalDetected = true; 189badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park break; 190badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 191badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 192badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park retry++; 193badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 194badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (!removalDetected) { 195badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park Log.w(TAG, "resetDevice failed for device, device still in the same mode: " + device); 196badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return null; 197badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 198badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park retry = 0; 199badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDevice newlyAttached = null; 200badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park while (retry < MAX_USB_STATE_CHANGE_WAIT) { 201badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park synchronized (mUsbConnectionChangeWait) { 202badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park try { 203badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbConnectionChangeWait.wait(USB_STATE_CHANGE_WAIT_TIMEOUT_MS); 204badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } catch (InterruptedException e) { 205badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park break; 206badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 207badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (mShouldQuit) { 208badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return null; 209badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 210badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park newlyAttached = checkDeviceAttachedLocked(device); 211badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 212badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (newlyAttached != null) { 213badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park break; 214badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 215badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park retry++; 216badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 217badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (newlyAttached == null) { 218badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park Log.w(TAG, "resetDevice failed for device, device disconnected: " + device); 219badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return null; 220badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 221badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return newlyAttached; 222badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 223badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 224badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private boolean isDeviceRemovedLocked(UsbDevice device) { 225badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park for (UsbDevice removed : mDevicesRemoved) { 226badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (UsbUtil.isDevicesMatching(device, removed)) { 227badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mDevicesRemoved.clear(); 228badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return true; 229badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 230badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 231badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mDevicesRemoved.clear(); 232badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return false; 233badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 234badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 235badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private UsbDevice checkDeviceAttachedLocked(UsbDevice device) { 236badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park for (UsbDevice attached : mDevicesAdded) { 237badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (UsbUtil.isTheSameDevice(device, attached)) { 238badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mDevicesAdded.clear(); 239badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return attached; 240badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 241badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 242badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mDevicesAdded.clear(); 243badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return null; 244badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 245badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 246badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public UsbDeviceConnection openConnection(UsbDevice device) { 247badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbManager.grantPermission(device); 248badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park return mUsbManager.openDevice(device); 249badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 250badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 251badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private void handleUsbDeviceAttached(UsbDevice device) { 252badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park synchronized (mUsbConnectionChangeWait) { 253badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mDevicesAdded.add(device); 254badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbConnectionChangeWait.notifyAll(); 255badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 256badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 257badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 258badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private void handleUsbDeviceDetached(UsbDevice device) { 259badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park synchronized (mUsbConnectionChangeWait) { 260badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mDevicesRemoved.add(device); 261badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park mUsbConnectionChangeWait.notifyAll(); 262badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 263badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 264badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 265badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private class UsbStateHandler extends Handler { 266badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final int MSG_RESET_DEVICE = 1; 267badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private final int MSG_AOAP = 2; 268badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 269badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private UsbStateHandler(Looper looper) { 270badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park super(looper); 271badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 272badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 273badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private void requestDeviceReset(UsbDevice device) { 274badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park Message msg = obtainMessage(MSG_RESET_DEVICE, device); 275badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park sendMessage(msg); 276badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 277badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 278badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private void requestAoap(AoapSwitchRequest request) { 279badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park Message msg = obtainMessage(MSG_AOAP, request); 280badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park sendMessage(msg); 281badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 282badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 283badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park @Override 284badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public void handleMessage(Message msg) { 285badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park switch (msg.what) { 286badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park case MSG_RESET_DEVICE: 287badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park doHandleDeviceReset((UsbDevice) msg.obj); 288badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park break; 289badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park case MSG_AOAP: 290badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park doHandleAoapStart((AoapSwitchRequest) msg.obj); 291badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park break; 292badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 293badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 294badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 295badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 296badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park private class UsbDeviceBroadcastReceiver extends BroadcastReceiver { 297badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park @Override 298badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public void onReceive(Context context, Intent intent) { 299badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) { 300badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDevice device = intent.<UsbDevice>getParcelableExtra(UsbManager.EXTRA_DEVICE); 301badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park handleUsbDeviceDetached(device); 302badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { 303badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park UsbDevice device = intent.<UsbDevice>getParcelableExtra(UsbManager.EXTRA_DEVICE); 304badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park handleUsbDeviceAttached(device); 305badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 306badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 307badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 308badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 309badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public static class AoapSwitchRequest { 310badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public final UsbDevice device; 311badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public final String manufacturer; 312badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public final String model; 313badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public final String description; 314badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public final String version; 315badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public final String uri; 316badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public final String serial; 317badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park 318badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park public AoapSwitchRequest(UsbDevice device, String manufacturer, String model, 319badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park String description, String version, String uri, String serial) { 320badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park this.device = device; 321badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park this.manufacturer = manufacturer; 322badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park this.model = model; 323badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park this.description = description; 324badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park this.version = version; 325badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park this.uri = uri; 326badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park this.serial = serial; 327badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 328badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park } 329badbbae6fa2846415778b2a152a0758acbf0eb74Keun-young Park} 330