Merge "Add api lint to upload checks"
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 42b0f6b..1503445 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -2,3 +2,8 @@
name: "IKeyAttestationApplicationIdProvider.aidl",
srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
}
+
+filegroup {
+ name: "IKeystoreService.aidl",
+ srcs: ["android/security/IKeystoreService.aidl"],
+}
diff --git a/core/java/android/hardware/usb/AccessoryFilter.java b/core/java/android/hardware/usb/AccessoryFilter.java
new file mode 100644
index 0000000..d9b7c5b
--- /dev/null
+++ b/core/java/android/hardware/usb/AccessoryFilter.java
@@ -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 + "\"]";
+ }
+}
diff --git a/core/java/android/hardware/usb/DeviceFilter.java b/core/java/android/hardware/usb/DeviceFilter.java
new file mode 100644
index 0000000..439c629
--- /dev/null
+++ b/core/java/android/hardware/usb/DeviceFilter.java
@@ -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 +
+ "]";
+ }
+}
diff --git a/core/java/android/security/KeystoreArguments.aidl b/core/java/android/security/KeystoreArguments.aidl
index d636414..dc8ed50 100644
--- a/core/java/android/security/KeystoreArguments.aidl
+++ b/core/java/android/security/KeystoreArguments.aidl
@@ -17,4 +17,4 @@
package android.security;
/* @hide */
-parcelable KeystoreArguments;
+parcelable KeystoreArguments cpp_header "keystore/KeystoreArguments.h";
diff --git a/core/java/android/security/keymaster/ExportResult.aidl b/core/java/android/security/keymaster/ExportResult.aidl
index 4d9b2de..1748653 100644
--- a/core/java/android/security/keymaster/ExportResult.aidl
+++ b/core/java/android/security/keymaster/ExportResult.aidl
@@ -17,4 +17,4 @@
package android.security.keymaster;
/* @hide */
-parcelable ExportResult;
+parcelable ExportResult cpp_header "keystore/ExportResult.h";
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.aidl b/core/java/android/security/keymaster/KeyCharacteristics.aidl
index be739d3..32e75ad 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.aidl
+++ b/core/java/android/security/keymaster/KeyCharacteristics.aidl
@@ -17,4 +17,4 @@
package android.security.keymaster;
/* @hide */
-parcelable KeyCharacteristics;
+parcelable KeyCharacteristics cpp_header "keystore/KeyCharacteristics.h";
diff --git a/core/java/android/security/keymaster/KeymasterArguments.aidl b/core/java/android/security/keymaster/KeymasterArguments.aidl
index 1a73206..44d9f09 100644
--- a/core/java/android/security/keymaster/KeymasterArguments.aidl
+++ b/core/java/android/security/keymaster/KeymasterArguments.aidl
@@ -17,4 +17,4 @@
package android.security.keymaster;
/* @hide */
-parcelable KeymasterArguments;
+parcelable KeymasterArguments cpp_header "keystore/KeymasterArguments.h";
diff --git a/core/java/android/security/keymaster/KeymasterBlob.aidl b/core/java/android/security/keymaster/KeymasterBlob.aidl
index b7cd1c9..5c5db9e 100644
--- a/core/java/android/security/keymaster/KeymasterBlob.aidl
+++ b/core/java/android/security/keymaster/KeymasterBlob.aidl
@@ -17,4 +17,4 @@
package android.security.keymaster;
/* @hide */
-parcelable KeymasterBlob;
+parcelable KeymasterBlob cpp_header "keystore/KeymasterBlob.h";
diff --git a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
index dc1876a..ddb5cae 100644
--- a/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
+++ b/core/java/android/security/keymaster/KeymasterCertificateChain.aidl
@@ -17,4 +17,4 @@
package android.security.keymaster;
/* @hide */
-parcelable KeymasterCertificateChain;
+parcelable KeymasterCertificateChain cpp_header "keystore/KeymasterCertificateChain.h";
diff --git a/core/java/android/security/keymaster/OperationResult.aidl b/core/java/android/security/keymaster/OperationResult.aidl
index ed26c8d..db689d4 100644
--- a/core/java/android/security/keymaster/OperationResult.aidl
+++ b/core/java/android/security/keymaster/OperationResult.aidl
@@ -17,4 +17,4 @@
package android.security.keymaster;
/* @hide */
-parcelable OperationResult;
+parcelable OperationResult cpp_header "keystore/OperationResult.h";
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index 18afe6e..ac79249 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -137,15 +137,18 @@
class StyleRun : public Run {
public:
- StyleRun(int32_t start, int32_t end, minikin::MinikinPaint&& paint, bool isRtl)
- : Run(start, end), mPaint(std::move(paint)), mIsRtl(isRtl) {}
+ StyleRun(int32_t start, int32_t end, minikin::MinikinPaint&& paint,
+ std::shared_ptr<minikin::FontCollection>&& collection, bool isRtl)
+ : Run(start, end), mPaint(std::move(paint)), mCollection(std::move(collection)),
+ mIsRtl(isRtl) {}
void addTo(minikin::LineBreaker* lineBreaker) override {
- lineBreaker->addStyleRun(&mPaint, mStart, mEnd, mIsRtl);
+ lineBreaker->addStyleRun(&mPaint, mCollection, mStart, mEnd, mIsRtl);
}
private:
minikin::MinikinPaint mPaint;
+ std::shared_ptr<minikin::FontCollection> mCollection;
const bool mIsRtl;
};
@@ -173,8 +176,10 @@
mIndents(std::move(indents)), mLeftPaddings(std::move(leftPaddings)),
mRightPaddings(std::move(rightPaddings)) {}
- void addStyleRun(int32_t start, int32_t end, minikin::MinikinPaint&& paint, bool isRtl) {
- mRuns.emplace_back(std::make_unique<StyleRun>(start, end, std::move(paint), isRtl));
+ void addStyleRun(int32_t start, int32_t end, minikin::MinikinPaint&& paint,
+ std::shared_ptr<minikin::FontCollection> collection, bool isRtl) {
+ mRuns.emplace_back(std::make_unique<StyleRun>(
+ start, end, std::move(paint), std::move(collection), isRtl));
}
void addReplacementRun(int32_t start, int32_t end, float width, uint32_t localeListId) {
@@ -329,7 +334,7 @@
Paint* paint = reinterpret_cast<Paint*>(nativePaint);
const Typeface* typeface = Typeface::resolveDefault(paint->getAndroidTypeface());
minikin::MinikinPaint minikinPaint = MinikinUtils::prepareMinikinPaint(paint, typeface);
- builder->addStyleRun(start, end, std::move(minikinPaint), isRtl);
+ builder->addStyleRun(start, end, std::move(minikinPaint), typeface->fFontCollection, isRtl);
}
// CriticalNative
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index a7469cd..399dddd 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -54,7 +54,7 @@
public class KeyStore {
private static final String TAG = "KeyStore";
- // ResponseCodes
+ // ResponseCodes - see system/security/keystore/include/keystore/keystore.h
public static final int NO_ERROR = 1;
public static final int LOCKED = 2;
public static final int UNINITIALIZED = 3;
@@ -168,10 +168,14 @@
public byte[] get(String key, int uid) {
try {
+ key = key != null ? key : "";
return mBinder.get(key, uid);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (android.os.ServiceSpecificException e) {
+ Log.w(TAG, "KeyStore exception", e);
+ return null;
}
}
@@ -185,6 +189,9 @@
public int insert(String key, byte[] value, int uid, int flags) {
try {
+ if (value == null) {
+ value = new byte[0];
+ }
return mBinder.insert(key, value, uid, flags);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -228,6 +235,9 @@
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (android.os.ServiceSpecificException e) {
+ Log.w(TAG, "KeyStore exception", e);
+ return null;
}
}
@@ -276,6 +286,7 @@
*/
public boolean unlock(int userId, String password) {
try {
+ password = password != null ? password : "";
mError = mBinder.unlock(userId, password);
return mError == NO_ERROR;
} catch (RemoteException e) {
@@ -330,16 +341,25 @@
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return null;
+ } catch (android.os.ServiceSpecificException e) {
+ Log.w(TAG, "KeyStore exception", e);
+ return null;
}
+
}
public boolean verify(String key, byte[] data, byte[] signature) {
try {
+ signature = signature != null ? signature : new byte[0];
return mBinder.verify(key, data, signature) == NO_ERROR;
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
return false;
+ } catch (android.os.ServiceSpecificException e) {
+ Log.w(TAG, "KeyStore exception", e);
+ return false;
}
+
}
public String grant(String key, int uid) {
@@ -432,6 +452,8 @@
public int generateKey(String alias, KeymasterArguments args, byte[] entropy, int uid,
int flags, KeyCharacteristics outCharacteristics) {
try {
+ entropy = entropy != null ? entropy : new byte[0];
+ args = args != null ? args : new KeymasterArguments();
return mBinder.generateKey(alias, args, entropy, uid, flags, outCharacteristics);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -447,6 +469,8 @@
public int getKeyCharacteristics(String alias, KeymasterBlob clientId, KeymasterBlob appId,
int uid, KeyCharacteristics outCharacteristics) {
try {
+ clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
+ appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
return mBinder.getKeyCharacteristics(alias, clientId, appId, uid, outCharacteristics);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -478,6 +502,8 @@
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
KeymasterBlob appId, int uid) {
try {
+ clientId = clientId != null ? clientId : new KeymasterBlob(new byte[0]);
+ appId = appId != null ? appId : new KeymasterBlob(new byte[0]);
return mBinder.exportKey(alias, format, clientId, appId, uid);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -492,6 +518,8 @@
public OperationResult begin(String alias, int purpose, boolean pruneable,
KeymasterArguments args, byte[] entropy, int uid) {
try {
+ args = args != null ? args : new KeymasterArguments();
+ entropy = entropy != null ? entropy : new byte[0];
return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -501,11 +529,15 @@
public OperationResult begin(String alias, int purpose, boolean pruneable,
KeymasterArguments args, byte[] entropy) {
+ entropy = entropy != null ? entropy : new byte[0];
+ args = args != null ? args : new KeymasterArguments();
return begin(alias, purpose, pruneable, args, entropy, UID_SELF);
}
public OperationResult update(IBinder token, KeymasterArguments arguments, byte[] input) {
try {
+ arguments = arguments != null ? arguments : new KeymasterArguments();
+ input = input != null ? input : new byte[0];
return mBinder.update(token, arguments, input);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -516,6 +548,9 @@
public OperationResult finish(IBinder token, KeymasterArguments arguments, byte[] signature,
byte[] entropy) {
try {
+ arguments = arguments != null ? arguments : new KeymasterArguments();
+ entropy = entropy != null ? entropy : new byte[0];
+ signature = signature != null ? signature : new byte[0];
return mBinder.finish(token, arguments, signature, entropy);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -632,6 +667,12 @@
public int attestKey(
String alias, KeymasterArguments params, KeymasterCertificateChain outChain) {
try {
+ if (params == null) {
+ params = new KeymasterArguments();
+ }
+ if (outChain == null) {
+ outChain = new KeymasterCertificateChain();
+ }
return mBinder.attestKey(alias, params, outChain);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
@@ -641,6 +682,12 @@
public int attestDeviceIds(KeymasterArguments params, KeymasterCertificateChain outChain) {
try {
+ if (params == null) {
+ params = new KeymasterArguments();
+ }
+ if (outChain == null) {
+ outChain = new KeymasterCertificateChain();
+ }
return mBinder.attestDeviceIds(params, outChain);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/libs/hwui/hwui/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 2a1a1f3..90fe0b7 100644
--- a/libs/hwui/hwui/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -30,43 +30,46 @@
const Typeface* typeface) {
const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
minikin::FontStyle resolved = resolvedFace->fStyle;
+
const minikin::FontVariant minikinVariant =
(paint->getFontVariant() == minikin::FontVariant::ELEGANT)
? minikin::FontVariant::ELEGANT
: minikin::FontVariant::COMPACT;
- float textSize = paint->getTextSize();
- if (!paint->isLinearText()) {
- // If linear text is not specified, truncate the value.
- textSize = trunc(textSize);
- }
- return minikin::MinikinPaint(
- textSize,
- paint->getTextScaleX(),
- paint->getTextSkewX(),
- paint->getLetterSpacing(),
- paint->getWordSpacing(),
- MinikinFontSkia::packPaintFlags(paint),
- paint->getMinikinLocaleListId(),
- minikin::FontStyle(minikinVariant, resolved.weight, resolved.slant),
- minikin::HyphenEdit(paint->getHyphenEdit()),
- paint->getFontFeatureSettings(),
- resolvedFace->fFontCollection);
+
+ minikin::MinikinPaint minikinPaint;
+ /* Prepare minikin Paint */
+ minikinPaint.size =
+ paint->isLinearText() ? paint->getTextSize() : static_cast<int>(paint->getTextSize());
+ minikinPaint.scaleX = paint->getTextScaleX();
+ minikinPaint.skewX = paint->getTextSkewX();
+ minikinPaint.letterSpacing = paint->getLetterSpacing();
+ minikinPaint.wordSpacing = paint->getWordSpacing();
+ minikinPaint.paintFlags = MinikinFontSkia::packPaintFlags(paint);
+ minikinPaint.localeListId = paint->getMinikinLocaleListId();
+ minikinPaint.fontStyle = minikin::FontStyle(minikinVariant, resolved.weight, resolved.slant);
+ minikinPaint.fontFeatureSettings = paint->getFontFeatureSettings();
+ minikinPaint.hyphenEdit = minikin::HyphenEdit(paint->getHyphenEdit());
+ return minikinPaint;
}
minikin::Layout MinikinUtils::doLayout(const Paint* paint, minikin::Bidi bidiFlags,
const Typeface* typeface, const uint16_t* buf, size_t start,
size_t count, size_t bufSize) {
+ minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
minikin::Layout layout;
- layout.doLayout(buf, start, count, bufSize, bidiFlags, prepareMinikinPaint(paint, typeface));
+ layout.doLayout(buf, start, count, bufSize, bidiFlags, minikinPaint,
+ Typeface::resolveDefault(typeface)->fFontCollection);
return layout;
}
float MinikinUtils::measureText(const Paint* paint, minikin::Bidi bidiFlags,
const Typeface* typeface, const uint16_t* buf, size_t start,
size_t count, size_t bufSize, float* advances) {
- return minikin::Layout::measureText(
- buf, start, count, bufSize, bidiFlags, prepareMinikinPaint(paint, typeface), advances,
- nullptr /* extent */, nullptr /* overhangs */);
+ minikin::MinikinPaint minikinPaint = prepareMinikinPaint(paint, typeface);
+ const Typeface* resolvedTypeface = Typeface::resolveDefault(typeface);
+ return minikin::Layout::measureText(buf, start, count, bufSize, bidiFlags, minikinPaint,
+ resolvedTypeface->fFontCollection, advances,
+ nullptr /* extent */, nullptr /* overhangs */);
}
bool MinikinUtils::hasVariationSelector(const Typeface* typeface, uint32_t codepoint, uint32_t vs) {
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1536b64..b132160 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -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>
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
index 3eccccd..e117969 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java
@@ -71,10 +71,12 @@
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 @@
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(
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index 1e69fc5..87d11b2 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -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 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 @@
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 @@
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);
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index ebb5a62..917e651 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -32,9 +32,10 @@
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 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.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 @@
}
}
- // 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) {
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index b9ae654..b214d21 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -345,15 +345,14 @@
*out << "# Referenced at " << location.source << "\n";
}
if (keep_set.conditional_keep_rules_ && can_be_conditional) {
- *out << "-keep class " << entry.first << " {\n ifused class **.R$layout {\n";
+ *out << "-if class **.R$layout {\n";
for (const UsageLocation& location : locations) {
auto transformed_name = JavaClassGenerator::TransformToFieldName(location.name.entry);
- *out << " int " << transformed_name << ";\n";
+ *out << " int " << transformed_name << ";\n";
}
- *out << " };\n <init>(...);\n}\n" << std::endl;
- } else {
- *out << "-keep class " << entry.first << " { <init>(...); }\n" << std::endl;
+ *out << "}\n";
}
+ *out << "-keep class " << entry.first << " { <init>(...); }\n" << std::endl;
}
for (const auto& entry : keep_set.method_set_) {
diff --git a/tools/aapt2/java/ProguardRules_test.cpp b/tools/aapt2/java/ProguardRules_test.cpp
index df3ac8b..802c56a 100644
--- a/tools/aapt2/java/ProguardRules_test.cpp
+++ b/tools/aapt2/java/ProguardRules_test.cpp
@@ -130,7 +130,7 @@
ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
std::string actual = out.str();
- EXPECT_THAT(actual, HasSubstr("ifused class **.R$layout"));
+ EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
EXPECT_THAT(actual, HasSubstr("int foo"));
EXPECT_THAT(actual, HasSubstr("int bar"));
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
@@ -152,7 +152,7 @@
ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
std::string actual = out.str();
- EXPECT_THAT(actual, HasSubstr("ifused class **.R$layout"));
+ EXPECT_THAT(actual, HasSubstr("-if class **.R$layout"));
EXPECT_THAT(actual, HasSubstr("int foo"));
EXPECT_THAT(actual, HasSubstr("int bar"));
EXPECT_THAT(actual, HasSubstr("com.foo.Bar"));
@@ -174,7 +174,7 @@
ASSERT_TRUE(proguard::WriteKeepSet(&out, set));
std::string actual = out.str();
- EXPECT_THAT(actual, Not(HasSubstr("ifused")));
+ EXPECT_THAT(actual, Not(HasSubstr("-if")));
}
TEST(ProguardRulesTest, ViewOnClickRuleIsEmitted) {