upload android base code part1

This commit is contained in:
August 2018-08-08 15:50:00 +08:00
parent e02f198e2d
commit 0a1de6c4b3
48159 changed files with 9071466 additions and 0 deletions

View file

@ -0,0 +1,35 @@
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
LOCAL_PATH:= $(call my-dir)
##################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AoapTestDeviceApp
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.hardware.usb.aoapdevicetest" >
<application android:label="UsbAoapDeviceTestApp" >
<activity android:name=".UsbAoapDeviceTestActivity"
android:configChanges="keyboard|keyboardHidden" >
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter"/>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
</LinearLayout>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<usb-accessory model="AOAP Test App" manufacturer="Android"/>
</resources>

View file

@ -0,0 +1,183 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.hardware.usb.aoapdevicetest;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import libcore.io.IoUtils;
public class UsbAoapDeviceTestActivity extends Activity {
private static final String TAG = UsbAoapDeviceTestActivity.class.getSimpleName();
private static final boolean DBG = true;
private static final String ACTION_USB_ACCESSORY_PERMISSION =
"com.android.hardware.usb.aoapdevicetest.ACTION_USB_ACCESSORY_PERMISSION";
private UsbManager mUsbManager;
private AccessoryReceiver mReceiver;
private ParcelFileDescriptor mFd;
private ReaderThread mReaderThread;
private UsbAccessory mAccessory;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.device);
mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
filter.addAction(ACTION_USB_ACCESSORY_PERMISSION);
mReceiver = new AccessoryReceiver();
registerReceiver(mReceiver, filter);
Intent intent = getIntent();
if (intent.getAction().equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
UsbAccessory accessory =
(UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null) {
onAccessoryAttached(accessory);
} else {
throw new RuntimeException("USB accessory is null.");
}
} else {
finish();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
IoUtils.closeQuietly(mFd);
if (mReaderThread != null) {
mReaderThread.requestToQuit();
try {
mReaderThread.join(1000);
} catch (InterruptedException e) {
}
if (mReaderThread.isAlive()) { // reader thread stuck
Log.w(TAG, "ReaderThread still alive");
}
}
}
private void onAccessoryAttached(UsbAccessory accessory) {
Log.i(TAG, "Starting AOAP discovery protocol, accessory attached: " + accessory);
// Check whether we have permission to access the accessory.
if (!mUsbManager.hasPermission(accessory)) {
Log.i(TAG, "Prompting the user for access to the accessory.");
Intent intent = new Intent(ACTION_USB_ACCESSORY_PERMISSION);
intent.setPackage(getPackageName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
mUsbManager.requestPermission(accessory, pendingIntent);
return;
}
mFd = mUsbManager.openAccessory(accessory);
if (mFd == null) {
Log.e(TAG, "UsbManager.openAccessory returned null");
finish();
return;
}
mAccessory = accessory;
mReaderThread = new ReaderThread(mFd);
mReaderThread.start();
}
private void onAccessoryDetached(UsbAccessory accessory) {
Log.i(TAG, "Accessory detached: " + accessory);
finish();
}
private class ReaderThread extends Thread {
private boolean mShouldQuit = false;
private final FileInputStream mInputStream;
private final FileOutputStream mOutputStream;
private final byte[] mBuffer = new byte[16384];
private ReaderThread(ParcelFileDescriptor fd) {
super("AOAP");
mInputStream = new FileInputStream(fd.getFileDescriptor());
mOutputStream = new FileOutputStream(fd.getFileDescriptor());
}
private synchronized void requestToQuit() {
mShouldQuit = true;
}
private synchronized boolean shouldQuit() {
return mShouldQuit;
}
@Override
public void run() {
while (!shouldQuit()) {
try {
int read = mInputStream.read(mBuffer);
} catch (IOException e) {
Log.i(TAG, "ReaderThread IOException", e);
// AOAP App should release FD when IOException happens.
// If FD is kept, device will not behave nicely on reset and multiple reset
// can be required.
finish();
return;
}
}
}
}
private class AccessoryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null) {
String action = intent.getAction();
if (action.equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
onAccessoryAttached(accessory);
} else if (action.equals(UsbManager.ACTION_USB_ACCESSORY_DETACHED)) {
if (mAccessory != null && mAccessory.equals(accessory)) {
onAccessoryDetached(accessory);
}
} else if (action.equals(ACTION_USB_ACCESSORY_PERMISSION)) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
Log.i(TAG, "Accessory permission granted: " + accessory);
onAccessoryAttached(accessory);
} else {
Log.e(TAG, "Accessory permission denied: " + accessory);
finish();
}
}
}
}
}
}

