Properly close USB device connection in Mtp device

Test: Built
Fixes: 32073045
Change-Id: I05179377532c1bd4dff1f4a4e0e837cb645317e3
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index 4e7551c..d6958b3 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -25,7 +25,9 @@
 import android.os.ParcelFileDescriptor;
 
 import android.os.UserManager;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
+import dalvik.system.CloseGuard;
 
 import java.io.IOException;
 
@@ -45,6 +47,16 @@
         System.loadLibrary("media_jni");
     }
 
+    /** Make sure that MTP device is closed properly */
+    @GuardedBy("mLock")
+    private CloseGuard mCloseGuard = CloseGuard.get();
+
+    /** Current connection to the {@link #mDevice}, or null if device is not connected */
+    @GuardedBy("mLock")
+    private UsbDeviceConnection mConnection;
+
+    private final Object mLock = new Object();
+
     /**
      * MtpClient constructor
      *
@@ -68,17 +80,25 @@
         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());
+        synchronized (mLock) {
+            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();
+            } else {
+                mConnection = connection;
+                mCloseGuard.open("close");
             }
         }
 
-        if (!result) {
-            connection.close();
-        }
         return result;
     }
 
@@ -88,13 +108,23 @@
      * with a new {@link android.hardware.usb.UsbDeviceConnection}.
      */
     public void close() {
-        native_close();
+        synchronized (mLock) {
+            if (mConnection != null) {
+                mCloseGuard.close();
+
+                native_close();
+
+                mConnection.close();
+                mConnection = null;
+            }
+        }
     }
 
     @Override
     protected void finalize() throws Throwable {
         try {
-            native_close();
+            mCloseGuard.warnIfOpen();
+            close();
         } finally {
             super.finalize();
         }
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 8bcc85f..768ac1d 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -194,6 +194,9 @@
         return JNI_FALSE;
     }
 
+    // The passed in fd is maintained by the UsbDeviceConnection
+    fd = dup(fd);
+
     MtpDevice* device = MtpDevice::open(deviceNameStr, fd);
     env->ReleaseStringUTFChars(deviceName, deviceNameStr);