Merge cherrypicks of ['googleplex-android-review.googlesource.com/20731569'] into tm-qpr2-release.

Change-Id: If6e3d82d98b45cf835fbe9fffb4d8936e148207b
diff --git a/usb/MonitorFfs.cpp b/usb/MonitorFfs.cpp
index 717e6a7..7a5ad9d 100644
--- a/usb/MonitorFfs.cpp
+++ b/usb/MonitorFfs.cpp
@@ -26,7 +26,8 @@
 
 static volatile bool gadgetPullup;
 
-MonitorFfs::MonitorFfs(const char *const gadget)
+MonitorFfs::MonitorFfs(const char *const gadget, const char *const extconTypecState,
+                       const char *const usbGadgetState)
     : mWatchFd(),
       mEndpointList(),
       mLock(),
@@ -37,6 +38,8 @@
       mCallback(NULL),
       mPayload(NULL),
       mGadgetName(gadget),
+      mExtconTypecState(extconTypecState),
+      mUsbGadgetState(usbGadgetState),
       mMonitorRunning(false) {
     unique_fd eventFd(eventfd(0, 0));
     if (eventFd == -1) {
@@ -112,12 +115,26 @@
         ALOGE("        name = %s\n", i->name);
 }
 
+void updateState(const char *typecState, const char *usbGadgetState, std::string &typec_state,
+                 std::string &usb_gadget_state) {
+    if (ReadFileToString(typecState, &typec_state))
+        typec_state = Trim(typec_state);
+    else
+        typec_state = TYPEC_GADGET_MODE_ENABLE;
+
+    if (ReadFileToString(usbGadgetState, &usb_gadget_state))
+        usb_gadget_state = Trim(usb_gadget_state);
+    else
+        usb_gadget_state = "";
+}
+
 void *MonitorFfs::startMonitorFd(void *param) {
     MonitorFfs *monitorFfs = (MonitorFfs *)param;
     char buf[kBufferSize];
     bool writeUdc = true, stopMonitor = false;
     struct epoll_event events[kEpollEvents];
     steady_clock::time_point disconnect;
+    std::string typec_state, usb_gadget_state;
 
     bool descriptorWritten = true;
     for (int i = 0; i < static_cast<int>(monitorFfs->mEndpointList.size()); i++) {
@@ -127,8 +144,14 @@
         }
     }
 
+    updateState(monitorFfs->mExtconTypecState, monitorFfs->mUsbGadgetState, typec_state,
+                usb_gadget_state);
+
     // notify here if the endpoints are already present.
-    if (descriptorWritten) {
+    if (typec_state == TYPEC_GADGET_MODE_DISABLE && usb_gadget_state == GADGET_ACTIVATE) {
+        gadgetPullup = false;
+        ALOGI("pending GADGET pulled up due to USB disconnected");
+    } else if (descriptorWritten) {
         usleep(kPullUpDelay);
         if (!!WriteStringToFile(monitorFfs->mGadgetName, PULLUP_PATH)) {
             lock_guard<mutex> lock(monitorFfs->mLock);
@@ -172,7 +195,14 @@
                         }
                     }
 
-                    if (!descriptorPresent && !writeUdc) {
+                    updateState(monitorFfs->mExtconTypecState, monitorFfs->mUsbGadgetState,
+                                typec_state, usb_gadget_state);
+
+                    if (typec_state == TYPEC_GADGET_MODE_DISABLE &&
+                        usb_gadget_state == GADGET_ACTIVATE) {
+                        gadgetPullup = false;
+                        ALOGI("pending GADGET pulled up due to USB disconnected");
+                    } else if (!descriptorPresent && !writeUdc) {
                         if (kDebug)
                             ALOGI("endpoints not up");
                         writeUdc = true;
diff --git a/usb/include/pixelusb/UsbGadgetCommon.h b/usb/include/pixelusb/UsbGadgetCommon.h
index 964a1d6..01467e0 100644
--- a/usb/include/pixelusb/UsbGadgetCommon.h
+++ b/usb/include/pixelusb/UsbGadgetCommon.h
@@ -19,10 +19,9 @@
 
 #include <android-base/file.h>
 #include <android-base/properties.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
-
 #include <android/hardware/usb/gadget/1.0/IUsbGadget.h>
-
 #include <dirent.h>
 #include <fcntl.h>
 #include <stdio.h>
@@ -34,6 +33,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <utils/Log.h>
+
 #include <chrono>
 #include <condition_variable>
 #include <mutex>
@@ -74,9 +74,15 @@
 #define FUNCTION_NAME "function"
 #define FUNCTION_PATH CONFIG_PATH FUNCTION_NAME
 #define RNDIS_PATH FUNCTIONS_PATH "gsi.rndis"
+#define TYPEC_GADGET_MODE_DISABLE "0"
+#define TYPEC_GADGET_MODE_ENABLE "1"
+#define GADGET_DEACTIVATE "0"
+#define GADGET_ACTIVATE "1"
 
 using ::android::base::GetProperty;
+using ::android::base::ReadFileToString;
 using ::android::base::SetProperty;
+using ::android::base::Trim;
 using ::android::base::unique_fd;
 using ::android::base::WriteStringToFile;
 using ::android::hardware::usb::gadget::V1_0::GadgetFunction;
@@ -126,31 +132,35 @@
   void *mPayload;
   // Name of the USB gadget. Used for pullup.
   const char *const mGadgetName;
+  // Extcon USB state from Type-C notification.
+  const char *const mExtconTypecState;
+  // USB Gadget state from Dwc3 device.
+  const char *const mUsbGadgetState;
   // Monitor State
   bool mMonitorRunning;
 
  public:
-  MonitorFfs(const char *const gadget);
-  // Inits all the UniqueFds.
-  void reset();
-  // Starts monitoring endpoints and pullup the gadget when
-  // the descriptors are written.
-  bool startMonitor();
-  // Waits for timeout_ms for gadget pull up to happen.
-  // Returns immediately if the gadget is already pulled up.
-  bool waitForPullUp(int timeout_ms);
-  // Adds the given fd to the watch list.
-  bool addInotifyFd(string fd);
-  // Adds the given endpoint to the watch list.
-  void addEndPoint(string ep);
-  // Registers the async callback from the caller to notify the caller
-  // when the gadget pull up happens.
-  void registerFunctionsAppliedCallback(void (*callback)(bool functionsApplied,
-                                                         void *(payload)),
-                                        void *payload);
-  bool isMonitorRunning();
-  // Ep monitoring and the gadget pull up logic.
-  static void *startMonitorFd(void *param);
+   MonitorFfs(const char *const gadget, const char *const extconTypecState = "",
+              const char *const usbGadgetState = "");
+   // Inits all the UniqueFds.
+   void reset();
+   // Starts monitoring endpoints and pullup the gadget when
+   // the descriptors are written.
+   bool startMonitor();
+   // Waits for timeout_ms for gadget pull up to happen.
+   // Returns immediately if the gadget is already pulled up.
+   bool waitForPullUp(int timeout_ms);
+   // Adds the given fd to the watch list.
+   bool addInotifyFd(string fd);
+   // Adds the given endpoint to the watch list.
+   void addEndPoint(string ep);
+   // Registers the async callback from the caller to notify the caller
+   // when the gadget pull up happens.
+   void registerFunctionsAppliedCallback(void (*callback)(bool functionsApplied, void *(payload)),
+                                         void *payload);
+   bool isMonitorRunning();
+   // Ep monitoring and the gadget pull up logic.
+   static void *startMonitorFd(void *param);
 };
 
 //**************** Helper functions ************************//
@@ -172,6 +182,9 @@
                                   bool *ffsEnabled, int *functionCount);
 // Pulls down USB gadget.
 Status resetGadget();
+// Update the state from typec and usb gadget
+void updateState(const char *typecState, const char *usbGadgetState, std::string &typec_state,
+                 std::string &usb_gadget_state);
 
 }  // namespace usb
 }  // namespace pixel