Require permission to read USB device's serial number.
Fixes: 110953952
Test: CtsVerifier USB Device test
Change-Id: I99b52bac6c800d869198e282e364f3a530336803
diff --git a/Android.bp b/Android.bp
index 2ab91a1..bfd961e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -194,6 +194,7 @@
"core/java/android/hardware/radio/ITunerCallback.aidl",
"core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl",
"core/java/android/hardware/usb/IUsbManager.aidl",
+ "core/java/android/hardware/usb/IUsbSerialReader.aidl",
"core/java/android/net/ICaptivePortal.aidl",
"core/java/android/net/IConnectivityManager.aidl",
"core/java/android/net/IIpConnectivityMetrics.aidl",
diff --git a/core/java/android/hardware/usb/IUsbSerialReader.aidl b/core/java/android/hardware/usb/IUsbSerialReader.aidl
new file mode 100644
index 0000000..787d5cd
--- /dev/null
+++ b/core/java/android/hardware/usb/IUsbSerialReader.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2018 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;
+
+/** @hide */
+interface IUsbSerialReader
+{
+ /* Returns a serial for the accessory/device */
+ String getSerial(String packageName);
+}
diff --git a/core/java/android/hardware/usb/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java
index 4aeb40c..b418d43 100644
--- a/core/java/android/hardware/usb/UsbAccessory.java
+++ b/core/java/android/hardware/usb/UsbAccessory.java
@@ -18,8 +18,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityThread;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
+
import com.android.internal.util.Preconditions;
/**
@@ -54,7 +57,7 @@
private final @Nullable String mDescription;
private final @Nullable String mVersion;
private final @Nullable String mUri;
- private final @Nullable String mSerial;
+ private final @NonNull IUsbSerialReader mSerialNumberReader;
/** @hide */
public static final int MANUFACTURER_STRING = 0;
@@ -75,22 +78,38 @@
*/
public UsbAccessory(@NonNull String manufacturer, @NonNull String model,
@Nullable String description, @Nullable String version, @Nullable String uri,
- @Nullable String serial) {
+ @NonNull IUsbSerialReader serialNumberReader) {
mManufacturer = Preconditions.checkNotNull(manufacturer);
mModel = Preconditions.checkNotNull(model);
mDescription = description;
mVersion = version;
mUri = uri;
- mSerial = serial;
+ mSerialNumberReader = serialNumberReader;
+
+ // Make sure the binder belongs to the system
+ if (ActivityThread.isSystem()) {
+ Preconditions.checkArgument(mSerialNumberReader instanceof IUsbSerialReader.Stub);
+ }
}
/**
- * UsbAccessory should only be instantiated by UsbService implementation
+ * DO NOT USE. Only for backwards compatibility with
+ * {@link com.android.future.usb.UsbAccessory}.
+ *
* @hide
+ * @deprecated use {@link UsbAccessory#UsbAccessory(String, String, String, String, String,
+ * IUsbSerialReader) instead}
*/
- public UsbAccessory(String[] strings) {
- this(strings[MANUFACTURER_STRING], strings[MODEL_STRING], strings[DESCRIPTION_STRING],
- strings[VERSION_STRING], strings[URI_STRING], strings[SERIAL_STRING]);
+ @Deprecated
+ public UsbAccessory(@NonNull String manufacturer, @NonNull String model,
+ @Nullable String description, @Nullable String version, @Nullable String uri,
+ @Nullable String serialNumber) {
+ this(manufacturer, model, description, version, uri, new IUsbSerialReader.Stub() {
+ @Override
+ public String getSerial(String packageName) {
+ return serialNumber;
+ }
+ });
}
/**
@@ -146,9 +165,17 @@
* between individual accessories of the same model and manufacturer
*
* @return the unique serial number, or {@code null} if not set
+ *
+ * @throws SecurityException if the app targets SDK >= {@value android.os.Build.VERSION_CODES#Q}
+ * and the app does not have permission to read from the accessory.
*/
public @Nullable String getSerial() {
- return mSerial;
+ try {
+ return mSerialNumberReader.getSerial(ActivityThread.currentPackageName());
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
}
private static boolean compare(String s1, String s2) {
@@ -165,7 +192,7 @@
compare(mDescription, accessory.getDescription()) &&
compare(mVersion, accessory.getVersion()) &&
compare(mUri, accessory.getUri()) &&
- compare(mSerial, accessory.getSerial()));
+ compare(getSerial(), accessory.getSerial()));
}
return false;
}
@@ -175,7 +202,7 @@
return mManufacturer.hashCode() ^ mModel.hashCode() ^
(mDescription == null ? 0 : mDescription.hashCode()) ^
(mVersion == null ? 0 : mVersion.hashCode()) ^
- (mUri == null ? 0 : mUri.hashCode()) ^ (mSerial == null ? 0 : mSerial.hashCode());
+ (mUri == null ? 0 : mUri.hashCode());
}
@Override
@@ -185,7 +212,7 @@
", mDescription=" + mDescription +
", mVersion=" + mVersion +
", mUri=" + mUri +
- ", mSerial=" + mSerial + "]";
+ ", mSerialNumberReader=" + mSerialNumberReader + "]";
}
public static final Parcelable.Creator<UsbAccessory> CREATOR =
@@ -196,8 +223,11 @@
String description = in.readString();
String version = in.readString();
String uri = in.readString();
- String serial = in.readString();
- return new UsbAccessory(manufacturer, model, description, version, uri, serial);
+ IUsbSerialReader serialNumberReader = IUsbSerialReader.Stub.asInterface(
+ in.readStrongBinder());
+
+ return new UsbAccessory(manufacturer, model, description, version, uri,
+ serialNumberReader);
}
public UsbAccessory[] newArray(int size) {
@@ -215,6 +245,6 @@
parcel.writeString(mDescription);
parcel.writeString(mVersion);
parcel.writeString(mUri);
- parcel.writeString(mSerial);
+ parcel.writeStrongBinder(mSerialNumberReader.asBinder());
}
}
diff --git a/core/java/android/hardware/usb/UsbDevice.java b/core/java/android/hardware/usb/UsbDevice.java
index 26c5a95..b08212c 100644
--- a/core/java/android/hardware/usb/UsbDevice.java
+++ b/core/java/android/hardware/usb/UsbDevice.java
@@ -19,8 +19,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
+import android.app.ActivityThread;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
+
import com.android.internal.util.Preconditions;
/**
@@ -50,27 +53,27 @@
private final @Nullable String mManufacturerName;
private final @Nullable String mProductName;
private final @NonNull String mVersion;
- private final @Nullable String mSerialNumber;
+ private final @NonNull UsbConfiguration[] mConfigurations;
+ private final @NonNull IUsbSerialReader mSerialNumberReader;
private final int mVendorId;
private final int mProductId;
private final int mClass;
private final int mSubclass;
private final int mProtocol;
- /** All configurations for this device, only null during creation */
- private @Nullable Parcelable[] mConfigurations;
-
/** All interfaces on the device. Initialized on first call to getInterfaceList */
@UnsupportedAppUsage
private @Nullable UsbInterface[] mInterfaces;
/**
- * UsbDevice should only be instantiated by UsbService implementation
+ * Create a new UsbDevice object. Only called by {@link Builder#build(IUsbSerialReader)}
+ *
* @hide
*/
- public UsbDevice(@NonNull String name, int vendorId, int productId, int Class, int subClass,
+ private UsbDevice(@NonNull String name, int vendorId, int productId, int Class, int subClass,
int protocol, @Nullable String manufacturerName, @Nullable String productName,
- @NonNull String version, @Nullable String serialNumber) {
+ @NonNull String version, @NonNull UsbConfiguration[] configurations,
+ @NonNull IUsbSerialReader serialNumberReader) {
mName = Preconditions.checkNotNull(name);
mVendorId = vendorId;
mProductId = productId;
@@ -80,7 +83,13 @@
mManufacturerName = manufacturerName;
mProductName = productName;
mVersion = Preconditions.checkStringNotEmpty(version);
- mSerialNumber = serialNumber;
+ mConfigurations = Preconditions.checkArrayElementsNotNull(configurations, "configurations");
+ mSerialNumberReader = Preconditions.checkNotNull(serialNumberReader);
+
+ // Make sure the binder belongs to the system
+ if (ActivityThread.isSystem()) {
+ Preconditions.checkArgument(mSerialNumberReader instanceof IUsbSerialReader.Stub);
+ }
}
/**
@@ -125,9 +134,17 @@
* Returns the serial number of the device.
*
* @return the serial number name, or {@code null} if the property could not be read
+ *
+ * @throws SecurityException if the app targets SDK >= {@value android.os.Build.VERSION_CODES#Q}
+ * and the app does not have permission to read from the device.
*/
public @Nullable String getSerialNumber() {
- return mSerialNumber;
+ try {
+ return mSerialNumberReader.getSerial(ActivityThread.currentPackageName());
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
}
/**
@@ -203,7 +220,7 @@
* @return the configuration
*/
public @NonNull UsbConfiguration getConfiguration(int index) {
- return (UsbConfiguration)mConfigurations[index];
+ return mConfigurations[index];
}
private @Nullable UsbInterface[] getInterfaceList() {
@@ -211,14 +228,14 @@
int configurationCount = mConfigurations.length;
int interfaceCount = 0;
for (int i = 0; i < configurationCount; i++) {
- UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
+ UsbConfiguration configuration = mConfigurations[i];
interfaceCount += configuration.getInterfaceCount();
}
mInterfaces = new UsbInterface[interfaceCount];
int offset = 0;
for (int i = 0; i < configurationCount; i++) {
- UsbConfiguration configuration = (UsbConfiguration)mConfigurations[i];
+ UsbConfiguration configuration = mConfigurations[i];
interfaceCount = configuration.getInterfaceCount();
for (int j = 0; j < interfaceCount; j++) {
mInterfaces[offset++] = configuration.getInterface(j);
@@ -251,14 +268,6 @@
return getInterfaceList()[index];
}
- /**
- * Only used by UsbService implementation
- * @hide
- */
- public void setConfigurations(@NonNull Parcelable[] configuration) {
- mConfigurations = Preconditions.checkArrayElementsNotNull(configuration, "configuration");
- }
-
@Override
public boolean equals(Object o) {
if (o instanceof UsbDevice) {
@@ -281,7 +290,8 @@
",mVendorId=" + mVendorId + ",mProductId=" + mProductId +
",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName +
- ",mVersion=" + mVersion + ",mSerialNumber=" + mSerialNumber + ",mConfigurations=[");
+ ",mVersion=" + mVersion + ",mSerialNumberReader=" + mSerialNumberReader
+ + ",mConfigurations=[");
for (int i = 0; i < mConfigurations.length; i++) {
builder.append("\n");
builder.append(mConfigurations[i].toString());
@@ -302,11 +312,13 @@
String manufacturerName = in.readString();
String productName = in.readString();
String version = in.readString();
- String serialNumber = in.readString();
- Parcelable[] configurations = in.readParcelableArray(UsbInterface.class.getClassLoader());
+ IUsbSerialReader serialNumberReader =
+ IUsbSerialReader.Stub.asInterface(in.readStrongBinder());
+ UsbConfiguration[] configurations = in.readParcelableArray(
+ UsbConfiguration.class.getClassLoader(), UsbConfiguration.class);
UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
- manufacturerName, productName, version, serialNumber);
- device.setConfigurations(configurations);
+ manufacturerName, productName, version, configurations,
+ serialNumberReader);
return device;
}
@@ -329,7 +341,7 @@
parcel.writeString(mManufacturerName);
parcel.writeString(mProductName);
parcel.writeString(mVersion);
- parcel.writeString(mSerialNumber);
+ parcel.writeStrongBinder(mSerialNumberReader.asBinder());
parcel.writeParcelableArray(mConfigurations, 0);
}
@@ -343,4 +355,53 @@
private static native int native_get_device_id(String name);
private static native String native_get_device_name(int id);
+
+ /**
+ * @hide
+ */
+ public static class Builder {
+ private final @NonNull String mName;
+ private final int mVendorId;
+ private final int mProductId;
+ private final int mClass;
+ private final int mSubclass;
+ private final int mProtocol;
+ private final @Nullable String mManufacturerName;
+ private final @Nullable String mProductName;
+ private final @NonNull String mVersion;
+ private final @NonNull UsbConfiguration[] mConfigurations;
+
+ // Temporary storage for serial number. Serial number reader need to be wrapped in a
+ // IUsbSerialReader as they might be used as PII.
+ public final @Nullable String serialNumber;
+
+ public Builder(@NonNull String name, int vendorId, int productId, int Class, int subClass,
+ int protocol, @Nullable String manufacturerName, @Nullable String productName,
+ @NonNull String version, @NonNull UsbConfiguration[] configurations,
+ @Nullable String serialNumber) {
+ mName = Preconditions.checkNotNull(name);
+ mVendorId = vendorId;
+ mProductId = productId;
+ mClass = Class;
+ mSubclass = subClass;
+ mProtocol = protocol;
+ mManufacturerName = manufacturerName;
+ mProductName = productName;
+ mVersion = Preconditions.checkStringNotEmpty(version);
+ mConfigurations = configurations;
+ this.serialNumber = serialNumber;
+ }
+
+ /**
+ * Create a new {@link UsbDevice}
+ *
+ * @param serialReader The method to read the serial number.
+ *
+ * @return The usb device
+ */
+ public UsbDevice build(@NonNull IUsbSerialReader serialReader) {
+ return new UsbDevice(mName, mVendorId, mProductId, mClass, mSubclass, mProtocol,
+ mManufacturerName, mProductName, mVersion, mConfigurations, serialReader);
+ }
+ }
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 57f1668..bd3e745 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -20,8 +20,6 @@
import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
import android.app.ActivityManager;
-
-import com.android.server.wm.ActivityTaskManagerInternal;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -52,6 +50,7 @@
import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification;
import android.os.BatteryManager;
+import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
@@ -82,6 +81,7 @@
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.File;
import java.io.FileDescriptor;
@@ -658,7 +658,19 @@
// successfully entered accessory mode
String[] accessoryStrings = mUsbDeviceManager.getAccessoryStrings();
if (accessoryStrings != null) {
- mCurrentAccessory = new UsbAccessory(accessoryStrings);
+ UsbSerialReader serialReader = new UsbSerialReader(mContext, mSettingsManager,
+ accessoryStrings[UsbAccessory.SERIAL_STRING]);
+
+ mCurrentAccessory = new UsbAccessory(
+ accessoryStrings[UsbAccessory.MANUFACTURER_STRING],
+ accessoryStrings[UsbAccessory.MODEL_STRING],
+ accessoryStrings[UsbAccessory.DESCRIPTION_STRING],
+ accessoryStrings[UsbAccessory.VERSION_STRING],
+ accessoryStrings[UsbAccessory.URI_STRING],
+ serialReader);
+
+ serialReader.setDevice(mCurrentAccessory);
+
Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory);
// defer accessoryAttached if system is not ready
if (mBootCompleted) {
@@ -1982,7 +1994,7 @@
+ currentAccessory;
throw new IllegalArgumentException(error);
}
- settings.checkPermission(accessory);
+ settings.checkPermission(accessory, Binder.getCallingUid());
return nativeOpenAccessory();
}
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 589bcdc..a4c29a6 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -370,13 +370,18 @@
return false;
}
- UsbDevice newDevice = parser.toAndroidUsbDevice();
- if (newDevice == null) {
+ UsbDevice.Builder newDeviceBuilder = parser.toAndroidUsbDevice();
+ if (newDeviceBuilder == null) {
Slog.e(TAG, "Couldn't create UsbDevice object.");
// Tracking
addConnectionRecord(deviceAddress, ConnectionRecord.CONNECT_BADDEVICE,
parser.getRawDescriptors());
} else {
+ UsbSerialReader serialNumberReader = new UsbSerialReader(mContext, mSettingsManager,
+ newDeviceBuilder.serialNumber);
+ UsbDevice newDevice = newDeviceBuilder.build(serialNumberReader);
+ serialNumberReader.setDevice(newDevice);
+
mDevices.put(deviceAddress, newDevice);
Slog.d(TAG, "Added device " + newDevice);
diff --git a/services/usb/java/com/android/server/usb/UsbPermissionManager.java b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
index 2c9ee36..dd2f29b 100644
--- a/services/usb/java/com/android/server/usb/UsbPermissionManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
@@ -148,11 +148,11 @@
* Returns true if caller has permission to access the accessory.
*
* @param accessory to check permission for
+ * @param uid to check permission for
* @return {@code true} if caller has permssion
*/
- boolean hasPermission(@NonNull UsbAccessory accessory) {
+ boolean hasPermission(@NonNull UsbAccessory accessory, int uid) {
synchronized (mLock) {
- int uid = Binder.getCallingUid();
if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
return true;
}
diff --git a/services/usb/java/com/android/server/usb/UsbSerialReader.java b/services/usb/java/com/android/server/usb/UsbSerialReader.java
new file mode 100644
index 0000000..5bf94af
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbSerialReader.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.hardware.usb.IUsbSerialReader;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.os.Binder;
+import android.os.Build;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+
+import com.android.internal.util.ArrayUtils;
+
+/**
+ * Allows an app to read the serial number of the {@link UsbDevice}/{@link UsbAccessory} only if
+ * the app has got the permission to do so.
+ */
+class UsbSerialReader extends IUsbSerialReader.Stub {
+ private final @Nullable String mSerialNumber;
+ private final @NonNull Context mContext;
+ private final @NonNull UsbSettingsManager mSettingsManager;
+
+ private Object mDevice;
+
+ /**
+ * Create an new {@link UsbSerialReader}. It is mandatory to call {@link #setDevice(Object)}
+ * immediately after this.
+ *
+ * @param context A context to be used by the reader
+ * @param settingsManager The USB settings manager
+ * @param serialNumber The serial number that might be read
+ */
+ UsbSerialReader(@NonNull Context context, @NonNull UsbSettingsManager settingsManager,
+ @Nullable String serialNumber) {
+ mContext = context;
+ mSettingsManager = settingsManager;
+ mSerialNumber = serialNumber;
+ }
+
+ /**
+ * Set the {@link UsbDevice}/{@link UsbAccessory} the serial number belongs to
+ *
+ * @param device The device/accessory
+ */
+ public void setDevice(@NonNull Object device) {
+ mDevice = device;
+ }
+
+ @Override
+ public String getSerial(String packageName) throws RemoteException {
+ int pid = Binder.getCallingPid();
+ int uid = Binder.getCallingUid();
+
+ if (uid != Process.SYSTEM_UID) {
+ enforcePackageBelongsToUid(uid, packageName);
+
+ PackageInfo pkg;
+ try {
+ pkg = mContext.getPackageManager().getPackageInfo(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RemoteException("package " + packageName + " cannot be found");
+ }
+
+ if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
+ if (mContext.checkPermission(android.Manifest.permission.MANAGE_USB, pid, uid)
+ == PackageManager.PERMISSION_DENIED) {
+ UsbUserSettingsManager settings = mSettingsManager.getSettingsForUser(
+ UserHandle.getUserId(uid));
+
+ if (mDevice instanceof UsbDevice) {
+ settings.checkPermission((UsbDevice) mDevice, packageName, uid);
+ } else {
+ settings.checkPermission((UsbAccessory) mDevice, uid);
+ }
+ }
+ }
+ }
+
+ return mSerialNumber;
+ }
+
+ private void enforcePackageBelongsToUid(int uid, @NonNull String packageName) {
+ String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
+
+ if (!ArrayUtils.contains(packages, packageName)) {
+ throw new IllegalArgumentException(packageName + " does to belong to the " + uid);
+ }
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index e92bd74..4be70af 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -318,8 +318,13 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
UserHandle user = UserHandle.of(userId);
- mSettingsManager.getSettingsForProfileGroup(user).setDevicePackage(device, packageName,
- user);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mSettingsManager.getSettingsForProfileGroup(user).setDevicePackage(device, packageName,
+ user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
@@ -329,49 +334,93 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
UserHandle user = UserHandle.of(userId);
- mSettingsManager.getSettingsForProfileGroup(user).setAccessoryPackage(accessory,
- packageName, user);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mSettingsManager.getSettingsForProfileGroup(user).setAccessoryPackage(accessory,
+ packageName, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public boolean hasDevicePermission(UsbDevice device, String packageName) {
- final int userId = UserHandle.getCallingUserId();
- return getSettingsForUser(userId).hasPermission(device, packageName,
- Binder.getCallingUid());
+ final int uid = Binder.getCallingUid();
+ final int userId = UserHandle.getUserId(uid);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getSettingsForUser(userId).hasPermission(device, packageName, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public boolean hasAccessoryPermission(UsbAccessory accessory) {
- final int userId = UserHandle.getCallingUserId();
- return getSettingsForUser(userId).hasPermission(accessory);
+ final int uid = Binder.getCallingUid();
+ final int userId = UserHandle.getUserId(uid);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getSettingsForUser(userId).hasPermission(accessory, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void requestDevicePermission(UsbDevice device, String packageName, PendingIntent pi) {
- final int userId = UserHandle.getCallingUserId();
- getSettingsForUser(userId).requestPermission(device, packageName, pi,
- Binder.getCallingUid());
+ final int uid = Binder.getCallingUid();
+ final int userId = UserHandle.getUserId(uid);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ getSettingsForUser(userId).requestPermission(device, packageName, pi, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void requestAccessoryPermission(
UsbAccessory accessory, String packageName, PendingIntent pi) {
- final int userId = UserHandle.getCallingUserId();
- getSettingsForUser(userId).requestPermission(accessory, packageName, pi);
+ final int uid = Binder.getCallingUid();
+ final int userId = UserHandle.getUserId(uid);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ getSettingsForUser(userId).requestPermission(accessory, packageName, pi, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void grantDevicePermission(UsbDevice device, int uid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
final int userId = UserHandle.getUserId(uid);
- getSettingsForUser(userId).grantDevicePermission(device, uid);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ getSettingsForUser(userId).grantDevicePermission(device, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
final int userId = UserHandle.getUserId(uid);
- getSettingsForUser(userId).grantAccessoryPermission(accessory, uid);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ getSettingsForUser(userId).grantAccessoryPermission(accessory, uid);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
@@ -381,7 +430,13 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
UserHandle user = UserHandle.of(userId);
- return mSettingsManager.getSettingsForProfileGroup(user).hasDefaults(packageName, user);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mSettingsManager.getSettingsForProfileGroup(user).hasDefaults(packageName, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
@@ -391,7 +446,13 @@
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
UserHandle user = UserHandle.of(userId);
- mSettingsManager.getSettingsForProfileGroup(user).clearDefaults(packageName, user);
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mSettingsManager.getSettingsForProfileGroup(user).clearDefaults(packageName, user);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
@Override
diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
index fe93399..0121d30 100644
--- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
@@ -168,19 +168,21 @@
return mUsbPermissionManager.hasPermission(device, uid);
}
- public boolean hasPermission(UsbAccessory accessory) {
- return mUsbPermissionManager.hasPermission(accessory);
+ public boolean hasPermission(UsbAccessory accessory, int uid) {
+ return mUsbPermissionManager.hasPermission(accessory, uid);
}
public void checkPermission(UsbDevice device, String packageName, int uid) {
if (!hasPermission(device, packageName, uid)) {
- throw new SecurityException("User has not given permission to device " + device);
+ throw new SecurityException("User has not given " + uid + "/" + packageName
+ + " permission to access device " + device.getDeviceName());
}
}
- public void checkPermission(UsbAccessory accessory) {
- if (!hasPermission(accessory)) {
- throw new SecurityException("User has not given permission to accessory " + accessory);
+ public void checkPermission(UsbAccessory accessory, int uid) {
+ if (!hasPermission(accessory, uid)) {
+ throw new SecurityException("User has not given " + uid + " permission to accessory "
+ + accessory);
}
}
@@ -236,9 +238,10 @@
requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi);
}
- public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) {
+ public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi,
+ int uid) {
// respond immediately if permission has already been granted
- if (hasPermission(accessory)) {
+ if (hasPermission(accessory, uid)) {
Intent intent = new Intent();
intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
index e615428..c021101 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -271,13 +271,13 @@
/**
* @hide
*/
- public UsbDevice toAndroidUsbDevice() {
+ public UsbDevice.Builder toAndroidUsbDevice() {
if (mDeviceDescriptor == null) {
Log.e(TAG, "toAndroidUsbDevice() ERROR - No Device Descriptor");
return null;
}
- UsbDevice device = mDeviceDescriptor.toAndroid(this);
+ UsbDevice.Builder device = mDeviceDescriptor.toAndroid(this);
if (device == null) {
Log.e(TAG, "toAndroidUsbDevice() ERROR Creating Device");
}
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
index fae594a..f50b9cb 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
@@ -135,7 +135,7 @@
/**
* @hide
*/
- public UsbDevice toAndroid(UsbDescriptorParser parser) {
+ public UsbDevice.Builder toAndroid(UsbDescriptorParser parser) {
if (DEBUG) {
Log.d(TAG, "toAndroid()");
}
@@ -152,16 +152,14 @@
Log.d(TAG, " versionString:" + versionString + " serialStr:" + serialStr);
}
- UsbDevice device = new UsbDevice(parser.getDeviceAddr(), mVendorID, mProductID,
- mDevClass, mDevSubClass,
- mProtocol, mfgName, prodName,
- versionString, serialStr);
UsbConfiguration[] configs = new UsbConfiguration[mConfigDescriptors.size()];
Log.d(TAG, " " + configs.length + " configs");
for (int index = 0; index < mConfigDescriptors.size(); index++) {
configs[index] = mConfigDescriptors.get(index).toAndroid(parser);
}
- device.setConfigurations(configs);
+ UsbDevice.Builder device = new UsbDevice.Builder(parser.getDeviceAddr(), mVendorID,
+ mProductID, mDevClass, mDevSubClass, mProtocol, mfgName, prodName, versionString,
+ configs, serialStr);
return device;
}