Merge "Only allow completion callback to be run once for PIs" into sc-qpr1-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b53041d1eb
@@ -243,15 +243,24 @@ public class LocationProviderManager extends
|
||||
intent.putExtra(KEY_LOCATIONS, locationResult.asList().toArray(new Location[0]));
|
||||
}
|
||||
|
||||
// send() SHOULD only run the completion callback if it completes successfully. however,
|
||||
// b/199464864 (which could not be fixed in the S timeframe) means that it's possible
|
||||
// for send() to throw an exception AND run the completion callback. if this happens, we
|
||||
// would over-release the wakelock... we take matters into our own hands to ensure that
|
||||
// the completion callback can only be run if send() completes successfully. this means
|
||||
// the completion callback may be run inline - but as we've never specified what thread
|
||||
// the callback is run on, this is fine.
|
||||
GatedCallback gatedCallback = new GatedCallback(onCompleteCallback);
|
||||
|
||||
mPendingIntent.send(
|
||||
mContext,
|
||||
0,
|
||||
intent,
|
||||
onCompleteCallback != null ? (pI, i, rC, rD, rE) -> onCompleteCallback.run()
|
||||
: null,
|
||||
(pI, i, rC, rD, rE) -> gatedCallback.run(),
|
||||
null,
|
||||
null,
|
||||
options.toBundle());
|
||||
gatedCallback.allow();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2734,4 +2743,49 @@ public class LocationProviderManager extends
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GatedCallback implements Runnable {
|
||||
|
||||
private @Nullable Runnable mCallback;
|
||||
|
||||
@GuardedBy("this")
|
||||
private boolean mGate;
|
||||
@GuardedBy("this")
|
||||
private boolean mRun;
|
||||
|
||||
GatedCallback(Runnable callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public void allow() {
|
||||
Runnable callback = null;
|
||||
synchronized (this) {
|
||||
mGate = true;
|
||||
if (mRun && mCallback != null) {
|
||||
callback = mCallback;
|
||||
mCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (callback != null) {
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Runnable callback = null;
|
||||
synchronized (this) {
|
||||
mRun = true;
|
||||
if (mGate && mCallback != null) {
|
||||
callback = mCallback;
|
||||
mCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (callback != null) {
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user