2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-30 13:47:41 +00:00

Fix potential race condition caused by early unlocking

The lock should be kept between the point we read and the point we write

Also, no need to pass SMSPlugin as a parameter, since enclossed classes
already have access to its parent by default.
This commit is contained in:
Albert Vaca Cintora
2019-07-04 21:01:12 +02:00
parent 7db40ee20a
commit bfadb84b9f

View File

@@ -163,18 +163,15 @@ public class SMSPlugin extends Plugin {
private final Lock mostRecentTimestampLock = new ReentrantLock(); private final Lock mostRecentTimestampLock = new ReentrantLock();
private class MessageContentObserver extends ContentObserver { private class MessageContentObserver extends ContentObserver {
final SMSPlugin mPlugin;
/** /**
* Create a ContentObserver to watch the Messages database. onChange is called for * Create a ContentObserver to watch the Messages database. onChange is called for
* every subscribed change * every subscribed change
* *
* @param parent Plugin which owns this observer
* @param handler Handler object used to make the callback * @param handler Handler object used to make the callback
*/ */
MessageContentObserver(SMSPlugin parent, Handler handler) { MessageContentObserver(Handler handler) {
super(handler); super(handler);
mPlugin = parent;
} }
/** /**
@@ -185,29 +182,26 @@ public class SMSPlugin extends Plugin {
*/ */
@Override @Override
public void onChange(boolean selfChange) { public void onChange(boolean selfChange) {
if (mPlugin.mostRecentTimestamp == 0) { if (mostRecentTimestamp == 0) {
// Since the timestamp has not been initialized, we know that nobody else // Since the timestamp has not been initialized, we know that nobody else
// has requested a message. That being the case, there is most likely // has requested a message. That being the case, there is most likely
// nobody listening for message updates, so just drop them // nobody listening for message updates, so just drop them
return; return;
} }
// Lock so no one uses the mostRecentTimestamp between the moment we read it and the
// moment we update it. This is because reading the Messages DB can take long.
mostRecentTimestampLock.lock(); mostRecentTimestampLock.lock();
// Grab the mostRecentTimestamp into the local stack because reading the Messages SMSHelper.Message message = SMSHelper.getNewestMessage(context);
// database could potentially be a long operation
long mostRecentTimestamp = mPlugin.mostRecentTimestamp;
mostRecentTimestampLock.unlock();
SMSHelper.Message message = SMSHelper.getNewestMessage(mPlugin.context); if (message == null || message.date <= mostRecentTimestamp) {
// onChange can trigger many times for a single message. Don't make unnecessary noise
if (message.date <= mostRecentTimestamp) { mostRecentTimestampLock.unlock();
// Our onChange often gets called many times for a single message. Don't make unnecessary
// noise
return; return;
} }
// Update the most recent counter // Update the most recent counter
mostRecentTimestampLock.lock(); mostRecentTimestamp = message.date;
mPlugin.mostRecentTimestamp = message.date;
mostRecentTimestampLock.unlock(); mostRecentTimestampLock.unlock();
// Send the alert about the update // Send the alert about the update
@@ -281,7 +275,7 @@ public class SMSPlugin extends Plugin {
context.registerReceiver(receiver, filter); context.registerReceiver(receiver, filter);
Looper helperLooper = SMSHelper.MessageLooper.getLooper(); Looper helperLooper = SMSHelper.MessageLooper.getLooper();
ContentObserver messageObserver = new MessageContentObserver(this, new Handler(helperLooper)); ContentObserver messageObserver = new MessageContentObserver(new Handler(helperLooper));
SMSHelper.registerObserver(messageObserver, context); SMSHelper.registerObserver(messageObserver, context);
return true; return true;