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

Commit 36af3442 authored by Neill Kapron's avatar Neill Kapron Committed by Android (Google) Code Review
Browse files

Merge "[AOA FFS Implementation] Verify FFS directory for AOA" into main

parents 2da21f70 cadcdcdf
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -60,6 +60,9 @@ interface IUsbManager
    /* Returns the max packet size of the USB accessory.*/
    int getMaxPacketSize(in UsbAccessory accessory);

    /* Returns true if accessory FFS is enabled. */
    boolean isAccessoryFfsEnabled();

    /* Sets the default package for a USB device
     * (or clears it if the package name is null)
     */
+29 −8
Original line number Diff line number Diff line
@@ -950,11 +950,21 @@ public class UsbManager {

        private final ParcelFileDescriptor mPfd;
        private final UsbAccessory mAccessory;
        private final boolean mIsAccessoryFfsEnabled;

        AccessoryAutoCloseInputStream(
                UsbAccessory accessory, ParcelFileDescriptor pfd, boolean isAccessoryFfsEnabled) {
            super(pfd.getFileDescriptor());
            this.mAccessory = accessory;
            this.mPfd = pfd;
            this.mIsAccessoryFfsEnabled = isAccessoryFfsEnabled;
        }

        AccessoryAutoCloseInputStream(UsbAccessory accessory, ParcelFileDescriptor pfd) {
            super(pfd.getFileDescriptor());
            this.mAccessory = accessory;
            this.mPfd = pfd;
            this.mIsAccessoryFfsEnabled = false;
        }

        @Override
@@ -962,7 +972,7 @@ public class UsbManager {
            /* TODO(b/377850642) : Ensure the stream is closed even if client does not
            explicitly close the stream to avoid corrupt FDs*/
            super.close();
            if (!android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            if (!mIsAccessoryFfsEnabled) {
                closeHandleForAccessory(mAccessory, true);
            }
        }
@@ -977,13 +987,18 @@ public class UsbManager {
        private final UsbAccessory mAccessory;
        private final int mMaxPacketSize;
        private final ParcelFileDescriptor mPfd;
        private final boolean mIsAccessoryFfsEnabled;

        AccessoryAutoCloseOutputStream(
                UsbAccessory accessory, ParcelFileDescriptor pfd, int maxPacketSize) {
                UsbAccessory accessory,
                ParcelFileDescriptor pfd,
                int maxPacketSize,
                boolean isAccessoryFfsEnabled) {
            super(pfd.getFileDescriptor());
            mMaxPacketSize = maxPacketSize;
            mAccessory = accessory;
            mPfd = pfd;
            mIsAccessoryFfsEnabled = isAccessoryFfsEnabled;
        }

        AccessoryAutoCloseOutputStream(UsbAccessory accessory, ParcelFileDescriptor pfd) {
@@ -991,13 +1006,14 @@ public class UsbManager {
            mMaxPacketSize = -1;
            mAccessory = accessory;
            mPfd = pfd;
            mIsAccessoryFfsEnabled = false;
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            super.write(b, off, len);

            if (!android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            if (!mIsAccessoryFfsEnabled) {
                return;
            }
            // Check if a ZLP is needed for this specific write operation
@@ -1011,7 +1027,7 @@ public class UsbManager {
            /* TODO(b/377850642) : Ensure the stream is closed even if client does not
            explicitly close the stream to avoid corrupt FDs*/
            super.close();
            if (!android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            if (!mIsAccessoryFfsEnabled) {
                closeHandleForAccessory(mAccessory, false);
            }
        }
@@ -1197,9 +1213,12 @@ public class UsbManager {
    @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
    public @NonNull InputStream openAccessoryInputStream(@NonNull UsbAccessory accessory) {
        try {
            if (android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            boolean isAccessoryFfsEnabled = mService.isAccessoryFfsEnabled();
            if (isAccessoryFfsEnabled) {
                return new AccessoryAutoCloseInputStream(
                        accessory, mService.openAccessoryForInputStream(accessory));
                        accessory,
                        mService.openAccessoryForInputStream(accessory),
                        isAccessoryFfsEnabled);
            }
            return new AccessoryAutoCloseInputStream(
                    accessory, openHandleForAccessory(accessory, true).getPfd());
@@ -1221,11 +1240,13 @@ public class UsbManager {
    @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
    public @NonNull OutputStream openAccessoryOutputStream(@NonNull UsbAccessory accessory) {
        try {
            if (android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
            boolean isAccessoryFfsEnabled = mService.isAccessoryFfsEnabled();
            if (isAccessoryFfsEnabled) {
                return new AccessoryAutoCloseOutputStream(
                        accessory,
                        mService.openAccessoryForOutputStream(accessory),
                        mService.getMaxPacketSize(accessory));
                        mService.getMaxPacketSize(accessory),
                        isAccessoryFfsEnabled);
            }
            return new AccessoryAutoCloseOutputStream(accessory,
                    openHandleForAccessory(accessory, false).getPfd());
+61 −1
Original line number Diff line number Diff line
@@ -21,6 +21,9 @@
#include <asyncio/AsyncIO.h>
#include <core_jni_helpers.h>
#include <fcntl.h>
#include <fstream>
#include <linux/aio_abi.h>

#include <linux/uhid.h>
#include <linux/usb/f_accessory.h>
#include <nativehelper/JNIPlatformHelp.h>
@@ -33,7 +36,6 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <map>
#include <thread>

@@ -1504,6 +1506,62 @@ static jboolean android_server_UsbDeviceManager_openAccessoryControl(JNIEnv * /*
    return JNI_TRUE;
}

// Function to check if a given path is a functionfs mount point
bool is_path_mounted_as_functionfs(std::string path) {

    std::ifstream mounts_file("/proc/mounts");
    if (!mounts_file.is_open()) {
        ALOGE("Could not open /proc/mounts");
        return false;
    }

    std::string line;
    while (std::getline(mounts_file, line)) {
        std::stringstream ss(line);
        std::string device, mount_point, fs_type;

        ss >> device >> mount_point >> fs_type;

        if (mount_point == path && fs_type == "functionfs") {
            return true;
        }
    }

    return false;
}

std::string get_parent_directory(std::string path) {
    std::string parent_dir = path;
    size_t pos = path.find_last_of('/');
    if (pos != std::string::npos) {
        parent_dir = path.substr(0, pos);
    }
    return parent_dir;
}

static jboolean android_server_UsbDeviceManager_checkAccessoryFfsDirectories(JNIEnv * /* env */,
                                                                             jobject /* thiz */) {
    if (access(FFS_VENDOR_CTRL_REQUEST_EP0, F_OK) != 0) {
        ALOGE("Cannot access %s", FFS_VENDOR_CTRL_REQUEST_EP0);
        return JNI_FALSE;
    }

    if (!is_path_mounted_as_functionfs(get_parent_directory(FFS_VENDOR_CTRL_REQUEST_EP0))) {
        return JNI_FALSE;
    }

    if (access(FFS_ACCESSORY_EP0, F_OK) != 0) {
        ALOGE("Cannot access %s", FFS_ACCESSORY_EP0);
        return JNI_FALSE;
    }

    if (!is_path_mounted_as_functionfs(get_parent_directory(FFS_ACCESSORY_EP0))) {
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

static jstring android_server_UsbDeviceManager_waitAndGetProperty(JNIEnv *env, jobject thiz,
                                                                  jstring jPropName) {
    ScopedUtfChars propName(env, jPropName);
@@ -1527,6 +1585,8 @@ static const JNINativeMethod method_table[] = {
         (void *)android_server_UsbDeviceManager_openAccessoryForInputStream},
        {"nativeOpenAccessoryForOutputStream", "()Landroid/os/ParcelFileDescriptor;",
         (void *)android_server_UsbDeviceManager_openAccessoryForOutputStream},
        {"nativeCheckAccessoryFfsDirectories", "()Z",
         (void *)android_server_UsbDeviceManager_checkAccessoryFfsDirectories},
        {"nativeIsStartRequested", "()Z", (void *)android_server_UsbDeviceManager_isStartRequested},
        {"nativeOpenControl", "(Ljava/lang/String;)Ljava/io/FileDescriptor;",
         (void *)android_server_UsbDeviceManager_openControl},
+19 −4
Original line number Diff line number Diff line
@@ -241,6 +241,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
    private final boolean mEnableUdcSysfsUsbStateUpdate;
    private String mUdcName = "";

    private boolean mEnableAoaUserspaceImplementation = false;

    /**
     * Counter for tracking UsbOperation operations.
     */
@@ -361,7 +363,12 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
        }
        mControlFds.put(UsbManager.FUNCTION_PTP, ptpFd);

        if (android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
      // TODO: b/440091110 - Add check for device property.
        mEnableAoaUserspaceImplementation =
                android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()
                        && nativeCheckAccessoryFfsDirectories();

        if (mEnableAoaUserspaceImplementation) {
            if (!nativeOpenAccessoryControl()) {
                Slog.e(TAG, "Failed to open control for accessory");
            }
@@ -476,9 +483,10 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
            mUEventObserver.startObserving(USB_STATE_MATCH);
        }

        if (android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
        if (mEnableAoaUserspaceImplementation) {
            nativeStartVendorControlRequestMonitor();
        }

        sEventLogger = new EventLogger(DUMPSYS_LOG_BUFFER, "UsbDeviceManager activity");
    }

@@ -541,7 +549,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser

        int operationId = sUsbOperationCount.incrementAndGet();

        if (android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
        if (mEnableAoaUserspaceImplementation) {
            mAccessoryStrings = nativeGetAccessoryStringsFromFfs();
        } else {
            mAccessoryStrings = nativeGetAccessoryStrings();
@@ -2667,6 +2675,10 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
        return nativeGetMaxPacketSize();
    }

    public boolean isAccessoryFfsEnabled() {
        return mEnableAoaUserspaceImplementation;
    }

    public long getCurrentFunctions() {
        return mHandler.getEnabledFunctions();
    }
@@ -2802,7 +2814,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
    /** Update accessory control state (Called by native code). */
    @Keep
    private void updateAccessoryState(String state) {
        if (!android.hardware.usb.flags.Flags.enableAoaUserspaceImplementation()) {
        if (!mEnableAoaUserspaceImplementation) {
            Slog.w(TAG, "Accessory state update from userspace is not supported!");
            return;
        }
@@ -2850,4 +2862,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
    private native boolean nativeStartVendorControlRequestMonitor();

    private native boolean nativeOpenAccessoryControl();

    private native boolean nativeCheckAccessoryFfsDirectories();

}
+16 −0
Original line number Diff line number Diff line
@@ -533,6 +533,22 @@ public class UsbService extends IUsbManager.Stub {
        }
    }

    /* Checks if accessory FFS is enabled */
    @Override
    public boolean isAccessoryFfsEnabled() {
        Preconditions.checkNotNull(mDeviceManager, "DeviceManager must not be null");

        final long ident = clearCallingIdentity();
        try {
            synchronized (mLock) {
                return mDeviceManager.isAccessoryFfsEnabled();
            }

        } finally {
            restoreCallingIdentity(ident);
        }
    }

    @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_MTP)
    /* Returns a dup of the control file descriptor for the given function. */
    @Override