Allow reregistering callback
Callbacks would have to be allowed being reregistered
to handle frameworks restarts.
Bug: 35758079
Test: adb shell stop; adb shell start; and see if USB notifications happen.
Change-Id: I256b4e714340f48c1dd8377e660cb28ebd716b8a
diff --git a/usb/1.0/default/Usb.cpp b/usb/1.0/default/Usb.cpp
index f46ff66..cdf0d79 100644
--- a/usb/1.0/default/Usb.cpp
+++ b/usb/1.0/default/Usb.cpp
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <assert.h>
#include <dirent.h>
#include <iostream>
#include <fstream>
@@ -34,6 +35,9 @@
namespace V1_0 {
namespace implementation {
+// Set by the signal handler to destroy the thread
+volatile bool destroyThread;
+
int32_t readFile(std::string filename, std::string& contents) {
std::ifstream file(filename);
@@ -374,7 +378,7 @@
goto error;
}
- while (1) {
+ while (!destroyThread) {
struct epoll_event events[64];
nevents = epoll_wait(epoll_fd, events, 64, -1);
@@ -392,6 +396,7 @@
}
}
+ ALOGI("exiting worker thread");
error:
close(uevent_fd);
@@ -401,26 +406,61 @@
return NULL;
}
+void sighandler(int sig)
+{
+ if (sig == SIGUSR1) {
+ destroyThread = true;
+ ALOGI("destroy set");
+ return;
+ }
+ signal(SIGUSR1, sighandler);
+}
Return<void> Usb::setCallback(const sp<IUsbCallback>& callback) {
- if (mCallback != NULL) {
- ALOGE("Callback already registered");
+ pthread_mutex_lock(&mLock);
+ if ((mCallback == NULL && callback == NULL) ||
+ (mCallback != NULL && callback != NULL)) {
+ mCallback = callback;
+ pthread_mutex_unlock(&mLock);
return Void();
}
mCallback = callback;
ALOGI("registering callback");
- if (pthread_create(&mPoll, NULL, work, this)) {
- ALOGE("pthread creation failed %d", errno);
- mCallback = NULL;
+ if (mCallback == NULL) {
+ if (!pthread_kill(mPoll, SIGUSR1)) {
+ pthread_join(mPoll, NULL);
+ ALOGI("pthread destroyed");
+ }
+ pthread_mutex_unlock(&mLock);
return Void();
}
+ destroyThread = false;
+ signal(SIGUSR1, sighandler);
+
+ if (pthread_create(&mPoll, NULL, work, this)) {
+ ALOGE("pthread creation failed %d", errno);
+ mCallback = NULL;
+ }
+ pthread_mutex_unlock(&mLock);
return Void();
}
+// Protects *usb assignment
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+Usb *usb;
+
+Usb::Usb() {
+ pthread_mutex_lock(&lock);
+ // Make this a singleton class
+ assert(usb == NULL);
+ usb = this;
+ pthread_mutex_unlock(&lock);
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace usb