Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3cfb29e authored by Febin Thattil's avatar Febin Thattil Committed by Android (Google) Code Review
Browse files

Merge changes I55fdbac0,I79e61d77,If2b3ca4c into main

* changes:
  [AOA FFS Implementation] Fetch accessory strings from FFS
  [AOA FFS Implementation] Enable accessory mode through FunctionFS
  [AOA FFS Implementation] Update accessory mode negotiation
parents 52c79fff e6d74db1
Loading
Loading
Loading
Loading
+106 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#define USB_STATE_MAX_LEN 20
#define FFS_VENDOR_CTRL_REQUEST_EP0 "/dev/usb-ffs/ctrl/ep0"

#define FFS_ACCESSORY_EP0 "/dev/usb-ffs/aoa/ep0"

namespace {
struct func_desc {
@@ -176,7 +177,6 @@ const struct desc_v2 ctrl_desc = {
};

#define CTRL_INTERFACE_STR "Android Control Interface"

struct ctrl_functionfs_lang {
    __le16 code;
    char str1[sizeof(CTRL_INTERFACE_STR)];
@@ -201,6 +201,50 @@ const struct ctrl_functionfs_strings ctrl_strings = {
                        .str1 = CTRL_INTERFACE_STR,
                },
};

const struct desc_v2 acc_desc = {
    .header =
            {
                    .magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2),
                    .length = htole32(sizeof(acc_desc)),
                    .flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
                            FUNCTIONFS_HAS_SS_DESC,
            },
    .fs_count = 3,
    .hs_count = 3,
    .ss_count = 5,
    .fs_descs = fs_descriptors,
    .hs_descs = hs_descriptors,
    .ss_descs = ss_descriptors,
};

#define ACC_INTERFACE_STR "Android Accessory Interface"
struct acc_functionfs_lang {
    __le16 code;
    char str1[sizeof(ACC_INTERFACE_STR)];
} __attribute__((packed));

struct acc_functionfs_strings {
    struct usb_functionfs_strings_head header;
    struct acc_functionfs_lang lang0;
} __attribute__((packed));

const struct acc_functionfs_strings acc_strings = {
        .header =
                {
                        .magic = htole32(FUNCTIONFS_STRINGS_MAGIC),
                        .length = htole32(sizeof(acc_strings)),
                        .str_count = htole32(1),
                        .lang_count = htole32(1),
                },
        .lang0 =
                {
                        .code = htole16(0x0409),
                        .str1 = ACC_INTERFACE_STR,
                },
};


} // namespace

namespace android
@@ -208,6 +252,7 @@ namespace android

static JavaVM *gvm = nullptr;
static jmethodID gUpdateGadgetStateMethod;
static jmethodID gUpdateAccessoryStateMethod;

static struct parcel_file_descriptor_offsets_t
{
@@ -646,6 +691,19 @@ static void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strA
    }
}

static void set_accessory_string_from_ffs(JNIEnv *env, jobjectArray strArray, int index) {
    if (!sVendorControlRequestMonitorThread) {
        ALOGE("Vendor control request monitor thread is not running");
        return;
    }

    std::string str = sVendorControlRequestMonitorThread->getAccessoryString(index);
    if (!str.empty()) {
        jstring obj = env->NewStringUTF(str.data());
        env->SetObjectArrayElement(strArray, index, obj);
        env->DeleteLocalRef(obj);
    }
}

static jobjectArray android_server_UsbDeviceManager_getAccessoryStrings(JNIEnv *env,
                                                                        jobject /* thiz */)
@@ -670,6 +728,21 @@ out:
    return strArray;
}

static jobjectArray android_server_UsbDeviceManager_getAccessoryStringsFromFfs(JNIEnv *env,
                                                                        jobject /* thiz */)
{
    jclass stringClass = env->FindClass("java/lang/String");
    jobjectArray strArray = env->NewObjectArray(6, stringClass, NULL);
    if (!strArray) return nullptr;
    set_accessory_string_from_ffs(env, strArray, 0);
    set_accessory_string_from_ffs(env, strArray, 1);
    set_accessory_string_from_ffs(env, strArray, 2);
    set_accessory_string_from_ffs(env, strArray, 3);
    set_accessory_string_from_ffs(env, strArray, 4);
    set_accessory_string_from_ffs(env, strArray, 5);
    return strArray;
}

static jobject android_server_UsbDeviceManager_openAccessory(JNIEnv *env, jobject /* thiz */)
{
    int fd = open(DRIVER_NAME, O_RDWR);
@@ -782,6 +855,31 @@ static jboolean android_server_UsbDeviceManager_startVendorControlRequestMonitor
    return JNI_TRUE;
}

