Replace the RequestRecommendationCaller if the timeout changes.
The timeout associated with a TimedRemoteCaller can't be changed
after creation so we have to create a new instance anytime the
timeout changes (which shouldn't be too often). The instance is
stored and retrieved from an AtomicReference to avoid concurrency
issues.
Test: runtest frameworks-services -c com.android.server.NetworkScoreServiceTest
Bug: 34060959
Change-Id: I52f5d617feb9b3536ff3474b5d032113e3caea5c
Merged-In: I1662ac27f7442a16d2ffd7257469f1983b7f0e5c
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index bd9f684..6f49702 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -75,6 +75,7 @@
import java.util.Map;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
/**
@@ -87,7 +88,7 @@
private final Context mContext;
private final NetworkScorerAppManager mNetworkScorerAppManager;
- private final RequestRecommendationCaller mRequestRecommendationCaller;
+ private final AtomicReference<RequestRecommendationCaller> mReqRecommendationCallerRef;
@GuardedBy("mScoreCaches")
private final Map<Integer, RemoteCallbackList<INetworkScoreCache>> mScoreCaches;
/** Lock used to update mPackageMonitor when scorer package changes occur. */
@@ -249,8 +250,8 @@
mContext.registerReceiverAsUser(
mUserIntentReceiver, UserHandle.SYSTEM, filter, null /* broadcastPermission*/,
null /* scheduler */);
- mRequestRecommendationCaller =
- new RequestRecommendationCaller(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS);
+ mReqRecommendationCallerRef = new AtomicReference<>(
+ new RequestRecommendationCaller(TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS));
mRecommendationRequestTimeoutMs = TimedRemoteCaller.DEFAULT_CALL_TIMEOUT_MILLIS;
mHandler = new ServiceHandler(looper);
mContentObserver = new DispatchingContentObserver(context, mHandler);
@@ -569,7 +570,8 @@
final INetworkRecommendationProvider provider = getRecommendationProvider();
if (provider != null) {
try {
- return mRequestRecommendationCaller.getRecommendationResult(provider, request);
+ final RequestRecommendationCaller caller = mReqRecommendationCallerRef.get();
+ return caller.getRecommendationResult(provider, request);
} catch (RemoteException | TimeoutException e) {
Log.w(TAG, "Failed to request a recommendation.", e);
// TODO(jjoslin): 12/15/16 - Keep track of failures.
@@ -748,6 +750,7 @@
}
if (DBG) Log.d(TAG, "Updating the recommendation request timeout to " + timeoutMs + " ms");
mRecommendationRequestTimeoutMs = timeoutMs;
+ mReqRecommendationCallerRef.set(new RequestRecommendationCaller(timeoutMs));
}
private static class ScoringServiceConnection implements ServiceConnection {