View file

@ -0,0 +1,35 @@
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
LOCAL_PATH:= $(call my-dir)
##################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AoapTestHostApp
LOCAL_MODULE_TAGS := tests
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.hardware.usb.aoaphosttest" >
<application android:label="UsbAoapHostTestApp" >
<activity android:name=".UsbAoapHostTestActivity"
android:configChanges="keyboard|keyboardHidden" >
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/usb_device_filter"/>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
</LinearLayout>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Android USB accessory: accessory -->
<usb-device vendor-id="16601" product-id="11520" />
<!-- Android USB accessory: accessory + adb -->
<usb-device vendor-id="16601" product-id="11521" />
<!-- not suppoted by UsbService, but external host management can use this. -->
<usb-aoap-device model="AOAP Test App" manufacturer="Android" version="1.0" />
</resources>

View file

@ -0,0 +1,165 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.hardware.usb.aoaphosttest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import libcore.io.IoUtils;
public class UsbAoapHostTestActivity extends Activity {
private static final String TAG = UsbAoapHostTestActivity.class.getSimpleName();
private UsbManager mUsbManager;
private UsbStateReceiver mReceiver;
private UsbDevice mUsbDevice;
private UsbDeviceConnection mUsbConnection;
private ReaderThread mReaderThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.host);
mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
mReceiver = new UsbStateReceiver();
registerReceiver(mReceiver, filter);
Intent intent = getIntent();
if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
mUsbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
mUsbConnection = mUsbManager.openDevice(mUsbDevice);
mReaderThread = new ReaderThread(mUsbDevice, mUsbConnection);
mReaderThread.start();
} else {
finish();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mReceiver);
if (mUsbConnection != null) {
mUsbConnection.close();
}
if (mReaderThread != null) {
mReaderThread.requestToQuit();
try {
mReaderThread.join(1000);
} catch (InterruptedException e) {
}
if (mReaderThread.isAlive()) { // reader thread stuck
throw new RuntimeException("ReaderThread still alive");
}
}
}
private static boolean isDevicesMatching(UsbDevice l, UsbDevice r) {
if (l.getVendorId() == r.getVendorId() && l.getProductId() == r.getProductId() &&
TextUtils.equals(l.getSerialNumber(), r.getSerialNumber())) {
return true;
}
return false;
}
private class ReaderThread extends Thread {
private boolean mShouldQuit = false;
private final UsbDevice mDevice;
private final UsbDeviceConnection mUsbConnection;
private final UsbEndpoint mBulkIn;
private final UsbEndpoint mBulkOut;
private final byte[] mBuffer = new byte[16384];
private ReaderThread(UsbDevice device, UsbDeviceConnection conn) {
super("AOAP");
mDevice = device;
mUsbConnection = conn;
UsbInterface iface = mDevice.getInterface(0);
// Setup bulk endpoints.
UsbEndpoint bulkIn = null;
UsbEndpoint bulkOut = null;
for (int i = 0; i < iface.getEndpointCount(); i++) {
UsbEndpoint ep = iface.getEndpoint(i);
if (ep.getDirection() == UsbConstants.USB_DIR_IN) {
if (bulkIn == null) {
bulkIn = ep;
}
} else {
if (bulkOut == null) {
bulkOut = ep;
}
}
}
if (bulkIn == null || bulkOut == null) {
throw new IllegalStateException("Unable to find bulk endpoints");
}
mBulkIn = bulkIn;
mBulkOut = bulkOut;
}
private synchronized void requestToQuit() {
mShouldQuit = true;
}
private synchronized boolean shouldQuit() {
return mShouldQuit;
}
@Override
public void run() {
while (!shouldQuit()) {
int read = mUsbConnection.bulkTransfer(mBulkIn, mBuffer, mBuffer.length,
Integer.MAX_VALUE);
if (read < 0) {
throw new RuntimeException("bulkTransfer failed, read = " + read);
}
}
}
}
private class UsbStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
if (isDevicesMatching(mUsbDevice, device)) {
finish();
}
}
}
}
}

View file

