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