Fix potential racing by wall time change in USBhal

pthread_cond_timedwait used wall time so it might introduce racing,
pthread_cond_timedwait_monotonic_np is Android specific but it is being
deprecated. And now Android support pthread_condattr_setclock so use it
to wait on CLOCK_MONOTONIC instead.

Bug: 64623895
Test: USB switch function works, charging/MTP/PTP
Change-Id: I136533ff90ef1be2b042ef1e0829643f2f7aa968
This commit is contained in:
Wei Wang
2017-08-11 15:05:46 -07:00
parent 8fd93c1f7c
commit 5934d8aab5
2 changed files with 33 additions and 8 deletions

View File

@@ -182,12 +182,12 @@ bool switchMode(const hidl_string &portName,
if (ret != EOF) {
struct timespec to;
struct timeval tp;
struct timespec now;
wait_again:
gettimeofday(&tp, NULL);
to.tv_sec = tp.tv_sec + PORT_TYPE_TIMEOUT;
to.tv_nsec = tp.tv_usec * 1000;;
clock_gettime(CLOCK_MONOTONIC, &now);
to.tv_sec = now.tv_sec + PORT_TYPE_TIMEOUT;
to.tv_nsec = now.tv_nsec;
int err = pthread_cond_timedwait(&usb->mPartnerCV, &usb->mPartnerLock, &to);
// There are no uevent signals which implies role swap timed out.
@@ -212,6 +212,29 @@ wait_again:
return roleSwitch;
}
Usb::Usb()
: mLock(PTHREAD_MUTEX_INITIALIZER),
mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER),
mPartnerLock(PTHREAD_MUTEX_INITIALIZER),
mPartnerUp(false) {
pthread_condattr_t attr;
if (pthread_condattr_init(&attr)) {
ALOGE("pthread_condattr_init failed: %s", strerror(errno));
abort();
}
if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) {
ALOGE("pthread_condattr_setclock failed: %s", strerror(errno));
abort();
}
if (pthread_cond_init(&mPartnerCV, &attr)) {
ALOGE("pthread_cond_init failed: %s", strerror(errno));
abort();
}
if (pthread_condattr_destroy(&attr)) {
ALOGE("pthread_condattr_destroy failed: %s", strerror(errno));
abort();
}
}
Return<void> Usb::switchRole(const hidl_string &portName,

View File

@@ -40,6 +40,8 @@ using ::android::hardware::Void;
using ::android::sp;
struct Usb : public IUsb {
Usb();
Return<void> switchRole(const hidl_string& portName, const PortRole& role) override;
Return<void> setCallback(const sp<V1_0::IUsbCallback>& callback) override;
Return<void> queryPortStatus() override;
@@ -47,13 +49,13 @@ struct Usb : public IUsb {
sp<V1_0::IUsbCallback> mCallback_1_0;
// Protects mCallback variable
pthread_mutex_t mLock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mLock;
// Protects roleSwitch operation
pthread_mutex_t mRoleSwitchLock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mRoleSwitchLock;
// Threads waiting for the partner to come back wait here
pthread_cond_t mPartnerCV = PTHREAD_COND_INITIALIZER;
pthread_cond_t mPartnerCV;
// lock protecting mPartnerCV
pthread_mutex_t mPartnerLock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mPartnerLock;
// Variable to signal partner coming back online after type switch
bool mPartnerUp;