@ -0,0 +1,37 @@
# Copyright (C) 2016 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
LOCAL_PATH:= $(call my-dir)
##################################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := UsbHostExternalManagementTestApp
LOCAL_PRIVILEGED_MODULE := true
# TODO remove tests tag
#LOCAL_MODULE_TAGS := tests
#LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_PROGUARD_ENABLED := disabled
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.hardware.usb.externalmanagementtest" >
<uses-permission android:name="android.permission.MANAGE_USB" />
<application android:label="UsbHostExternalManagementTestApp" >
<activity android:name=".UsbHostManagementActivity"
android:configChanges="keyboard|keyboardHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
</activity>
</application>
</manifest>

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView android:id="@+id/device_info_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/current_device"
/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<Button android:id="@+id/start_aoap_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/start_aoap"
/>
<Button android:id="@+id/start_aoap_activity_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/start_aoap_activity"
/>
<Button android:id="@+id/reset_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/usb_reset"
/>
<Button android:id="@+id/finish_button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/finish_app"
/>
</LinearLayout>
<TextView android:id="@+id/aoap_apps_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/aoap_app_msg"
/>
</LinearLayout>

View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2016 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string name="app_title">UsbHostExternalManagementTestApp</string>
<string name="current_device">No device</string>
<string name="aoap_app_msg">AOAP App message</string>
<string name="usb_reset">Reset USB</string>
<string name="start_aoap">Start Test AOAP</string>
<string name="start_aoap_activity">Start Test AOAP Activity</string>
<string name="finish_app">Finish</string>
</resources>

View file

@ -0,0 +1,135 @@
/**
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.hardware.usb.externalmanagementtest;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.util.Log;
public class AoapInterface {
/**
* Use Google Vendor ID when in accessory mode
*/
public static final int USB_ACCESSORY_VENDOR_ID = 0x18D1;
/**
* Product ID to use when in accessory mode
*/
public static final int USB_ACCESSORY_PRODUCT_ID = 0x2D00;
/**
* Product ID to use when in accessory mode and adb is enabled
*/
public static final int USB_ACCESSORY_ADB_PRODUCT_ID = 0x2D01;
/**
* Indexes for strings sent by the host via ACCESSORY_SEND_STRING
*/
public static final int ACCESSORY_STRING_MANUFACTURER = 0;
public static final int ACCESSORY_STRING_MODEL = 1;
public static final int ACCESSORY_STRING_DESCRIPTION = 2;
public static final int ACCESSORY_STRING_VERSION = 3;
public static final int ACCESSORY_STRING_URI = 4;
public static final int ACCESSORY_STRING_SERIAL = 5;
/**
* Control request for retrieving device's protocol version
*
* requestType: USB_DIR_IN | USB_TYPE_VENDOR
* request: ACCESSORY_GET_PROTOCOL
* value: 0
* index: 0
* data version number (16 bits little endian)
* 1 for original accessory support
* 2 adds HID and device to host audio support
*/
public static final int ACCESSORY_GET_PROTOCOL = 51;
/**
* Control request for host to send a string to the device
*
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
* request: ACCESSORY_SEND_STRING
* value: 0
* index: string ID
* data zero terminated UTF8 string
*
* The device can later retrieve these strings via the
* ACCESSORY_GET_STRING_* ioctls
*/
public static final int ACCESSORY_SEND_STRING = 52;
/**
* Control request for starting device in accessory mode.
* The host sends this after setting all its strings to the device.
*
* requestType: USB_DIR_OUT | USB_TYPE_VENDOR
* request: ACCESSORY_START
* value: 0
* index: 0
* data none
*/
public static final int ACCESSORY_START = 53;
/**
* Max payload size for AOAP. Limited by driver.
*/
public static final int MAX_PAYLOAD_SIZE = 16384;
private static final String TAG = AoapInterface.class.getSimpleName();
public static int getProtocol(UsbDeviceConnection conn) {
byte buffer[] = new byte[2];
int len = conn.controlTransfer(
UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_VENDOR,
AoapInterface.ACCESSORY_GET_PROTOCOL, 0, 0, buffer, 2, 10000);
if (len != 2) {
return -1;
}
return (buffer[1] << 8) | buffer[0];
}
public static void sendString(UsbDeviceConnection conn, int index, String string) {
byte[] buffer = (string + "\0").getBytes();
int len = conn.controlTransfer(
UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR,
AoapInterface.ACCESSORY_SEND_STRING, 0, index,
buffer, buffer.length, 10000);
if (len != buffer.length) {
throw new RuntimeException("Failed to send string " + index + ": \"" + string + "\"");
} else {
Log.i(TAG, "Sent string " + index + ": \"" + string + "\"");
}
}
public static void sendAoapStart(UsbDeviceConnection conn) {
int len = conn.controlTransfer(
UsbConstants.USB_DIR_OUT | UsbConstants.USB_TYPE_VENDOR,
AoapInterface.ACCESSORY_START, 0, 0, null, 0, 10000);
if (len < 0) {
throw new RuntimeException("control transfer for accessory start failed:" + len);
}
}
public static boolean isDeviceInAoapMode(UsbDevice device) {
final int vid = device.getVendorId();
final int pid = device.getProductId();
return vid == USB_ACCESSORY_VENDOR_ID
&& (pid == USB_ACCESSORY_PRODUCT_ID
|| pid == USB_ACCESSORY_ADB_PRODUCT_ID);
}
}

