Fix sideload for user devices by adding a new sideload config

Bug: 113563995
Test: Tested the 'adb sideload' command on marlin user/userdebug builds
and walleye user/userdebug builds

Change-Id: I00d565547b85f2db87012e4a08316609e03395ac
diff --git a/adb_install.cpp b/adb_install.cpp
index 97dff22..438da9f 100644
--- a/adb_install.cpp
+++ b/adb_install.cpp
@@ -26,55 +26,23 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
-#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
-#include <android-base/unique_fd.h>
 
 #include "common.h"
 #include "fuse_sideload.h"
 #include "install.h"
 #include "ui.h"
 
-static void set_usb_driver(bool enabled) {
-  // USB configfs doesn't use /s/c/a/a/enable.
-  if (android::base::GetBoolProperty("sys.usb.configfs", false)) {
-    return;
-  }
-
-  static constexpr const char* USB_DRIVER_CONTROL = "/sys/class/android_usb/android0/enable";
-  android::base::unique_fd fd(open(USB_DRIVER_CONTROL, O_WRONLY));
-  if (fd == -1) {
-    PLOG(ERROR) << "Failed to open driver control";
-    return;
-  }
-  // Not using android::base::WriteStringToFile since that will open with O_CREAT and give EPERM
-  // when USB_DRIVER_CONTROL doesn't exist. When it gives EPERM, we don't know whether that's due
-  // to non-existent USB_DRIVER_CONTROL or indeed a permission issue.
-  if (!android::base::WriteStringToFd(enabled ? "1" : "0", fd)) {
-    PLOG(ERROR) << "Failed to set driver control";
-  }
-}
-
-static void stop_adbd() {
-  ui->Print("Stopping adbd...\n");
-  android::base::SetProperty("ctl.stop", "adbd");
-  set_usb_driver(false);
-}
-
-static void maybe_restart_adbd() {
-  if (is_ro_debuggable()) {
-    ui->Print("Restarting adbd...\n");
-    set_usb_driver(true);
-    android::base::SetProperty("ctl.start", "adbd");
-  }
-}
-
 int apply_from_adb(bool* wipe_cache) {
   modified_flash = true;
-
-  stop_adbd();
-  set_usb_driver(true);
+  // Save the usb state to restore after the sideload operation.
+  std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
+  // Clean up state and stop adbd.
+  if (usb_state != "none" && !SetUsbConfig("none")) {
+    LOG(ERROR) << "Failed to clear USB config";
+    return INSTALL_ERROR;
+  }
 
   ui->Print(
       "\n\nNow send the package you want to apply\n"
@@ -86,6 +54,11 @@
     _exit(EXIT_FAILURE);
   }
 
+  if (!SetUsbConfig("sideload")) {
+    LOG(ERROR) << "Failed to set usb config to sideload";
+    return INSTALL_ERROR;
+  }
+
   // How long (in seconds) we wait for the host to start sending us a package, before timing out.
   static constexpr int ADB_INSTALL_TIMEOUT = 300;
 
@@ -136,8 +109,17 @@
     }
   }
 
-  set_usb_driver(false);
-  maybe_restart_adbd();
+  // Clean up before switching to the older state, for example setting the state
+  // to none sets sys/class/android_usb/android0/enable to 0.
+  if (!SetUsbConfig("none")) {
+    LOG(ERROR) << "Failed to clear USB config";
+  }
+
+  if (usb_state != "none") {
+    if (!SetUsbConfig(usb_state)) {
+      LOG(ERROR) << "Failed to set USB config to " << usb_state;
+    }
+  }
 
   return result;
 }
diff --git a/common.h b/common.h
index c24431b..38bdd52 100644
--- a/common.h
+++ b/common.h
@@ -44,4 +44,5 @@
 
 bool is_ro_debuggable();
 
+bool SetUsbConfig(const std::string& state);
 #endif  // RECOVERY_COMMON_H
diff --git a/etc/init.rc b/etc/init.rc
index 2adecb7..fa8fe26 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -132,11 +132,9 @@
 on property:sys.usb.config=fastboot
     start fastbootd
 
-on property:sys.usb.config=none
-    stop adbd
-    stop fastbootd
-
 on property:sys.usb.config=none && property:sys.usb.configfs=0
+    stop adbd
+    stop fastboot
     write /sys/class/android_usb/android0/enable 0
     setprop sys.usb.state ${sys.usb.config}
 
@@ -146,6 +144,12 @@
     write /sys/class/android_usb/android0/enable 1
     setprop sys.usb.state ${sys.usb.config}
 
+on property:sys.usb.config=sideload && property:sys.usb.configfs=0
+    write /sys/class/android_usb/android0/idProduct D001
+    write /sys/class/android_usb/android0/functions adb
+    write /sys/class/android_usb/android0/enable 1
+    setprop sys.usb.state ${sys.usb.config}
+
 on property:sys.usb.config=fastboot && property:sys.usb.configfs=0
     write /sys/class/android_usb/android0/idProduct 4EE0
     write /sys/class/android_usb/android0/functions fastboot
@@ -155,10 +159,19 @@
 # Configfs triggers
 on property:sys.usb.config=none && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/UDC "none"
+    stop adbd
+    stop fastbootd
     setprop sys.usb.ffs.ready 0
     rm /config/usb_gadget/g1/configs/b.1/f1
     setprop sys.usb.state ${sys.usb.config}
 
+on property:sys.usb.config=sideload && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1
+    write /config/usb_gadget/g1/idProduct 0xD001
+    write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "adb"
+    symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
+    write /config/usb_gadget/g1/UDC ${sys.usb.controller}
+    setprop sys.usb.state ${sys.usb.config}
+
 on property:sys.usb.config=adb && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1
     write /config/usb_gadget/g1/idProduct 0xD001
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "adb"
diff --git a/recovery.cpp b/recovery.cpp
index 01bd83b..5934b61 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -286,6 +286,12 @@
   return (result == 0);
 }
 
+// Sets the usb config to 'state'
+bool SetUsbConfig(const std::string& state) {
+  android::base::SetProperty("sys.usb.config", state);
+  return android::base::WaitForProperty("sys.usb.state", state);
+}
+
 // Returns the selected filename, or an empty string.
 static std::string browse_directory(const std::string& path, Device* device) {
   ensure_path_mounted(path.c_str());
diff --git a/recovery_main.cpp b/recovery_main.cpp
index 020a531..c3168fc 100644
--- a/recovery_main.cpp
+++ b/recovery_main.cpp
@@ -305,11 +305,6 @@
   }
 }
 
-static bool SetUsbConfig(const std::string& state) {
-  android::base::SetProperty("sys.usb.config", state);
-  return android::base::WaitForProperty("sys.usb.state", state);
-}
-
 int main(int argc, char** argv) {
   // We don't have logcat yet under recovery; so we'll print error on screen and log to stdout
   // (which is redirected to recovery.log) as we used to do.