1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package android.net;
18 
19 import android.Manifest.permission;
20 import android.annotation.CallbackExecutor;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SdkConstant;
26 import android.annotation.SdkConstant.SdkConstantType;
27 import android.annotation.SystemApi;
28 import android.annotation.SystemService;
29 import android.content.Context;
30 import android.os.Binder;
31 import android.os.RemoteException;
32 import android.os.ServiceManager;
33 import android.os.ServiceManager.ServiceNotFoundException;
34 import android.util.Log;
35 
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 import java.util.Collection;
39 import java.util.List;
40 import java.util.concurrent.Executor;
41 
42 /**
43  * Class that manages communication between network subsystems and a network scorer.
44  *
45  * <p>A network scorer is any application which:
46  * <ul>
47  * <li>Is granted the {@link permission#SCORE_NETWORKS} permission.
48  * <li>Is granted the {@link permission#ACCESS_COARSE_LOCATION} permission.
49  * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
50  *     protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
51  *     permission.
52  * </ul>
53  *
54  * @hide
55  */
56 @SystemApi
57 @SystemService(Context.NETWORK_SCORE_SERVICE)
58 public class NetworkScoreManager {
59     private static final String TAG = "NetworkScoreManager";
60 
61     /**
62      * Activity action: ask the user to change the active network scorer. This will show a dialog
63      * that asks the user whether they want to replace the current active scorer with the one
64      * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the
65      * active scorer was changed or RESULT_CANCELED if it failed for any reason.
66      * @deprecated No longer sent.
67      */
68     @Deprecated
69     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
70     public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
71 
72     /**
73      * Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with
74      * {@link android.content.Intent#putExtra(String, String)}.
75      * @deprecated No longer sent.
76      */
77     @Deprecated
78     public static final String EXTRA_PACKAGE_NAME = "packageName";
79 
80     /**
81      * Broadcast action: new network scores are being requested. This intent will only be delivered
82      * to the current active scorer app. That app is responsible for scoring the networks and
83      * calling {@link #updateScores} when complete. The networks to score are specified in
84      * {@link #EXTRA_NETWORKS_TO_SCORE}, and will generally consist of all networks which have been
85      * configured by the user as well as any open networks.
86      *
87      * <p class="note">This is a protected intent that can only be sent by the system.
88      * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
89      */
90     @Deprecated
91     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
92     public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
93 
94     /**
95      * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an
96      * array of {@link NetworkKey}s. Can be obtained with
97      * {@link android.content.Intent#getParcelableArrayExtra(String)}}.
98      * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
99      */
100     @Deprecated
101     public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
102 
103     /**
104      * Activity action: launch an activity for configuring a provider for the feature that connects
105      * and secures open wifi networks available before enabling it. Applications that enable this
106      * feature must provide an activity for this action. The framework will launch this activity
107      * which must return RESULT_OK if the feature should be enabled.
108      */
109     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
110     public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
111 
112     /**
113      * Meta-data specified on a {@link NetworkRecommendationProvider} that provides a user-visible
114      * label of the recommendation service.
115      * @hide
116      */
117     public static final String RECOMMENDATION_SERVICE_LABEL_META_DATA =
118             "android.net.scoring.recommendation_service_label";
119 
120     /**
121      * Meta-data specified on a {@link NetworkRecommendationProvider} that specified the package
122      * name of the application that connects and secures open wifi networks automatically. The
123      * specified package must provide an Activity for {@link #ACTION_CUSTOM_ENABLE}.
124      * @hide
125      */
126     public static final String USE_OPEN_WIFI_PACKAGE_META_DATA =
127             "android.net.wifi.use_open_wifi_package";
128 
129     /**
130      * Meta-data specified on a {@link NetworkRecommendationProvider} that specifies the
131      * {@link android.app.NotificationChannel} ID used to post open network notifications.
132      * @hide
133      */
134     public static final String NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID_META_DATA =
135             "android.net.wifi.notification_channel_id_network_available";
136 
137     /**
138      * Broadcast action: the active scorer has been changed. Scorer apps may listen to this to
139      * perform initialization once selected as the active scorer, or clean up unneeded resources
140      * if another scorer has been selected. This is an explicit broadcast only sent to the
141      * previous scorer and new scorer. Note that it is unnecessary to clear existing scores as
142      * this is handled by the system.
143      *
144      * <p>The new scorer will be specified in {@link #EXTRA_NEW_SCORER}.
145      *
146      * <p class="note">This is a protected intent that can only be sent by the system.
147      */
148     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
149     public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
150 
151     /**
152      * Service action: Used to discover and bind to a network recommendation provider.
153      * Implementations should return {@link NetworkRecommendationProvider#getBinder()} from
154      * their <code>onBind()</code> method.
155      */
156     @SdkConstant(SdkConstantType.SERVICE_ACTION)
157     public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
158 
159     /**
160      * Extra used with {@link #ACTION_SCORER_CHANGED} to specify the newly selected scorer's package
161      * name. Will be null if scoring was disabled. Can be obtained with
162      * {@link android.content.Intent#getStringExtra(String)}.
163      */
164     public static final String EXTRA_NEW_SCORER = "newScorer";
165 
166     /** @hide */
167     @IntDef({SCORE_FILTER_NONE, SCORE_FILTER_CURRENT_NETWORK, SCORE_FILTER_SCAN_RESULTS})
168     @Retention(RetentionPolicy.SOURCE)
169     public @interface ScoreUpdateFilter {}
170 
171     /**
172      * Do not filter updates sent to the {@link NetworkScoreCallback}].
173      */
174     public static final int SCORE_FILTER_NONE = 0;
175 
176     /**
177      * Only send updates to the {@link NetworkScoreCallback} when the network matches the connected
178      * network.
179      */
180     public static final int SCORE_FILTER_CURRENT_NETWORK = 1;
181 
182     /**
183      * Only send updates to the {@link NetworkScoreCallback} when the network is part of the
184      * current scan result set.
185      */
186     public static final int SCORE_FILTER_SCAN_RESULTS = 2;
187 
188     /** @hide */
189     @IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF,
190             RECOMMENDATIONS_ENABLED_ON})
191     @Retention(RetentionPolicy.SOURCE)
192     public @interface RecommendationsEnabledSetting {}
193 
194     /**
195      * Recommendations have been forced off.
196      * <p>
197      * This value is never set by any of the NetworkScore classes, it must be set via other means.
198      * This state is also "sticky" and we won't transition out of this state once entered. To move
199      * to a different state this value has to be explicitly set to a different value via
200      * other means.
201      * @hide
202      */
203     public static final int RECOMMENDATIONS_ENABLED_FORCED_OFF = -1;
204 
205     /**
206      * Recommendations are not enabled.
207      * <p>
208      * This is a transient state that can be entered when the default recommendation app is enabled
209      * but no longer valid. This state will transition to RECOMMENDATIONS_ENABLED_ON when a valid
210      * recommendation app is enabled.
211      * @hide
212      */
213     public static final int RECOMMENDATIONS_ENABLED_OFF = 0;
214 
215     /**
216      * Recommendations are enabled.
217      * <p>
218      * This is a transient state that means a valid recommendation app is active. This state will
219      * transition to RECOMMENDATIONS_ENABLED_OFF if the current and default recommendation apps
220      * become invalid.
221      * @hide
222      */
223     public static final int RECOMMENDATIONS_ENABLED_ON = 1;
224 
225     private final Context mContext;
226     private final INetworkScoreService mService;
227 
228     /** @hide */
NetworkScoreManager(Context context)229     public NetworkScoreManager(Context context) throws ServiceNotFoundException {
230         mContext = context;
231         mService = INetworkScoreService.Stub
232                 .asInterface(ServiceManager.getServiceOrThrow(Context.NETWORK_SCORE_SERVICE));
233     }
234 
235     /**
236      * Obtain the package name of the current active network scorer.
237      *
238      * <p>At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
239      * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to
240      * determine the current scorer and offer the user the ability to select a different scorer via
241      * the {@link #ACTION_CHANGE_ACTIVE} intent.
242      * @return the full package name of the current active scorer, or null if there is no active
243      *         scorer.
244      * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS}
245      *                           or {@link permission#REQUEST_NETWORK_SCORES} permissions.
246      */
247     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
248                                  android.Manifest.permission.REQUEST_NETWORK_SCORES})
getActiveScorerPackage()249     public String getActiveScorerPackage() {
250         try {
251             return mService.getActiveScorerPackage();
252         } catch (RemoteException e) {
253             throw e.rethrowFromSystemServer();
254         }
255     }
256 
257     /**
258      * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
259      *
260      * @throws SecurityException if the caller does not hold the
261      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
262      * @hide
263      */
264     @Nullable
265     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
getActiveScorer()266     public NetworkScorerAppData getActiveScorer() {
267         try {
268             return mService.getActiveScorer();
269         } catch (RemoteException e) {
270             throw e.rethrowFromSystemServer();
271         }
272     }
273 
274     /**
275      * Returns the list of available scorer apps. The list will be empty if there are
276      * no valid scorers.
277      *
278      * @throws SecurityException if the caller does not hold the
279      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
280      * @hide
281      */
282     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
getAllValidScorers()283     public List<NetworkScorerAppData> getAllValidScorers() {
284         try {
285             return mService.getAllValidScorers();
286         } catch (RemoteException e) {
287             throw e.rethrowFromSystemServer();
288         }
289     }
290 
291     /**
292      * Update network scores.
293      *
294      * <p>This may be called at any time to re-score active networks. Scores will generally be
295      * updated quickly, but if this method is called too frequently, the scores may be held and
296      * applied at a later time.
297      *
298      * @param networks the networks which have been scored by the scorer.
299      * @return whether the update was successful.
300      * @throws SecurityException if the caller is not the active scorer.
301      */
302     @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
updateScores(@onNull ScoredNetwork[] networks)303     public boolean updateScores(@NonNull ScoredNetwork[] networks) throws SecurityException {
304         try {
305             return mService.updateScores(networks);
306         } catch (RemoteException e) {
307             throw e.rethrowFromSystemServer();
308         }
309     }
310 
311     /**
312      * Clear network scores.
313      *
314      * <p>Should be called when all scores need to be invalidated, i.e. because the scoring
315      * algorithm has changed and old scores can no longer be compared to future scores.
316      *
317      * <p>Note that scores will be cleared automatically when the active scorer changes, as scores
318      * from one scorer cannot be compared to those from another scorer.
319      *
320      * @return whether the clear was successful.
321      * @throws SecurityException if the caller is not the active scorer or if the caller doesn't
322      *                           hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
323      */
324     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
325                                  android.Manifest.permission.REQUEST_NETWORK_SCORES})
clearScores()326     public boolean clearScores() throws SecurityException {
327         try {
328             return mService.clearScores();
329         } catch (RemoteException e) {
330             throw e.rethrowFromSystemServer();
331         }
332     }
333 
334     /**
335      * Set the active scorer to a new package and clear existing scores.
336      *
337      * <p>Should never be called directly without obtaining user consent. This can be done by using
338      * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity.
339      *
340      * @return true if the operation succeeded, or false if the new package is not a valid scorer.
341      * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS}
342      *                           or {@link permission#REQUEST_NETWORK_SCORES} permissions.
343      * @hide
344      */
345     @SystemApi
346     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
347                                  android.Manifest.permission.REQUEST_NETWORK_SCORES})
setActiveScorer(String packageName)348     public boolean setActiveScorer(String packageName) throws SecurityException {
349         try {
350             return mService.setActiveScorer(packageName);
351         } catch (RemoteException e) {
352             throw e.rethrowFromSystemServer();
353         }
354     }
355 
356     /**
357      * Turn off network scoring.
358      *
359      * <p>May only be called by the current scorer app, or the system.
360      *
361      * @throws SecurityException if the caller is not the active scorer or if the caller doesn't
362      *                           hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
363      */
364     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
365                                  android.Manifest.permission.REQUEST_NETWORK_SCORES})
disableScoring()366     public void disableScoring() throws SecurityException {
367         try {
368             mService.disableScoring();
369         } catch (RemoteException e) {
370             throw e.rethrowFromSystemServer();
371         }
372     }
373 
374     /**
375      * Request scoring for networks.
376      *
377      * <p>
378      * Note: The results (i.e scores) for these networks, when available will be provided via the
379      * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor,
380      * NetworkScoreCallback)}. The calling module is responsible for registering a callback to
381      * receive the results before requesting new scores via this API.
382      *
383      * @return true if the request was successfully sent, or false if there is no active scorer.
384      * @throws SecurityException if the caller does not hold the
385      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
386      *
387      * @hide
388      */
389     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
requestScores(@onNull NetworkKey[] networks)390     public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException {
391         try {
392             return mService.requestScores(networks);
393         } catch (RemoteException e) {
394             throw e.rethrowFromSystemServer();
395         }
396     }
397 
398     /**
399      * Request scoring for networks.
400      *
401      * <p>
402      * Note: The results (i.e scores) for these networks, when available will be provided via the
403      * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor,
404      * NetworkScoreCallback)}. The calling module is responsible for registering a callback to
405      * receive the results before requesting new scores via this API.
406      *
407      * @return true if the request was successfully sent, or false if there is no active scorer.
408      * @throws SecurityException if the caller does not hold the
409      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
410      *
411      * @hide
412      */
413     @SystemApi
414     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
requestScores(@onNull Collection<NetworkKey> networks)415     public boolean requestScores(@NonNull Collection<NetworkKey> networks)
416             throws SecurityException {
417         return requestScores(networks.toArray(new NetworkKey[0]));
418     }
419 
420     /**
421      * Register a network score cache.
422      *
423      * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
424      * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
425      * @throws SecurityException if the caller does not hold the
426      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
427      * @throws IllegalArgumentException if a score cache is already registered for this type.
428      * @deprecated equivalent to registering for cache updates with {@link #SCORE_FILTER_NONE}.
429      * @hide
430      */
431     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
432     @Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int)
registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache)433     public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
434         registerNetworkScoreCache(networkType, scoreCache, SCORE_FILTER_NONE);
435     }
436 
437     /**
438      * Register a network score cache.
439      *
440      * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
441      * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
442      * @param filterType the {@link ScoreUpdateFilter} to apply
443      * @throws SecurityException if the caller does not hold the
444      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
445      * @throws IllegalArgumentException if a score cache is already registered for this type.
446      * @hide
447      */
448     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache, @ScoreUpdateFilter int filterType)449     public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache,
450             @ScoreUpdateFilter int filterType) {
451         try {
452             mService.registerNetworkScoreCache(networkType, scoreCache, filterType);
453         } catch (RemoteException e) {
454             throw e.rethrowFromSystemServer();
455         }
456     }
457 
458     /**
459      * Unregister a network score cache.
460      *
461      * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
462      * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
463      * @throws SecurityException if the caller does not hold the
464      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
465      * @throws IllegalArgumentException if a score cache is already registered for this type.
466      * @hide
467      */
468     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache)469     public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
470         try {
471             mService.unregisterNetworkScoreCache(networkType, scoreCache);
472         } catch (RemoteException e) {
473             throw e.rethrowFromSystemServer();
474         }
475     }
476 
477     /**
478      * Base class for network score cache callback. Should be extended by applications and set
479      * when calling {@link #registerNetworkScoreCallback(int, int, Executor, NetworkScoreCallback)}.
480      *
481      * @hide
482      */
483     @SystemApi
484     public abstract static class NetworkScoreCallback {
485         /**
486          * Called when a new set of network scores are available.
487          * This is triggered in response when the client invokes
488          * {@link #requestScores(Collection)} to score a new set of networks.
489          *
490          * @param networks List of {@link ScoredNetwork} containing updated scores.
491          */
onScoresUpdated(@onNull Collection<ScoredNetwork> networks)492         public abstract void onScoresUpdated(@NonNull Collection<ScoredNetwork> networks);
493 
494         /**
495          * Invokes when all the previously provided scores are no longer valid.
496          */
onScoresInvalidated()497         public abstract void onScoresInvalidated();
498     }
499 
500     /**
501      * Callback proxy for {@link NetworkScoreCallback} objects.
502      */
503     private class NetworkScoreCallbackProxy extends INetworkScoreCache.Stub {
504         private final Executor mExecutor;
505         private final NetworkScoreCallback mCallback;
506 
NetworkScoreCallbackProxy(Executor executor, NetworkScoreCallback callback)507         NetworkScoreCallbackProxy(Executor executor, NetworkScoreCallback callback) {
508             mExecutor = executor;
509             mCallback = callback;
510         }
511 
512         @Override
updateScores(@onNull List<ScoredNetwork> networks)513         public void updateScores(@NonNull List<ScoredNetwork> networks) {
514             final long token = Binder.clearCallingIdentity();
515             try {
516                 mExecutor.execute(() -> {
517                     mCallback.onScoresUpdated(networks);
518                 });
519             } finally {
520                 Binder.restoreCallingIdentity(token);
521             }
522         }
523 
524         @Override
clearScores()525         public void clearScores() {
526             final long token = Binder.clearCallingIdentity();
527             try {
528                 mExecutor.execute(() -> {
529                     mCallback.onScoresInvalidated();
530                 });
531             } finally {
532                 Binder.restoreCallingIdentity(token);
533             }
534         }
535     }
536 
537     /**
538      * Register a network score callback.
539      *
540      * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
541      * @param filterType the {@link ScoreUpdateFilter} to apply
542      * @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the
543      *                 scores change.
544      * @param executor The executor on which to execute the callbacks.
545      * @throws SecurityException if the caller does not hold the
546      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
547      * @throws IllegalArgumentException if a callback is already registered for this type.
548      * @hide
549      */
550     @SystemApi
551     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
registerNetworkScoreCallback(@etworkKey.NetworkType int networkType, @ScoreUpdateFilter int filterType, @NonNull @CallbackExecutor Executor executor, @NonNull NetworkScoreCallback callback)552     public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType,
553             @ScoreUpdateFilter int filterType,
554             @NonNull @CallbackExecutor Executor executor,
555             @NonNull NetworkScoreCallback callback) throws SecurityException {
556         if (callback == null || executor == null) {
557             throw new IllegalArgumentException("callback / executor cannot be null");
558         }
559         Log.v(TAG, "registerNetworkScoreCallback: callback=" + callback + ", executor="
560                 + executor);
561         // Use the @hide method.
562         registerNetworkScoreCache(
563                 networkType, new NetworkScoreCallbackProxy(executor, callback), filterType);
564     }
565 
566     /**
567      * Determine whether the application with the given UID is the enabled scorer.
568      *
569      * @param callingUid the UID to check
570      * @return true if the provided UID is the active scorer, false otherwise.
571      * @throws SecurityException if the caller does not hold the
572      *         {@link permission#REQUEST_NETWORK_SCORES} permission.
573      * @hide
574      */
575     @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
isCallerActiveScorer(int callingUid)576     public boolean isCallerActiveScorer(int callingUid) {
577         try {
578             return mService.isCallerActiveScorer(callingUid);
579         } catch (RemoteException e) {
580             throw e.rethrowFromSystemServer();
581         }
582     }
583 }
584