View file

@ -0,0 +1,329 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.hardware.usb.externalmanagementtest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import java.util.LinkedList;
import dalvik.system.CloseGuard;
public class UsbDeviceStateController {
public interface UsbDeviceStateListener {
void onDeviceResetComplete(UsbDevice device);
void onAoapStartComplete(UsbDevice devie);
}
private static final String TAG = UsbDeviceStateController.class.getSimpleName();
private static final int MAX_USB_STATE_CHANGE_WAIT = 5;
private static final long USB_STATE_CHANGE_WAIT_TIMEOUT_MS = 500;
private final Context mContext;
private final UsbDeviceStateListener mListener;
private final UsbManager mUsbManager;
private final HandlerThread mHandlerThread;
private final UsbStateHandler mHandler;
private final UsbDeviceBroadcastReceiver mUsbStateBroadcastReceiver;
private final CloseGuard mCloseGuard = CloseGuard.get();
private final Object mUsbConnectionChangeWait = new Object();
private final LinkedList<UsbDevice> mDevicesRemoved = new LinkedList<>();
private final LinkedList<UsbDevice> mDevicesAdded = new LinkedList<>();
private boolean mShouldQuit = false;
public UsbDeviceStateController(Context context, UsbDeviceStateListener listener,
UsbManager usbManager) {
mContext = context;
mListener = listener;
mUsbManager = usbManager;
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
mCloseGuard.open("release");
mHandler = new UsbStateHandler(mHandlerThread.getLooper());
mUsbStateBroadcastReceiver = new UsbDeviceBroadcastReceiver();
}
public void init() {
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
mContext.registerReceiver(mUsbStateBroadcastReceiver, filter);
}
public void release() {
mCloseGuard.close();
mContext.unregisterReceiver(mUsbStateBroadcastReceiver);
synchronized (mUsbConnectionChangeWait) {
mShouldQuit = true;
mUsbConnectionChangeWait.notifyAll();
}
mHandlerThread.quit();
}
@Override
protected void finalize() throws Throwable {
try {
if (mCloseGuard != null) {
mCloseGuard.warnIfOpen();
}
release();
} finally {
super.finalize();
}
}
public void startDeviceReset(UsbDevice device) {
mHandler.requestDeviceReset(device);
}
public void startAoap(AoapSwitchRequest request) {
mHandler.requestAoap(request);
}
private void doHandleDeviceReset(UsbDevice device) {
boolean isInAoap = AoapInterface.isDeviceInAoapMode(device);
UsbDevice completedDevice = null;
if (isInAoap) {
completedDevice = resetUsbDeviceAndConfirmModeChange(device);
} else {
UsbDeviceConnection conn = openConnection(device);
if (conn == null) {
throw new RuntimeException("cannot open conneciton for device: " + device);
} else {
try {
if (!conn.resetDevice()) {
throw new RuntimeException("resetDevice failed for devie: " + device);
} else {
completedDevice = device;
}
} finally {
conn.close();
}
}
}
mListener.onDeviceResetComplete(completedDevice);
}
private void doHandleAoapStart(AoapSwitchRequest request) {
UsbDevice device = request.device;
boolean isInAoap = AoapInterface.isDeviceInAoapMode(device);
if (isInAoap) {
device = resetUsbDeviceAndConfirmModeChange(device);
if (device == null) {
mListener.onAoapStartComplete(null);
return;
}
}
UsbDeviceConnection connection = openConnection(device);
AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_MANUFACTURER,
request.manufacturer);
AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_MODEL,
request.model);
AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_DESCRIPTION,
request.description);
AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_VERSION,
request.version);
AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_URI, request.uri);
AoapInterface.sendString(connection, AoapInterface.ACCESSORY_STRING_SERIAL, request.serial);
AoapInterface.sendAoapStart(connection);
device = resetUsbDeviceAndConfirmModeChange(device);
if (device == null) {
mListener.onAoapStartComplete(null);
}
if (!AoapInterface.isDeviceInAoapMode(device)) {
Log.w(TAG, "Device not in AOAP mode after switching: " + device);
mListener.onAoapStartComplete(device);
}
mListener.onAoapStartComplete(device);
}
private UsbDevice resetUsbDeviceAndConfirmModeChange(UsbDevice device) {
int retry = 0;
boolean removalDetected = false;
while (retry < MAX_USB_STATE_CHANGE_WAIT) {
UsbDeviceConnection connNow = openConnection(device);
if (connNow == null) {
removalDetected = true;
break;
}
connNow.resetDevice();
connNow.close();
synchronized (mUsbConnectionChangeWait) {
try {
mUsbConnectionChangeWait.wait(USB_STATE_CHANGE_WAIT_TIMEOUT_MS);
} catch (InterruptedException e) {
break;
}
if (mShouldQuit) {
return null;
}
if (isDeviceRemovedLocked(device)) {
removalDetected = true;
break;
}
}
retry++;
}
if (!removalDetected) {
Log.w(TAG, "resetDevice failed for device, device still in the same mode: " + device);
return null;
}
retry = 0;
UsbDevice newlyAttached = null;
while (retry < MAX_USB_STATE_CHANGE_WAIT) {
synchronized (mUsbConnectionChangeWait) {
try {
mUsbConnectionChangeWait.wait(USB_STATE_CHANGE_WAIT_TIMEOUT_MS);
} catch (InterruptedException e) {
break;
}
if (mShouldQuit) {
return null;
}
newlyAttached = checkDeviceAttachedLocked(device);
}
if (newlyAttached != null) {
break;
}
retry++;
}
if (newlyAttached == null) {
Log.w(TAG, "resetDevice failed for device, device disconnected: " + device);
return null;
}
return newlyAttached;
}
private boolean isDeviceRemovedLocked(UsbDevice device) {
for (UsbDevice removed : mDevicesRemoved) {
if (UsbUtil.isDevicesMatching(device, removed)) {
mDevicesRemoved.clear();
return true;
}
}
mDevicesRemoved.clear();
return false;
}
private UsbDevice checkDeviceAttachedLocked(UsbDevice device) {
for (UsbDevice attached : mDevicesAdded) {
if (UsbUtil.isTheSameDevice(device, attached)) {
mDevicesAdded.clear();
return attached;
}
}
mDevicesAdded.clear();
return null;
}
public UsbDeviceConnection openConnection(UsbDevice device) {
mUsbManager.grantPermission(device);
return mUsbManager.openDevice(device);
}
private void handleUsbDeviceAttached(UsbDevice device) {
synchronized (mUsbConnectionChangeWait) {
mDevicesAdded.add(device);
mUsbConnectionChangeWait.notifyAll();
}
}
private void handleUsbDeviceDetached(UsbDevice device) {
synchronized (mUsbConnectionChangeWait) {
mDevicesRemoved.add(device);
mUsbConnectionChangeWait.notifyAll();
}
}
private class UsbStateHandler extends Handler {
private final int MSG_RESET_DEVICE = 1;
private final int MSG_AOAP = 2;
private UsbStateHandler(Looper looper) {
super(looper);
}
private void requestDeviceReset(UsbDevice device) {
Message msg = obtainMessage(MSG_RESET_DEVICE, device);
sendMessage(msg);
}
private void requestAoap(AoapSwitchRequest request) {
Message msg = obtainMessage(MSG_AOAP, request);
sendMessage(msg);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_RESET_DEVICE:
doHandleDeviceReset((UsbDevice) msg.obj);
break;
case MSG_AOAP:
doHandleAoapStart((AoapSwitchRequest) msg.obj);
break;
}
}
}
private class UsbDeviceBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
UsbDevice device = intent.<UsbDevice>getParcelableExtra(UsbManager.EXTRA_DEVICE);
handleUsbDeviceDetached(device);
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
UsbDevice device = intent.<UsbDevice>getParcelableExtra(UsbManager.EXTRA_DEVICE);
handleUsbDeviceAttached(device);
}
}
}
public static class AoapSwitchRequest {
public final UsbDevice device;
public final String manufacturer;
public final String model;
public final String description;
public final String version;
public final String uri;
public final String serial;
public AoapSwitchRequest(UsbDevice device, String manufacturer, String model,
String description, String version, String uri, String serial) {
this.device = device;
this.manufacturer = manufacturer;
this.model = model;
this.description = description;
this.version = version;
this.uri = uri;
this.serial = serial;
}
}
}