static jboolean android_server_UsbDeviceManager_openAccessoryControl(JNIEnv * /* env */,
                                                                     jobject /* thiz */) {
    ALOGI("Writing descriptors to USB Accessory...");

    int fd = TEMP_FAILURE_RETRY(open(FFS_ACCESSORY_EP0, O_RDWR));
    if (fd < 0) {
        ALOGE("Opening accessory ep0 failed: %d - %s", fd, strerror(errno));
        return JNI_FALSE;
    }
    ssize_t ret = TEMP_FAILURE_RETRY(write(fd, &acc_desc, sizeof(acc_desc)));
    if (ret < 0) {
        ALOGE("Writing accessory desc failed: %d - %s", fd, strerror(errno));
        close(fd);
        return JNI_FALSE;
    }
    ret = TEMP_FAILURE_RETRY(write(fd, &acc_strings, sizeof(acc_strings)));
    if (ret < 0) {
        ALOGE("Writing accessory strings failed: %d - %s", fd, strerror(errno));
        close(fd);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

static jstring android_server_UsbDeviceManager_waitAndGetProperty(JNIEnv *env, jobject thiz,
                                                                  jstring jPropName) {
    ScopedUtfChars propName(env, jPropName);
@@ -796,6 +894,8 @@ static jstring android_server_UsbDeviceManager_waitAndGetProperty(JNIEnv *env, j
static const JNINativeMethod method_table[] = {
        {"nativeGetAccessoryStrings", "()[Ljava/lang/String;",
         (void *)android_server_UsbDeviceManager_getAccessoryStrings},
        {"nativeGetAccessoryStringsFromFfs", "()[Ljava/lang/String;",
         (void *)android_server_UsbDeviceManager_getAccessoryStringsFromFfs},
        {"nativeOpenAccessory", "()Landroid/os/ParcelFileDescriptor;",
         (void *)android_server_UsbDeviceManager_openAccessory},
        {"nativeIsStartRequested", "()Z", (void *)android_server_UsbDeviceManager_isStartRequested},
@@ -807,6 +907,8 @@ static const JNINativeMethod method_table[] = {
         (void *)android_server_UsbDeviceManager_stopGadgetMonitor},
        {"nativeStartVendorControlRequestMonitor", "()Z",
         (void *)android_server_UsbDeviceManager_startVendorControlRequestMonitor},
        {"nativeOpenAccessoryControl", "()Z",
         (void *)android_server_UsbDeviceManager_openAccessoryControl},
        {"nativeWaitAndGetProperty", "(Ljava/lang/String;)Ljava/lang/String;",
         (void *)android_server_UsbDeviceManager_waitAndGetProperty},
};
@@ -823,6 +925,9 @@ int register_android_server_UsbDeviceManager(JavaVM *vm, JNIEnv *env) {
    gUpdateGadgetStateMethod =
            GetMethodIDOrDie(env, clazz, "updateGadgetState", "(Ljava/lang/String;)V");

    gUpdateAccessoryStateMethod =
            GetMethodIDOrDie(env, clazz, "updateAccessoryState", "(Ljava/lang/String;)V");

    clazz = env->FindClass("android/os/ParcelFileDescriptor");
    LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
    gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
+42 −1
Original line number Diff line number Diff line
@@ -361,6 +361,12 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
        }
        mControlFds.put(UsbManager.FUNCTION_PTP, ptpFd);

        if (android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            if (!nativeOpenAccessoryControl()) {
                Slog.e(TAG, "Failed to open control for accessory");
            }
        }

        if (mUsbGadgetHal == null) {
            /**
             * Initialze the legacy UsbHandler
@@ -535,7 +541,12 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser

        int operationId = sUsbOperationCount.incrementAndGet();

        if (android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            mAccessoryStrings = nativeGetAccessoryStringsFromFfs();
        } else {
            mAccessoryStrings = nativeGetAccessoryStrings();
        }

        // don't start accessory mode if our mandatory strings have not been set
        boolean enableAccessory = (mAccessoryStrings != null &&
                mAccessoryStrings[UsbAccessory.MANUFACTURER_STRING] != null &&
@@ -2728,8 +2739,36 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
        mHandler.updateState(state);
    }

    /** Update accessory control state (Called by native code). */
    @Keep
    private void updateAccessoryState(String state) {
        if (!android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            Slog.w(TAG, "Accessory state update from userspace is not supported!");
            return;
        }

        Slog.d(TAG, "Accessory state update " + state);

        if ("GETPROTOCOL".equals(state)) {
            if (DEBUG) Slog.d(TAG, "got accessory get protocol");
            mHandler.setAccessoryUEventTime(SystemClock.elapsedRealtime());
            resetAccessoryHandshakeTimeoutHandler();
        } else if ("SENDSTRING".equals(state)) {
            if (DEBUG) Slog.d(TAG, "got accessory send string");
            mHandler.sendEmptyMessage(MSG_INCREASE_SENDSTRING_COUNT);
            resetAccessoryHandshakeTimeoutHandler();
        } else if ("START".equals(state)) {
            if (DEBUG) Slog.d(TAG, "got accessory start");
            mHandler.removeMessages(MSG_ACCESSORY_HANDSHAKE_TIMEOUT);
            mHandler.setStartAccessoryTrue();
            startAccessoryMode();
        }
    }

    private native String[] nativeGetAccessoryStrings();

    private native String[] nativeGetAccessoryStringsFromFfs();

    private native ParcelFileDescriptor nativeOpenAccessory();

    private native String nativeWaitAndGetProperty(String propName);
@@ -2743,4 +2782,6 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
    private native void nativeStopGadgetMonitor();

    private native boolean nativeStartVendorControlRequestMonitor();

    private native boolean nativeOpenAccessoryControl();
}