Write descriptors for Mtp in UsbService

The current model for setting up a functionfs
function is:

UsbDeviceManager#setCurrentFunctions() ->
intent is sent to MtpReceiver to write the descriptors ->
init/hal waits for descriptors to write, then pulls up gadget ->
Gadget is configured, a USB_STATE intent starts MtpServer

The main downside of this is a lack of reliability because
the Mtp process could be killed at any point. Normally, a
gadget is unbound if its control endpoint is closed. no_disconnect
works around this, but is still a little janky. In addition, the
extra intent delays the startup of the gadget.

With the new model, UsbDeviceManager writes the descriptors
on initialization. Since it is a system service, it won't be killed.

UsbDeviceManager#setCurrentFunctions() ->
init/hal pulls up gadget ->
Gadget is configured, a USB_STATE intent starts MtpServer
MtpServer calls UsbManager#getControlFd to get a dup of the control
endpoint.

Also modify permissions so system server can access mtp files.

Bug: 72877174
Test: Change usb configurations to ptp/mtp
Change-Id: Id17d2b5930f4e1f37ec1b4f00add9d594174ad49
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 427b9d2..89efe12 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -86,6 +86,7 @@
         "libhardware_legacy",
         "libhidlbase",
         "libkeystore_binder",
+        "libmtp",
         "libnativehelper",
         "libutils",
         "libui",
diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp
index f37f870..ff1ec04 100644
--- a/services/core/jni/com_android_server_UsbDeviceManager.cpp
+++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp
@@ -21,6 +21,7 @@
 #include <nativehelper/JNIHelp.h>
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
+#include "MtpDescriptors.h"
 
 #include <stdio.h>
 #include <asm/byteorder.h>
@@ -118,6 +119,38 @@
     return result;
 }
 
+static jobject android_server_UsbDeviceManager_openControl(JNIEnv *env, jobject /* thiz */, jstring jFunction) {
+    const char *function = env->GetStringUTFChars(jFunction, NULL);
+    bool ptp = false;
+    int fd = -1;
+    if (!strcmp(function, "ptp")) {
+        ptp = true;
+    }
+    if (!strcmp(function, "mtp") || ptp) {
+        fd = TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP0 : FFS_MTP_EP0, O_RDWR));
+        if (fd < 0) {
+            ALOGE("could not open control for %s %s", function, strerror(errno));
+            goto error;
+        }
+        if (!writeDescriptors(fd, ptp)) {
+            goto error;
+        }
+    }
+
+    if (function != NULL) {
+        env->ReleaseStringUTFChars(jFunction, function);
+    }
+    return jniCreateFileDescriptor(env, fd);
+error:
+    if (fd != -1) {
+        close(fd);
+    }
+    if (function != NULL) {
+        env->ReleaseStringUTFChars(jFunction, function);
+    }
+    return NULL;
+}
+
 static const JNINativeMethod method_table[] = {
     { "nativeGetAccessoryStrings",  "()[Ljava/lang/String;",
                                     (void*)android_server_UsbDeviceManager_getAccessoryStrings },
@@ -127,6 +160,8 @@
                                     (void*)android_server_UsbDeviceManager_isStartRequested },
     { "nativeGetAudioMode",         "()I",
                                     (void*)android_server_UsbDeviceManager_getAudioMode },
+    { "nativeOpenControl",          "(Ljava/lang/String;)Ljava/io/FileDescriptor;",
+                                    (void*)android_server_UsbDeviceManager_openControl },
 };
 
 int register_android_server_UsbDeviceManager(JNIEnv *env)