View file

@ -0,0 +1,246 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.hardware.usb.externalmanagementtest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.net.nsd.NsdManager.DiscoveryListener;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import com.android.hardware.usb.externalmanagementtest.UsbDeviceStateController.AoapSwitchRequest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
public class UsbHostManagementActivity extends Activity
implements UsbDeviceStateController.UsbDeviceStateListener {
private static final String TAG = UsbHostManagementActivity.class.getSimpleName();
private static final String AOAP_APP_PACKAGE_NAME = "com.android.hardware.usb.aoaphosttest";
private static final String AOAP_APP_ACTIVITY_NAME =
"com.android.hardware.usb.aoaphosttest.UsbAoapHostTestActivity";
private TextView mDeviceInfoText;
private Button mStartAoapButton;
private Button mStartAoapActivityButton;
private TextView mAoapAppLog;
private Button mResetUsbButton;
private Button mFinishButton;
private UsbDevice mUsbDevice = null;
private final UsbDeviceConnectionListener mConnectionListener =
new UsbDeviceConnectionListener();
private UsbDeviceStateController mUsbDeviceStateController;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.host_management);
mDeviceInfoText = findViewById(R.id.device_info_text);
mStartAoapButton = findViewById(R.id.start_aoap_button);
mStartAoapActivityButton = findViewById(R.id.start_aoap_activity_button);
mAoapAppLog = findViewById(R.id.aoap_apps_text);
mResetUsbButton = findViewById(R.id.reset_button);
mFinishButton = findViewById(R.id.finish_button);
Intent intent = getIntent();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
mUsbDevice = intent.<UsbDevice>getParcelableExtra(UsbManager.EXTRA_DEVICE);
}
UsbManager usbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
if (mUsbDevice == null) {
LinkedList<UsbDevice> devices = UsbUtil.findAllPossibleAndroidDevices(usbManager);
if (devices.size() > 0) {
mUsbDevice = devices.getLast();
}
}
updateDevice(mUsbDevice);
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(mConnectionListener, filter);
mStartAoapButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mUsbDevice == null) {
return;
}
startAoap(mUsbDevice);
}
});
mStartAoapActivityButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mUsbDevice == null) {
return;
}
startAoapActivity(mUsbDevice);
}
});
mResetUsbButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mUsbDevice == null) {
return;
}
resetDevice(mUsbDevice);
}
});
mFinishButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
mUsbDeviceStateController = new UsbDeviceStateController(this, this, usbManager);
mUsbDeviceStateController.init();
}
private void startAoap(UsbDevice device) {
AoapSwitchRequest request = new AoapSwitchRequest(device, "Android", "AOAP Test App", "",
"1.0", "", "");
mUsbDeviceStateController.startAoap(request);
}
private void startAoapActivity(UsbDevice device) {
if (!AoapInterface.isDeviceInAoapMode(device)) {
Log.w(TAG, "Device not in AOAP mode:" + device);
return;
}
PackageManager pm = getPackageManager();
PackageInfo pi = null;
try {
pi = pm.getPackageInfo(AOAP_APP_PACKAGE_NAME, 0);
} catch (NameNotFoundException e) {
Log.w(TAG, "AOAP Test app not found:" + AOAP_APP_PACKAGE_NAME);
}
int uid = pi.applicationInfo.uid;
UsbManager usbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
usbManager.grantPermission(device, uid);
Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
intent.setComponent(new ComponentName(AOAP_APP_PACKAGE_NAME, AOAP_APP_ACTIVITY_NAME));
startActivity(intent);
}
private void resetDevice(UsbDevice device) {
Log.i(TAG, "resetDevice");
mUsbDeviceStateController.startDeviceReset(device);
}
private void dumpUsbDevices() {
UsbManager usbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> devices = usbManager.getDeviceList();
StringBuilder sb = new StringBuilder();
sb.append("Usb devices\n");
for (UsbDevice device : devices.values()) {
sb.append(device.toString() + "\n");
}
Log.i(TAG, sb.toString());
}
@Override
protected void onDestroy() {
Log.i(TAG, "onDestroy");
super.onDestroy();
unregisterReceiver(mConnectionListener);
mUsbDeviceStateController.release();
}
private void handleUsbDeviceAttached(UsbDevice device) {
boolean deviceReplaced = false;
if (mUsbDevice == null) {
deviceReplaced = true;
} else {
UsbManager usbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
if (!UsbUtil.isDeviceConnected(usbManager, mUsbDevice)) {
deviceReplaced = true;
}
}
if (deviceReplaced) {
Log.i(TAG, "device attached:" + device);
updateDevice(device);
}
}
private void handleUsbDeviceDetached(UsbDevice device) {
if (mUsbDevice != null && UsbUtil.isDevicesMatching(mUsbDevice, device)) {
Log.i(TAG, "device removed ");
updateDevice(device);
}
}
private void updateDevice(UsbDevice device) {
mUsbDevice = device;
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mUsbDevice == null) {
mDeviceInfoText.setText("disconnected");
} else {
mDeviceInfoText.setText(mUsbDevice.toString());
}
}
});
}
@Override
public void onDeviceResetComplete(UsbDevice device) {
updateDevice(device);
}
@Override
public void onAoapStartComplete(UsbDevice device) {
updateDevice(device);
}
private class UsbDeviceConnectionListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(intent.getAction())) {
UsbDevice device = intent.<UsbDevice>getParcelableExtra(UsbManager.EXTRA_DEVICE);
handleUsbDeviceDetached(device);
} else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) {
UsbDevice device = intent.<UsbDevice>getParcelableExtra(UsbManager.EXTRA_DEVICE);
handleUsbDeviceAttached(device);
}
}
}
}

