Do not access MTP devices when disabled.

The USB data transfer is disabled we should not allow access MTP devices
(e.g.
usb sticks). We have two ways of accessing them: Either by mounting them
or by creating a MTPDevice in an app.

Of course an app could implement implement their own MTPDevice
implementation. In this case we cannot enforce the policy without
completely suppressing all MTP USB devices which would be too
restrictive.

Note: When the policy is set we do _not_ disconnect already connected
MTP devices

Fixes: 31472955
Change-Id: I6080c48c49657102774b2b3b4d89ff030245a266
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index c062b3a..893b954 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -16,8 +16,10 @@
 
 package android.hardware.usb;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
 import android.os.ParcelFileDescriptor;
-
 import java.io.FileDescriptor;
 
 
@@ -31,6 +33,8 @@
 
     private final UsbDevice mDevice;
 
+    private Context mContext;
+
     // used by the JNI code
     private long mNativeContext;
 
@@ -42,11 +46,22 @@
         mDevice = device;
     }
 
-    /* package */ boolean open(String name, ParcelFileDescriptor pfd) {
+    /* package */ boolean open(String name, ParcelFileDescriptor pfd,  @NonNull Context context) {
+        mContext = context.getApplicationContext();
+
         return native_open(name, pfd.getFileDescriptor());
     }
 
     /**
+     * @return The application context the connection was created for.
+     *
+     * @hide
+     */
+    public @Nullable Context getContext() {
+        return mContext;
+    }
+
+    /**
      * Releases all system resources related to the device.
      * Once the object is closed it cannot be used again.
      * The client must call {@link UsbManager#openDevice} again
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 629db06..cb2720a 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -330,7 +330,7 @@
             ParcelFileDescriptor pfd = mService.openDevice(deviceName);
             if (pfd != null) {
                 UsbDeviceConnection connection = new UsbDeviceConnection(device);
-                boolean result = connection.open(deviceName, pfd);
+                boolean result = connection.open(deviceName, pfd, mContext);
                 pfd.close();
                 if (result) {
                     return connection;
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index 4082778..e7ea1a5 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -18,11 +18,13 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.Context;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbDeviceConnection;
 import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
 
+import android.os.UserManager;
 import com.android.internal.util.Preconditions;
 
 import java.io.IOException;
@@ -62,7 +64,17 @@
      * @return true if the device was successfully opened.
      */
     public boolean open(UsbDeviceConnection connection) {
-        boolean result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor());
+        boolean result = false;
+
+        Context context = connection.getContext();
+        if (context != null) {
+            UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+
+            if (!userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
+                result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor());
+            }
+        }
+
         if (!result) {
             connection.close();
         }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 0023e4b..8430a0b 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1437,13 +1437,22 @@
      * Decide if volume is mountable per device policies.
      */
     private boolean isMountDisallowed(VolumeInfo vol) {
-        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
-            final UserManager userManager = mContext.getSystemService(UserManager.class);
-            return userManager.hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
+        UserManager userManager = mContext.getSystemService(UserManager.class);
+
+        boolean isUsbRestricted = false;
+        if (vol.disk != null && vol.disk.isUsb()) {
+            isUsbRestricted = userManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER,
                     Binder.getCallingUserHandle());
-        } else {
-            return false;
         }
+
+        boolean isTypeRestricted = false;
+        if (vol.type == VolumeInfo.TYPE_PUBLIC || vol.type == VolumeInfo.TYPE_PRIVATE) {
+            isTypeRestricted = userManager
+                    .hasUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
+                    Binder.getCallingUserHandle());
+        }
+
+        return isUsbRestricted || isTypeRestricted;
     }
 
     private void enforceAdminUser() {