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

Commit 6ea47a35 authored by Tim Kilbourn's avatar Tim Kilbourn
Browse files

Use init to write usb typec props.

The sysfs nodes are owned by root, so we must use init to write to
them.

Bug: 21615151
Change-Id: Ia8c838827ff45794aa359443117ac85764cf3772
parent 4b655fd1
Loading
Loading
Loading
Loading
+42 −12
Original line number Diff line number Diff line
@@ -26,8 +26,13 @@ import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
import android.os.UserHandle;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -89,6 +94,9 @@ public class UsbPortManager {
    private static final String PORT_DATA_ROLE_HOST = "host";
    private static final String PORT_DATA_ROLE_DEVICE = "device";

    private static final String USB_TYPEC_PROP_PREFIX = "sys.usb.typec.";
    private static final String USB_TYPEC_STATE = "sys.usb.typec.state";

    // All non-trivial role combinations.
    private static final int COMBO_SOURCE_HOST =
            UsbPort.combineRolesAsBit(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
@@ -621,16 +629,25 @@ public class UsbPortManager {
        return 0;
    }

    private static boolean fileIsRootWritable(String path) {
        try {
            // If the file is user writable, then it is root writable.
            return (Os.stat(path).st_mode & OsConstants.S_IWUSR) != 0;
        } catch (ErrnoException e) {
            return false;
        }
    }

    private static boolean canChangeMode(File portDir) {
        return new File(portDir, SYSFS_PORT_MODE).canWrite();
        return fileIsRootWritable(new File(portDir, SYSFS_PORT_MODE).getPath());
    }

    private static boolean canChangePowerRole(File portDir) {
        return new File(portDir, SYSFS_PORT_POWER_ROLE).canWrite();
        return fileIsRootWritable(new File(portDir, SYSFS_PORT_POWER_ROLE).getPath());
    }

    private static boolean canChangeDataRole(File portDir) {
        return new File(portDir, SYSFS_PORT_DATA_ROLE).canWrite();
        return fileIsRootWritable(new File(portDir, SYSFS_PORT_DATA_ROLE).getPath());
    }

    private static String readFile(File dir, String filename) {
@@ -642,16 +659,29 @@ public class UsbPortManager {
        }
    }

    private static boolean writeFile(File dir, String filename, String contents) {
        final File file = new File(dir, filename);
        try {
            try (FileWriter writer = new FileWriter(file)) {
                writer.write(contents);
    private static boolean waitForState(String property, String state) {
        // wait for the transition to complete.
        // give up after 5 seconds.
        // 5 seconds is probably too long, but we have seen hardware that takes
        // over 3 seconds to change states.
        String value = null;
        for (int i = 0; i < 100; i++) {
            // State transition is done when property is set to the new configuration
            value = SystemProperties.get(property);
            if (state.equals(value)) return true;
            SystemClock.sleep(50);
        }
            return true;
        } catch (IOException ex) {
        Slog.e(TAG, "waitForState(" + state + ") for " + property + " FAILED: got " + value);
        return false;
    }

    private static String propertyFromFilename(String filename) {
        return USB_TYPEC_PROP_PREFIX + filename;
    }

    private static boolean writeFile(File dir, String filename, String contents) {
        SystemProperties.set(propertyFromFilename(filename), contents);
        return waitForState(USB_TYPEC_STATE, contents);
    }

    private static void logAndPrint(int priority, IndentingPrintWriter pw, String msg) {