View file

@ -0,0 +1,87 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.hardware.usb.externalmanagementtest;
import java.util.HashMap;
import java.util.LinkedList;
import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.text.TextUtils;
public class UsbUtil {
public static final String ADB_INTERFACE_NAME = "ADB Interface";
public static final String AOAP_INTERFACE_NAME = "Android Accessory Interface";
public static final String MTP_INTERFACE_NAME = "MTP";
public static LinkedList<UsbDevice> findAllPossibleAndroidDevices(UsbManager usbManager) {
HashMap<String, UsbDevice> devices = usbManager.getDeviceList();
LinkedList<UsbDevice> androidDevices = null;
for (UsbDevice device : devices.values()) {
if (possiblyAndroid(device)) {
if (androidDevices == null) {
androidDevices = new LinkedList<>();
}
androidDevices.add(device);
}
}
return androidDevices;
}
public static boolean possiblyAndroid(UsbDevice device) {
int numInterfaces = device.getInterfaceCount();
for (int i = 0; i < numInterfaces; i++) {
UsbInterface usbInterface = device.getInterface(i);
String interfaceName = usbInterface.getName();
// more thorough check can be added, later
if (AOAP_INTERFACE_NAME.equals(interfaceName) ||
ADB_INTERFACE_NAME.equals(interfaceName) ||
MTP_INTERFACE_NAME.equals(interfaceName)) {
return true;
}
}
return false;
}
public static boolean isTheSameDevice(UsbDevice l, UsbDevice r) {
if (TextUtils.equals(l.getManufacturerName(), r.getManufacturerName()) &&
TextUtils.equals(l.getProductName(), r.getProductName()) &&
TextUtils.equals(l.getSerialNumber(), r.getSerialNumber())) {
return true;
}
return false;
}
public static boolean isDevicesMatching(UsbDevice l, UsbDevice r) {
if (l.getVendorId() == r.getVendorId() && l.getProductId() == r.getProductId() &&
TextUtils.equals(l.getSerialNumber(), r.getSerialNumber())) {
return true;
}
return false;
}
public static boolean isDeviceConnected(UsbManager usbManager, UsbDevice device) {
HashMap<String, UsbDevice> devices = usbManager.getDeviceList();
for (UsbDevice dev : devices.values()) {
if (isDevicesMatching(dev, device)) {
return true;
}
}
return false;
}
}