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