Merge "Don't show "always use" when app can't be default"
This commit is contained in:
committed by
Android (Google) Code Review
commit
630fc40aad
145
core/java/android/hardware/usb/AccessoryFilter.java
Normal file
145
core/java/android/hardware/usb/AccessoryFilter.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2017 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 android.hardware.usb;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class is used to describe a USB accessory.
|
||||
* When used in HashMaps all values must be specified,
|
||||
* but wildcards can be used for any of the fields in
|
||||
* the package meta-data.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class AccessoryFilter {
|
||||
// USB accessory manufacturer (or null for unspecified)
|
||||
public final String mManufacturer;
|
||||
// USB accessory model (or null for unspecified)
|
||||
public final String mModel;
|
||||
// USB accessory version (or null for unspecified)
|
||||
public final String mVersion;
|
||||
|
||||
public AccessoryFilter(String manufacturer, String model, String version) {
|
||||
mManufacturer = manufacturer;
|
||||
mModel = model;
|
||||
mVersion = version;
|
||||
}
|
||||
|
||||
public AccessoryFilter(UsbAccessory accessory) {
|
||||
mManufacturer = accessory.getManufacturer();
|
||||
mModel = accessory.getModel();
|
||||
mVersion = accessory.getVersion();
|
||||
}
|
||||
|
||||
public static AccessoryFilter read(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
String manufacturer = null;
|
||||
String model = null;
|
||||
String version = null;
|
||||
|
||||
int count = parser.getAttributeCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String name = parser.getAttributeName(i);
|
||||
String value = parser.getAttributeValue(i);
|
||||
|
||||
if ("manufacturer".equals(name)) {
|
||||
manufacturer = value;
|
||||
} else if ("model".equals(name)) {
|
||||
model = value;
|
||||
} else if ("version".equals(name)) {
|
||||
version = value;
|
||||
}
|
||||
}
|
||||
return new AccessoryFilter(manufacturer, model, version);
|
||||
}
|
||||
|
||||
public void write(XmlSerializer serializer)throws IOException {
|
||||
serializer.startTag(null, "usb-accessory");
|
||||
if (mManufacturer != null) {
|
||||
serializer.attribute(null, "manufacturer", mManufacturer);
|
||||
}
|
||||
if (mModel != null) {
|
||||
serializer.attribute(null, "model", mModel);
|
||||
}
|
||||
if (mVersion != null) {
|
||||
serializer.attribute(null, "version", mVersion);
|
||||
}
|
||||
serializer.endTag(null, "usb-accessory");
|
||||
}
|
||||
|
||||
public boolean matches(UsbAccessory acc) {
|
||||
if (mManufacturer != null && !acc.getManufacturer().equals(mManufacturer)) return false;
|
||||
if (mModel != null && !acc.getModel().equals(mModel)) return false;
|
||||
return !(mVersion != null && !acc.getVersion().equals(mVersion));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the accessories described {@code accessory} covered by this filter?
|
||||
*
|
||||
* @param accessory A filter describing the accessory
|
||||
*
|
||||
* @return {@code true} iff this the filter covers the accessory
|
||||
*/
|
||||
public boolean contains(AccessoryFilter accessory) {
|
||||
if (mManufacturer != null && !Objects.equals(accessory.mManufacturer, mManufacturer)) {
|
||||
return false;
|
||||
}
|
||||
if (mModel != null && !Objects.equals(accessory.mModel, mModel)) return false;
|
||||
return !(mVersion != null && !Objects.equals(accessory.mVersion, mVersion));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// can't compare if we have wildcard strings
|
||||
if (mManufacturer == null || mModel == null || mVersion == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj instanceof AccessoryFilter) {
|
||||
AccessoryFilter filter = (AccessoryFilter)obj;
|
||||
return (mManufacturer.equals(filter.mManufacturer) &&
|
||||
mModel.equals(filter.mModel) &&
|
||||
mVersion.equals(filter.mVersion));
|
||||
}
|
||||
if (obj instanceof UsbAccessory) {
|
||||
UsbAccessory accessory = (UsbAccessory)obj;
|
||||
return (mManufacturer.equals(accessory.getManufacturer()) &&
|
||||
mModel.equals(accessory.getModel()) &&
|
||||
mVersion.equals(accessory.getVersion()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^
|
||||
(mModel == null ? 0 : mModel.hashCode()) ^
|
||||
(mVersion == null ? 0 : mVersion.hashCode()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccessoryFilter[mManufacturer=\"" + mManufacturer +
|
||||
"\", mModel=\"" + mModel +
|
||||
"\", mVersion=\"" + mVersion + "\"]";
|
||||
}
|
||||
}
|
||||
313
core/java/android/hardware/usb/DeviceFilter.java
Normal file
313
core/java/android/hardware/usb/DeviceFilter.java
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright 2017 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 android.hardware.usb;
|
||||
|
||||
import android.util.Slog;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class is used to describe a USB device.
|
||||
* When used in HashMaps all values must be specified,
|
||||
* but wildcards can be used for any of the fields in
|
||||
* the package meta-data.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class DeviceFilter {
|
||||
private static final String TAG = DeviceFilter.class.getSimpleName();
|
||||
|
||||
// USB Vendor ID (or -1 for unspecified)
|
||||
public final int mVendorId;
|
||||
// USB Product ID (or -1 for unspecified)
|
||||
public final int mProductId;
|
||||
// USB device or interface class (or -1 for unspecified)
|
||||
public final int mClass;
|
||||
// USB device subclass (or -1 for unspecified)
|
||||
public final int mSubclass;
|
||||
// USB device protocol (or -1 for unspecified)
|
||||
public final int mProtocol;
|
||||
// USB device manufacturer name string (or null for unspecified)
|
||||
public final String mManufacturerName;
|
||||
// USB device product name string (or null for unspecified)
|
||||
public final String mProductName;
|
||||
// USB device serial number string (or null for unspecified)
|
||||
public final String mSerialNumber;
|
||||
|
||||
public DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol,
|
||||
String manufacturer, String product, String serialnum) {
|
||||
mVendorId = vid;
|
||||
mProductId = pid;
|
||||
mClass = clasz;
|
||||
mSubclass = subclass;
|
||||
mProtocol = protocol;
|
||||
mManufacturerName = manufacturer;
|
||||
mProductName = product;
|
||||
mSerialNumber = serialnum;
|
||||
}
|
||||
|
||||
public DeviceFilter(UsbDevice device) {
|
||||
mVendorId = device.getVendorId();
|
||||
mProductId = device.getProductId();
|
||||
mClass = device.getDeviceClass();
|
||||
mSubclass = device.getDeviceSubclass();
|
||||
mProtocol = device.getDeviceProtocol();
|
||||
mManufacturerName = device.getManufacturerName();
|
||||
mProductName = device.getProductName();
|
||||
mSerialNumber = device.getSerialNumber();
|
||||
}
|
||||
|
||||
public static DeviceFilter read(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
int vendorId = -1;
|
||||
int productId = -1;
|
||||
int deviceClass = -1;
|
||||
int deviceSubclass = -1;
|
||||
int deviceProtocol = -1;
|
||||
String manufacturerName = null;
|
||||
String productName = null;
|
||||
String serialNumber = null;
|
||||
|
||||
int count = parser.getAttributeCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String name = parser.getAttributeName(i);
|
||||
String value = parser.getAttributeValue(i);
|
||||
// Attribute values are ints or strings
|
||||
if ("manufacturer-name".equals(name)) {
|
||||
manufacturerName = value;
|
||||
} else if ("product-name".equals(name)) {
|
||||
productName = value;
|
||||
} else if ("serial-number".equals(name)) {
|
||||
serialNumber = value;
|
||||
} else {
|
||||
int intValue;
|
||||
int radix = 10;
|
||||
if (value != null && value.length() > 2 && value.charAt(0) == '0' &&
|
||||
(value.charAt(1) == 'x' || value.charAt(1) == 'X')) {
|
||||
// allow hex values starting with 0x or 0X
|
||||
radix = 16;
|
||||
value = value.substring(2);
|
||||
}
|
||||
try {
|
||||
intValue = Integer.parseInt(value, radix);
|
||||
} catch (NumberFormatException e) {
|
||||
Slog.e(TAG, "invalid number for field " + name, e);
|
||||
continue;
|
||||
}
|
||||
if ("vendor-id".equals(name)) {
|
||||
vendorId = intValue;
|
||||
} else if ("product-id".equals(name)) {
|
||||
productId = intValue;
|
||||
} else if ("class".equals(name)) {
|
||||
deviceClass = intValue;
|
||||
} else if ("subclass".equals(name)) {
|
||||
deviceSubclass = intValue;
|
||||
} else if ("protocol".equals(name)) {
|
||||
deviceProtocol = intValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new DeviceFilter(vendorId, productId,
|
||||
deviceClass, deviceSubclass, deviceProtocol,
|
||||
manufacturerName, productName, serialNumber);
|
||||
}
|
||||
|
||||
public void write(XmlSerializer serializer) throws IOException {
|
||||
serializer.startTag(null, "usb-device");
|
||||
if (mVendorId != -1) {
|
||||
serializer.attribute(null, "vendor-id", Integer.toString(mVendorId));
|
||||
}
|
||||
if (mProductId != -1) {
|
||||
serializer.attribute(null, "product-id", Integer.toString(mProductId));
|
||||
}
|
||||
if (mClass != -1) {
|
||||
serializer.attribute(null, "class", Integer.toString(mClass));
|
||||
}
|
||||
if (mSubclass != -1) {
|
||||
serializer.attribute(null, "subclass", Integer.toString(mSubclass));
|
||||
}
|
||||
if (mProtocol != -1) {
|
||||
serializer.attribute(null, "protocol", Integer.toString(mProtocol));
|
||||
}
|
||||
if (mManufacturerName != null) {
|
||||
serializer.attribute(null, "manufacturer-name", mManufacturerName);
|
||||
}
|
||||
if (mProductName != null) {
|
||||
serializer.attribute(null, "product-name", mProductName);
|
||||
}
|
||||
if (mSerialNumber != null) {
|
||||
serializer.attribute(null, "serial-number", mSerialNumber);
|
||||
}
|
||||
serializer.endTag(null, "usb-device");
|
||||
}
|
||||
|
||||
private boolean matches(int clasz, int subclass, int protocol) {
|
||||
return ((mClass == -1 || clasz == mClass) &&
|
||||
(mSubclass == -1 || subclass == mSubclass) &&
|
||||
(mProtocol == -1 || protocol == mProtocol));
|
||||
}
|
||||
|
||||
public boolean matches(UsbDevice device) {
|
||||
if (mVendorId != -1 && device.getVendorId() != mVendorId) return false;
|
||||
if (mProductId != -1 && device.getProductId() != mProductId) return false;
|
||||
if (mManufacturerName != null && device.getManufacturerName() == null) return false;
|
||||
if (mProductName != null && device.getProductName() == null) return false;
|
||||
if (mSerialNumber != null && device.getSerialNumber() == null) return false;
|
||||
if (mManufacturerName != null && device.getManufacturerName() != null &&
|
||||
!mManufacturerName.equals(device.getManufacturerName())) return false;
|
||||
if (mProductName != null && device.getProductName() != null &&
|
||||
!mProductName.equals(device.getProductName())) return false;
|
||||
if (mSerialNumber != null && device.getSerialNumber() != null &&
|
||||
!mSerialNumber.equals(device.getSerialNumber())) return false;
|
||||
|
||||
// check device class/subclass/protocol
|
||||
if (matches(device.getDeviceClass(), device.getDeviceSubclass(),
|
||||
device.getDeviceProtocol())) return true;
|
||||
|
||||
// if device doesn't match, check the interfaces
|
||||
int count = device.getInterfaceCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UsbInterface intf = device.getInterface(i);
|
||||
if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(),
|
||||
intf.getInterfaceProtocol())) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the device described by {@code device} covered by this filter?
|
||||
*
|
||||
* @param device The device
|
||||
*
|
||||
* @return {@code true} iff this filter covers the {@code device}
|
||||
*/
|
||||
public boolean contains(DeviceFilter device) {
|
||||
// -1 and null means "match anything"
|
||||
|
||||
if (mVendorId != -1 && device.mVendorId != mVendorId) return false;
|
||||
if (mProductId != -1 && device.mProductId != mProductId) return false;
|
||||
if (mManufacturerName != null && !Objects.equals(mManufacturerName,
|
||||
device.mManufacturerName)) {
|
||||
return false;
|
||||
}
|
||||
if (mProductName != null && !Objects.equals(mProductName, device.mProductName)) {
|
||||
return false;
|
||||
}
|
||||
if (mSerialNumber != null
|
||||
&& !Objects.equals(mSerialNumber, device.mSerialNumber)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check device class/subclass/protocol
|
||||
return matches(device.mClass, device.mSubclass, device.mProtocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// can't compare if we have wildcard strings
|
||||
if (mVendorId == -1 || mProductId == -1 ||
|
||||
mClass == -1 || mSubclass == -1 || mProtocol == -1) {
|
||||
return false;
|
||||
}
|
||||
if (obj instanceof DeviceFilter) {
|
||||
DeviceFilter filter = (DeviceFilter)obj;
|
||||
|
||||
if (filter.mVendorId != mVendorId ||
|
||||
filter.mProductId != mProductId ||
|
||||
filter.mClass != mClass ||
|
||||
filter.mSubclass != mSubclass ||
|
||||
filter.mProtocol != mProtocol) {
|
||||
return(false);
|
||||
}
|
||||
if ((filter.mManufacturerName != null &&
|
||||
mManufacturerName == null) ||
|
||||
(filter.mManufacturerName == null &&
|
||||
mManufacturerName != null) ||
|
||||
(filter.mProductName != null &&
|
||||
mProductName == null) ||
|
||||
(filter.mProductName == null &&
|
||||
mProductName != null) ||
|
||||
(filter.mSerialNumber != null &&
|
||||
mSerialNumber == null) ||
|
||||
(filter.mSerialNumber == null &&
|
||||
mSerialNumber != null)) {
|
||||
return(false);
|
||||
}
|
||||
if ((filter.mManufacturerName != null &&
|
||||
mManufacturerName != null &&
|
||||
!mManufacturerName.equals(filter.mManufacturerName)) ||
|
||||
(filter.mProductName != null &&
|
||||
mProductName != null &&
|
||||
!mProductName.equals(filter.mProductName)) ||
|
||||
(filter.mSerialNumber != null &&
|
||||
mSerialNumber != null &&
|
||||
!mSerialNumber.equals(filter.mSerialNumber))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof UsbDevice) {
|
||||
UsbDevice device = (UsbDevice)obj;
|
||||
if (device.getVendorId() != mVendorId ||
|
||||
device.getProductId() != mProductId ||
|
||||
device.getDeviceClass() != mClass ||
|
||||
device.getDeviceSubclass() != mSubclass ||
|
||||
device.getDeviceProtocol() != mProtocol) {
|
||||
return(false);
|
||||
}
|
||||
if ((mManufacturerName != null && device.getManufacturerName() == null) ||
|
||||
(mManufacturerName == null && device.getManufacturerName() != null) ||
|
||||
(mProductName != null && device.getProductName() == null) ||
|
||||
(mProductName == null && device.getProductName() != null) ||
|
||||
(mSerialNumber != null && device.getSerialNumber() == null) ||
|
||||
(mSerialNumber == null && device.getSerialNumber() != null)) {
|
||||
return(false);
|
||||
}
|
||||
if ((device.getManufacturerName() != null &&
|
||||
!mManufacturerName.equals(device.getManufacturerName())) ||
|
||||
(device.getProductName() != null &&
|
||||
!mProductName.equals(device.getProductName())) ||
|
||||
(device.getSerialNumber() != null &&
|
||||
!mSerialNumber.equals(device.getSerialNumber()))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (((mVendorId << 16) | mProductId) ^
|
||||
((mClass << 16) | (mSubclass << 8) | mProtocol));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" + mProductId +
|
||||
",mClass=" + mClass + ",mSubclass=" + mSubclass +
|
||||
",mProtocol=" + mProtocol + ",mManufacturerName=" + mManufacturerName +
|
||||
",mProductName=" + mProductName + ",mSerialNumber=" + mSerialNumber +
|
||||
"]";
|
||||
}
|
||||
}
|
||||
@@ -124,16 +124,16 @@
|
||||
<string name="status_bar_use_physical_keyboard">Physical keyboard</string>
|
||||
|
||||
<!-- Prompt for the USB device permission dialog [CHAR LIMIT=80] -->
|
||||
<string name="usb_device_permission_prompt">Allow the app <xliff:g id="application">%1$s</xliff:g> to access the USB device?</string>
|
||||
<string name="usb_device_permission_prompt">Allow <xliff:g id="application">%1$s</xliff:g> to access <xliff:g id="usb_device">%2$s</xliff:g>?</string>
|
||||
|
||||
<!-- Prompt for the USB accessory permission dialog [CHAR LIMIT=80] -->
|
||||
<string name="usb_accessory_permission_prompt">Allow the app <xliff:g id="application">%1$s</xliff:g> to access the USB accessory?</string>
|
||||
<string name="usb_accessory_permission_prompt">Allow <xliff:g id="application">%1$s</xliff:g> to access <xliff:g id="usb_accessory">%2$s</xliff:g>?</string>
|
||||
|
||||
<!-- Prompt for the USB device confirm dialog [CHAR LIMIT=80] -->
|
||||
<string name="usb_device_confirm_prompt">Open <xliff:g id="activity">%1$s</xliff:g> when this USB device is connected?</string>
|
||||
<string name="usb_device_confirm_prompt">Open <xliff:g id="application">%1$s</xliff:g> to handle <xliff:g id="usb_device">%2$s</xliff:g>?</string>
|
||||
|
||||
<!-- Prompt for the USB accessory confirm dialog [CHAR LIMIT=80] -->
|
||||
<string name="usb_accessory_confirm_prompt">Open <xliff:g id="activity">%1$s</xliff:g> when this USB accessory is connected?</string>
|
||||
<string name="usb_accessory_confirm_prompt">Open <xliff:g id="application">%1$s</xliff:g> to handle <xliff:g id="usb_accessory">%2$s</xliff:g>?</string>
|
||||
|
||||
<!-- Prompt for the USB accessory URI dialog [CHAR LIMIT=80] -->
|
||||
<string name="usb_accessory_uri_prompt">No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="url">%1$s</xliff:g></string>
|
||||
@@ -145,10 +145,10 @@
|
||||
<string name="label_view">View</string>
|
||||
|
||||
<!-- Checkbox label for USB device dialogs. [CHAR LIMIT=50] -->
|
||||
<string name="always_use_device">Use by default for this USB device</string>
|
||||
<string name="always_use_device">Always open <xliff:g id="application">%1$s</xliff:g> when <xliff:g id="usb_device">%2$s</xliff:g> is connected</string>
|
||||
|
||||
<!-- Checkbox label for USB accessory dialogs. [CHAR LIMIT=50] -->
|
||||
<string name="always_use_accessory">Use by default for this USB accessory</string>
|
||||
<!-- Checkbox label for USB accessory dialogs. [CHAR LIMIT=50]-->
|
||||
<string name="always_use_accessory">Always open <xliff:g id="application">%1$s</xliff:g> when <xliff:g id="usb_accessory">%2$s</xliff:g> is connected</string>
|
||||
|
||||
<!-- Title of confirmation dialog for USB debugging -->
|
||||
<string name="usb_debugging_title">Allow USB debugging?</string>
|
||||
|
||||
@@ -71,10 +71,12 @@ public class UsbConfirmActivity extends AlertActivity
|
||||
ap.mIcon = mResolveInfo.loadIcon(packageManager);
|
||||
ap.mTitle = appName;
|
||||
if (mDevice == null) {
|
||||
ap.mMessage = getString(R.string.usb_accessory_confirm_prompt, appName);
|
||||
ap.mMessage = getString(R.string.usb_accessory_confirm_prompt, appName,
|
||||
mAccessory.getDescription());
|
||||
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
|
||||
} else {
|
||||
ap.mMessage = getString(R.string.usb_device_confirm_prompt, appName);
|
||||
ap.mMessage = getString(R.string.usb_device_confirm_prompt, appName,
|
||||
mDevice.getProductName());
|
||||
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
|
||||
}
|
||||
ap.mPositiveButtonText = getString(android.R.string.ok);
|
||||
@@ -88,9 +90,11 @@ public class UsbConfirmActivity extends AlertActivity
|
||||
ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
|
||||
mAlwaysUse = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
|
||||
if (mDevice == null) {
|
||||
mAlwaysUse.setText(R.string.always_use_accessory);
|
||||
mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
|
||||
mAccessory.getDescription()));
|
||||
} else {
|
||||
mAlwaysUse.setText(R.string.always_use_device);
|
||||
mAlwaysUse.setText(getString(R.string.always_use_device, appName,
|
||||
mDevice.getProductName()));
|
||||
}
|
||||
mAlwaysUse.setOnCheckedChangeListener(this);
|
||||
mClearDefaultHint = (TextView)ap.mView.findViewById(
|
||||
|
||||
@@ -16,13 +16,17 @@
|
||||
|
||||
package com.android.systemui.usb;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.hardware.usb.IUsbManager;
|
||||
import android.hardware.usb.UsbAccessory;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
@@ -41,8 +45,13 @@ import android.widget.TextView;
|
||||
|
||||
import com.android.internal.app.AlertActivity;
|
||||
import com.android.internal.app.AlertController;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import android.hardware.usb.AccessoryFilter;
|
||||
import android.hardware.usb.DeviceFilter;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
public class UsbPermissionActivity extends AlertActivity
|
||||
implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
|
||||
|
||||
@@ -84,10 +93,12 @@ public class UsbPermissionActivity extends AlertActivity
|
||||
ap.mIcon = aInfo.loadIcon(packageManager);
|
||||
ap.mTitle = appName;
|
||||
if (mDevice == null) {
|
||||
ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName);
|
||||
ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName,
|
||||
mAccessory.getDescription());
|
||||
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
|
||||
} else {
|
||||
ap.mMessage = getString(R.string.usb_device_permission_prompt, appName);
|
||||
ap.mMessage = getString(R.string.usb_device_permission_prompt, appName,
|
||||
mDevice.getProductName());
|
||||
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
|
||||
}
|
||||
ap.mPositiveButtonText = getString(android.R.string.ok);
|
||||
@@ -95,25 +106,123 @@ public class UsbPermissionActivity extends AlertActivity
|
||||
ap.mPositiveButtonListener = this;
|
||||
ap.mNegativeButtonListener = this;
|
||||
|
||||
// add "always use" checkbox
|
||||
LayoutInflater inflater = (LayoutInflater)getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
|
||||
mAlwaysUse = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
|
||||
if (mDevice == null) {
|
||||
mAlwaysUse.setText(R.string.always_use_accessory);
|
||||
} else {
|
||||
mAlwaysUse.setText(R.string.always_use_device);
|
||||
try {
|
||||
PackageInfo packageInfo = packageManager.getPackageInfo(mPackageName,
|
||||
PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
|
||||
|
||||
if ((mDevice != null && canBeDefault(mDevice, packageInfo))
|
||||
|| (mAccessory != null && canBeDefault(mAccessory, packageInfo))) {
|
||||
// add "open when" checkbox
|
||||
LayoutInflater inflater = (LayoutInflater) getSystemService(
|
||||
Context.LAYOUT_INFLATER_SERVICE);
|
||||
ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
|
||||
mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
|
||||
if (mDevice == null) {
|
||||
mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
|
||||
mAccessory.getDescription()));
|
||||
} else {
|
||||
mAlwaysUse.setText(getString(R.string.always_use_device, appName,
|
||||
mDevice.getProductName()));
|
||||
}
|
||||
mAlwaysUse.setOnCheckedChangeListener(this);
|
||||
|
||||
mClearDefaultHint = (TextView)ap.mView.findViewById(
|
||||
com.android.internal.R.id.clearDefaultHint);
|
||||
mClearDefaultHint.setVisibility(View.GONE);
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
// ignore
|
||||
}
|
||||
mAlwaysUse.setOnCheckedChangeListener(this);
|
||||
mClearDefaultHint = (TextView)ap.mView.findViewById(
|
||||
com.android.internal.R.id.clearDefaultHint);
|
||||
mClearDefaultHint.setVisibility(View.GONE);
|
||||
|
||||
setupAlert();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the app be the default for the USB device. I.e. can the app be launched by default if
|
||||
* the device is plugged in.
|
||||
*
|
||||
* @param device The device the app would be default for
|
||||
* @param packageInfo The package info of the app
|
||||
*
|
||||
* @return {@code true} iff the app can be default
|
||||
*/
|
||||
private boolean canBeDefault(@NonNull UsbDevice device, @NonNull PackageInfo packageInfo) {
|
||||
ActivityInfo[] activities = packageInfo.activities;
|
||||
if (activities != null) {
|
||||
int numActivities = activities.length;
|
||||
for (int i = 0; i < numActivities; i++) {
|
||||
ActivityInfo activityInfo = activities[i];
|
||||
|
||||
try (XmlResourceParser parser = activityInfo.loadXmlMetaData(getPackageManager(),
|
||||
UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
|
||||
if (parser == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
XmlUtils.nextElement(parser);
|
||||
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
|
||||
if ("usb-device".equals(parser.getName())) {
|
||||
DeviceFilter filter = DeviceFilter.read(parser);
|
||||
if (filter.matches(device)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
XmlUtils.nextElement(parser);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the app be the default for the USB accessory. I.e. can the app be launched by default if
|
||||
* the accessory is plugged in.
|
||||
*
|
||||
* @param accessory The accessory the app would be default for
|
||||
* @param packageInfo The package info of the app
|
||||
*
|
||||
* @return {@code true} iff the app can be default
|
||||
*/
|
||||
private boolean canBeDefault(@NonNull UsbAccessory accessory,
|
||||
@NonNull PackageInfo packageInfo) {
|
||||
ActivityInfo[] activities = packageInfo.activities;
|
||||
if (activities != null) {
|
||||
int numActivities = activities.length;
|
||||
for (int i = 0; i < numActivities; i++) {
|
||||
ActivityInfo activityInfo = activities[i];
|
||||
|
||||
try (XmlResourceParser parser = activityInfo.loadXmlMetaData(getPackageManager(),
|
||||
UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
|
||||
if (parser == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
XmlUtils.nextElement(parser);
|
||||
while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
|
||||
if ("usb-accessory".equals(parser.getName())) {
|
||||
AccessoryFilter filter = AccessoryFilter.read(parser);
|
||||
if (filter.matches(accessory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
XmlUtils.nextElement(parser);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
IBinder b = ServiceManager.getService(USB_SERVICE);
|
||||
|
||||
@@ -32,9 +32,10 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.hardware.usb.AccessoryFilter;
|
||||
import android.hardware.usb.DeviceFilter;
|
||||
import android.hardware.usb.UsbAccessory;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbInterface;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
@@ -58,7 +59,6 @@ import libcore.io.IoUtils;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlSerializer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -71,7 +71,6 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
class UsbProfileGroupSettingsManager {
|
||||
private static final String TAG = UsbProfileGroupSettingsManager.class.getSimpleName();
|
||||
@@ -157,404 +156,6 @@ class UsbProfileGroupSettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
// This class is used to describe a USB device.
|
||||
// When used in HashMaps all values must be specified,
|
||||
// but wildcards can be used for any of the fields in
|
||||
// the package meta-data.
|
||||
private static class DeviceFilter {
|
||||
// USB Vendor ID (or -1 for unspecified)
|
||||
public final int mVendorId;
|
||||
// USB Product ID (or -1 for unspecified)
|
||||
public final int mProductId;
|
||||
// USB device or interface class (or -1 for unspecified)
|
||||
public final int mClass;
|
||||
// USB device subclass (or -1 for unspecified)
|
||||
public final int mSubclass;
|
||||
// USB device protocol (or -1 for unspecified)
|
||||
public final int mProtocol;
|
||||
// USB device manufacturer name string (or null for unspecified)
|
||||
public final String mManufacturerName;
|
||||
// USB device product name string (or null for unspecified)
|
||||
public final String mProductName;
|
||||
// USB device serial number string (or null for unspecified)
|
||||
public final String mSerialNumber;
|
||||
|
||||
public DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol,
|
||||
String manufacturer, String product, String serialnum) {
|
||||
mVendorId = vid;
|
||||
mProductId = pid;
|
||||
mClass = clasz;
|
||||
mSubclass = subclass;
|
||||
mProtocol = protocol;
|
||||
mManufacturerName = manufacturer;
|
||||
mProductName = product;
|
||||
mSerialNumber = serialnum;
|
||||
}
|
||||
|
||||
public DeviceFilter(UsbDevice device) {
|
||||
mVendorId = device.getVendorId();
|
||||
mProductId = device.getProductId();
|
||||
mClass = device.getDeviceClass();
|
||||
mSubclass = device.getDeviceSubclass();
|
||||
mProtocol = device.getDeviceProtocol();
|
||||
mManufacturerName = device.getManufacturerName();
|
||||
mProductName = device.getProductName();
|
||||
mSerialNumber = device.getSerialNumber();
|
||||
}
|
||||
|
||||
public static DeviceFilter read(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
int vendorId = -1;
|
||||
int productId = -1;
|
||||
int deviceClass = -1;
|
||||
int deviceSubclass = -1;
|
||||
int deviceProtocol = -1;
|
||||
String manufacturerName = null;
|
||||
String productName = null;
|
||||
String serialNumber = null;
|
||||
|
||||
int count = parser.getAttributeCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String name = parser.getAttributeName(i);
|
||||
String value = parser.getAttributeValue(i);
|
||||
// Attribute values are ints or strings
|
||||
if ("manufacturer-name".equals(name)) {
|
||||
manufacturerName = value;
|
||||
} else if ("product-name".equals(name)) {
|
||||
productName = value;
|
||||
} else if ("serial-number".equals(name)) {
|
||||
serialNumber = value;
|
||||
} else {
|
||||
int intValue;
|
||||
int radix = 10;
|
||||
if (value != null && value.length() > 2 && value.charAt(0) == '0' &&
|
||||
(value.charAt(1) == 'x' || value.charAt(1) == 'X')) {
|
||||
// allow hex values starting with 0x or 0X
|
||||
radix = 16;
|
||||
value = value.substring(2);
|
||||
}
|
||||
try {
|
||||
intValue = Integer.parseInt(value, radix);
|
||||
} catch (NumberFormatException e) {
|
||||
Slog.e(TAG, "invalid number for field " + name, e);
|
||||
continue;
|
||||
}
|
||||
if ("vendor-id".equals(name)) {
|
||||
vendorId = intValue;
|
||||
} else if ("product-id".equals(name)) {
|
||||
productId = intValue;
|
||||
} else if ("class".equals(name)) {
|
||||
deviceClass = intValue;
|
||||
} else if ("subclass".equals(name)) {
|
||||
deviceSubclass = intValue;
|
||||
} else if ("protocol".equals(name)) {
|
||||
deviceProtocol = intValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new DeviceFilter(vendorId, productId,
|
||||
deviceClass, deviceSubclass, deviceProtocol,
|
||||
manufacturerName, productName, serialNumber);
|
||||
}
|
||||
|
||||
public void write(XmlSerializer serializer) throws IOException {
|
||||
serializer.startTag(null, "usb-device");
|
||||
if (mVendorId != -1) {
|
||||
serializer.attribute(null, "vendor-id", Integer.toString(mVendorId));
|
||||
}
|
||||
if (mProductId != -1) {
|
||||
serializer.attribute(null, "product-id", Integer.toString(mProductId));
|
||||
}
|
||||
if (mClass != -1) {
|
||||
serializer.attribute(null, "class", Integer.toString(mClass));
|
||||
}
|
||||
if (mSubclass != -1) {
|
||||
serializer.attribute(null, "subclass", Integer.toString(mSubclass));
|
||||
}
|
||||
if (mProtocol != -1) {
|
||||
serializer.attribute(null, "protocol", Integer.toString(mProtocol));
|
||||
}
|
||||
if (mManufacturerName != null) {
|
||||
serializer.attribute(null, "manufacturer-name", mManufacturerName);
|
||||
}
|
||||
if (mProductName != null) {
|
||||
serializer.attribute(null, "product-name", mProductName);
|
||||
}
|
||||
if (mSerialNumber != null) {
|
||||
serializer.attribute(null, "serial-number", mSerialNumber);
|
||||
}
|
||||
serializer.endTag(null, "usb-device");
|
||||
}
|
||||
|
||||
private boolean matches(int clasz, int subclass, int protocol) {
|
||||
return ((mClass == -1 || clasz == mClass) &&
|
||||
(mSubclass == -1 || subclass == mSubclass) &&
|
||||
(mProtocol == -1 || protocol == mProtocol));
|
||||
}
|
||||
|
||||
public boolean matches(UsbDevice device) {
|
||||
if (mVendorId != -1 && device.getVendorId() != mVendorId) return false;
|
||||
if (mProductId != -1 && device.getProductId() != mProductId) return false;
|
||||
if (mManufacturerName != null && device.getManufacturerName() == null) return false;
|
||||
if (mProductName != null && device.getProductName() == null) return false;
|
||||
if (mSerialNumber != null && device.getSerialNumber() == null) return false;
|
||||
if (mManufacturerName != null && device.getManufacturerName() != null &&
|
||||
!mManufacturerName.equals(device.getManufacturerName())) return false;
|
||||
if (mProductName != null && device.getProductName() != null &&
|
||||
!mProductName.equals(device.getProductName())) return false;
|
||||
if (mSerialNumber != null && device.getSerialNumber() != null &&
|
||||
!mSerialNumber.equals(device.getSerialNumber())) return false;
|
||||
|
||||
// check device class/subclass/protocol
|
||||
if (matches(device.getDeviceClass(), device.getDeviceSubclass(),
|
||||
device.getDeviceProtocol())) return true;
|
||||
|
||||
// if device doesn't match, check the interfaces
|
||||
int count = device.getInterfaceCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UsbInterface intf = device.getInterface(i);
|
||||
if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(),
|
||||
intf.getInterfaceProtocol())) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the device described by {@code device} covered by this filter?
|
||||
*
|
||||
* @param device The device
|
||||
*
|
||||
* @return {@code true} iff this filter covers the {@code device}
|
||||
*/
|
||||
public boolean contains(DeviceFilter device) {
|
||||
// -1 and null means "match anything"
|
||||
|
||||
if (mVendorId != -1 && device.mVendorId != mVendorId) return false;
|
||||
if (mProductId != -1 && device.mProductId != mProductId) return false;
|
||||
if (mManufacturerName != null && !Objects.equals(mManufacturerName,
|
||||
device.mManufacturerName)) {
|
||||
return false;
|
||||
}
|
||||
if (mProductName != null && !Objects.equals(mProductName, device.mProductName)) {
|
||||
return false;
|
||||
}
|
||||
if (mSerialNumber != null
|
||||
&& !Objects.equals(mSerialNumber, device.mSerialNumber)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check device class/subclass/protocol
|
||||
return matches(device.mClass, device.mSubclass, device.mProtocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// can't compare if we have wildcard strings
|
||||
if (mVendorId == -1 || mProductId == -1 ||
|
||||
mClass == -1 || mSubclass == -1 || mProtocol == -1) {
|
||||
return false;
|
||||
}
|
||||
if (obj instanceof DeviceFilter) {
|
||||
DeviceFilter filter = (DeviceFilter)obj;
|
||||
|
||||
if (filter.mVendorId != mVendorId ||
|
||||
filter.mProductId != mProductId ||
|
||||
filter.mClass != mClass ||
|
||||
filter.mSubclass != mSubclass ||
|
||||
filter.mProtocol != mProtocol) {
|
||||
return(false);
|
||||
}
|
||||
if ((filter.mManufacturerName != null &&
|
||||
mManufacturerName == null) ||
|
||||
(filter.mManufacturerName == null &&
|
||||
mManufacturerName != null) ||
|
||||
(filter.mProductName != null &&
|
||||
mProductName == null) ||
|
||||
(filter.mProductName == null &&
|
||||
mProductName != null) ||
|
||||
(filter.mSerialNumber != null &&
|
||||
mSerialNumber == null) ||
|
||||
(filter.mSerialNumber == null &&
|
||||
mSerialNumber != null)) {
|
||||
return(false);
|
||||
}
|
||||
if ((filter.mManufacturerName != null &&
|
||||
mManufacturerName != null &&
|
||||
!mManufacturerName.equals(filter.mManufacturerName)) ||
|
||||
(filter.mProductName != null &&
|
||||
mProductName != null &&
|
||||
!mProductName.equals(filter.mProductName)) ||
|
||||
(filter.mSerialNumber != null &&
|
||||
mSerialNumber != null &&
|
||||
!mSerialNumber.equals(filter.mSerialNumber))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof UsbDevice) {
|
||||
UsbDevice device = (UsbDevice)obj;
|
||||
if (device.getVendorId() != mVendorId ||
|
||||
device.getProductId() != mProductId ||
|
||||
device.getDeviceClass() != mClass ||
|
||||
device.getDeviceSubclass() != mSubclass ||
|
||||
device.getDeviceProtocol() != mProtocol) {
|
||||
return(false);
|
||||
}
|
||||
if ((mManufacturerName != null && device.getManufacturerName() == null) ||
|
||||
(mManufacturerName == null && device.getManufacturerName() != null) ||
|
||||
(mProductName != null && device.getProductName() == null) ||
|
||||
(mProductName == null && device.getProductName() != null) ||
|
||||
(mSerialNumber != null && device.getSerialNumber() == null) ||
|
||||
(mSerialNumber == null && device.getSerialNumber() != null)) {
|
||||
return(false);
|
||||
}
|
||||
if ((device.getManufacturerName() != null &&
|
||||
!mManufacturerName.equals(device.getManufacturerName())) ||
|
||||
(device.getProductName() != null &&
|
||||
!mProductName.equals(device.getProductName())) ||
|
||||
(device.getSerialNumber() != null &&
|
||||
!mSerialNumber.equals(device.getSerialNumber()))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (((mVendorId << 16) | mProductId) ^
|
||||
((mClass << 16) | (mSubclass << 8) | mProtocol));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" + mProductId +
|
||||
",mClass=" + mClass + ",mSubclass=" + mSubclass +
|
||||
",mProtocol=" + mProtocol + ",mManufacturerName=" + mManufacturerName +
|
||||
",mProductName=" + mProductName + ",mSerialNumber=" + mSerialNumber +
|
||||
"]";
|
||||
}
|
||||
}
|
||||
|
||||
// This class is used to describe a USB accessory.
|
||||
// When used in HashMaps all values must be specified,
|
||||
// but wildcards can be used for any of the fields in
|
||||
// the package meta-data.
|
||||
private static class AccessoryFilter {
|
||||
// USB accessory manufacturer (or null for unspecified)
|
||||
public final String mManufacturer;
|
||||
// USB accessory model (or null for unspecified)
|
||||
public final String mModel;
|
||||
// USB accessory version (or null for unspecified)
|
||||
public final String mVersion;
|
||||
|
||||
public AccessoryFilter(String manufacturer, String model, String version) {
|
||||
mManufacturer = manufacturer;
|
||||
mModel = model;
|
||||
mVersion = version;
|
||||
}
|
||||
|
||||
public AccessoryFilter(UsbAccessory accessory) {
|
||||
mManufacturer = accessory.getManufacturer();
|
||||
mModel = accessory.getModel();
|
||||
mVersion = accessory.getVersion();
|
||||
}
|
||||
|
||||
public static AccessoryFilter read(XmlPullParser parser)
|
||||
throws XmlPullParserException, IOException {
|
||||
String manufacturer = null;
|
||||
String model = null;
|
||||
String version = null;
|
||||
|
||||
int count = parser.getAttributeCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
String name = parser.getAttributeName(i);
|
||||
String value = parser.getAttributeValue(i);
|
||||
|
||||
if ("manufacturer".equals(name)) {
|
||||
manufacturer = value;
|
||||
} else if ("model".equals(name)) {
|
||||
model = value;
|
||||
} else if ("version".equals(name)) {
|
||||
version = value;
|
||||
}
|
||||
}
|
||||
return new AccessoryFilter(manufacturer, model, version);
|
||||
}
|
||||
|
||||
public void write(XmlSerializer serializer)throws IOException {
|
||||
serializer.startTag(null, "usb-accessory");
|
||||
if (mManufacturer != null) {
|
||||
serializer.attribute(null, "manufacturer", mManufacturer);
|
||||
}
|
||||
if (mModel != null) {
|
||||
serializer.attribute(null, "model", mModel);
|
||||
}
|
||||
if (mVersion != null) {
|
||||
serializer.attribute(null, "version", mVersion);
|
||||
}
|
||||
serializer.endTag(null, "usb-accessory");
|
||||
}
|
||||
|
||||
public boolean matches(UsbAccessory acc) {
|
||||
if (mManufacturer != null && !acc.getManufacturer().equals(mManufacturer)) return false;
|
||||
if (mModel != null && !acc.getModel().equals(mModel)) return false;
|
||||
return !(mVersion != null && !acc.getVersion().equals(mVersion));
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the accessories described {@code accessory} covered by this filter?
|
||||
*
|
||||
* @param accessory A filter describing the accessory
|
||||
*
|
||||
* @return {@code true} iff this the filter covers the accessory
|
||||
*/
|
||||
public boolean contains(AccessoryFilter accessory) {
|
||||
if (mManufacturer != null && !Objects.equals(accessory.mManufacturer, mManufacturer)) {
|
||||
return false;
|
||||
}
|
||||
if (mModel != null && !Objects.equals(accessory.mModel, mModel)) return false;
|
||||
return !(mVersion != null && !Objects.equals(accessory.mVersion, mVersion));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// can't compare if we have wildcard strings
|
||||
if (mManufacturer == null || mModel == null || mVersion == null) {
|
||||
return false;
|
||||
}
|
||||
if (obj instanceof AccessoryFilter) {
|
||||
AccessoryFilter filter = (AccessoryFilter)obj;
|
||||
return (mManufacturer.equals(filter.mManufacturer) &&
|
||||
mModel.equals(filter.mModel) &&
|
||||
mVersion.equals(filter.mVersion));
|
||||
}
|
||||
if (obj instanceof UsbAccessory) {
|
||||
UsbAccessory accessory = (UsbAccessory)obj;
|
||||
return (mManufacturer.equals(accessory.getManufacturer()) &&
|
||||
mModel.equals(accessory.getModel()) &&
|
||||
mVersion.equals(accessory.getVersion()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^
|
||||
(mModel == null ? 0 : mModel.hashCode()) ^
|
||||
(mVersion == null ? 0 : mVersion.hashCode()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccessoryFilter[mManufacturer=\"" + mManufacturer +
|
||||
"\", mModel=\"" + mModel +
|
||||
"\", mVersion=\"" + mVersion + "\"]";
|
||||
}
|
||||
}
|
||||
|
||||
private class MyPackageMonitor extends PackageMonitor {
|
||||
@Override
|
||||
public void onPackageAdded(String packageName, int uid) {
|
||||
|
||||
Reference in New Issue
Block a user