Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74bfb078 authored by Soonil Nagarkar's avatar Soonil Nagarkar Committed by Automerger Merge Worker
Browse files

Merge "Only allow completion callback to be run once for PIs" into sc-qpr1-dev...

Merge "Only allow completion callback to be run once for PIs" into sc-qpr1-dev am: b53041d1 am: 0a0cb88b am: 8fe1134b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15890710

Change-Id: I6054208b70a830959bcfbb7ef22992cf9f51d245
parents a290b6b1 8fe1134b
Loading
Loading
Loading
Loading
+56 −2
Original line number Diff line number Diff line
@@ -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();
            }
        }
    }
}