summaryrefslogtreecommitdiff
path: root/core/java/android/net/NetworkScoreManager.java
blob: 804662987655a626de7abea9e845515805c9965e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package android.net;

import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Class that manages communication between network subsystems and a network scorer.
 *
 * <p>A network scorer is any application which:
 * <ul>
 * <li>Is granted the {@link permission#SCORE_NETWORKS} permission.
 * <li>Is granted the {@link permission#ACCESS_COARSE_LOCATION} permission.
 * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
 *     protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
 *     permission.
 * </ul>
 *
 * @deprecated No longer functional on {@link android.os.Build.VERSION_CODES#TIRAMISU} and above.
 * See <a href="{@docRoot}guide/topics/connectivity/wifi-suggest">Wi-Fi Suggestion API</a> for
 * alternative APIs to suggest/configure Wi-Fi networks.
 * @hide
 */
@SystemApi
@Deprecated
@SystemService(Context.NETWORK_SCORE_SERVICE)
public class NetworkScoreManager {
    private static final String TAG = "NetworkScoreManager";

    /**
     * Activity action: ask the user to change the active network scorer. This will show a dialog
     * that asks the user whether they want to replace the current active scorer with the one
     * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the
     * active scorer was changed or RESULT_CANCELED if it failed for any reason.
     * @deprecated No longer sent.
     */
    @Deprecated
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";

    /**
     * Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with
     * {@link android.content.Intent#putExtra(String, String)}.
     * @deprecated No longer sent.
     */
    @Deprecated
    public static final String EXTRA_PACKAGE_NAME = "packageName";

    /**
     * Broadcast action: new network scores are being requested. This intent will only be delivered
     * to the current active scorer app. That app is responsible for scoring the networks and
     * calling {@link #updateScores} when complete. The networks to score are specified in
     * {@link #EXTRA_NETWORKS_TO_SCORE}, and will generally consist of all networks which have been
     * configured by the user as well as any open networks.
     *
     * <p class="note">This is a protected intent that can only be sent by the system.
     * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
     */
    @Deprecated
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";

    /**
     * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an
     * array of {@link NetworkKey}s. Can be obtained with
     * {@link android.content.Intent#getParcelableArrayExtra(String)}}.
     * @deprecated Use {@link #ACTION_RECOMMEND_NETWORKS} to bind scorer app instead.
     */
    @Deprecated
    public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";

    /**
     * Activity action: launch an activity for configuring a provider for the feature that connects
     * and secures open wifi networks available before enabling it. Applications that enable this
     * feature must provide an activity for this action. The framework will launch this activity
     * which must return RESULT_OK if the feature should be enabled.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";

    /**
     * Meta-data specified on a {@link NetworkRecommendationProvider} that provides a user-visible
     * label of the recommendation service.
     * @hide
     */
    public static final String RECOMMENDATION_SERVICE_LABEL_META_DATA =
            "android.net.scoring.recommendation_service_label";

    /**
     * Meta-data specified on a {@link NetworkRecommendationProvider} that specified the package
     * name of the application that connects and secures open wifi networks automatically. The
     * specified package must provide an Activity for {@link #ACTION_CUSTOM_ENABLE}.
     * @hide
     */
    public static final String USE_OPEN_WIFI_PACKAGE_META_DATA =
            "android.net.wifi.use_open_wifi_package";

    /**
     * Meta-data specified on a {@link NetworkRecommendationProvider} that specifies the
     * {@link android.app.NotificationChannel} ID used to post open network notifications.
     * @hide
     */
    public static final String NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID_META_DATA =
            "android.net.wifi.notification_channel_id_network_available";

    /**
     * Broadcast action: the active scorer has been changed. Scorer apps may listen to this to
     * perform initialization once selected as the active scorer, or clean up unneeded resources
     * if another scorer has been selected. This is an explicit broadcast only sent to the
     * previous scorer and new scorer. Note that it is unnecessary to clear existing scores as
     * this is handled by the system.
     *
     * <p>The new scorer will be specified in {@link #EXTRA_NEW_SCORER}.
     *
     * <p class="note">This is a protected intent that can only be sent by the system.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";

    /**
     * Service action: Used to discover and bind to a network recommendation provider.
     * Implementations should return {@link NetworkRecommendationProvider#getBinder()} from
     * their <code>onBind()</code> method.
     */
    @SdkConstant(SdkConstantType.SERVICE_ACTION)
    public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";

    /**
     * Extra used with {@link #ACTION_SCORER_CHANGED} to specify the newly selected scorer's package
     * name. Will be null if scoring was disabled. Can be obtained with
     * {@link android.content.Intent#getStringExtra(String)}.
     */
    public static final String EXTRA_NEW_SCORER = "newScorer";

    /** @hide */
    @IntDef({SCORE_FILTER_NONE, SCORE_FILTER_CURRENT_NETWORK, SCORE_FILTER_SCAN_RESULTS})
    @Retention(RetentionPolicy.SOURCE)
    public @interface ScoreUpdateFilter {}

    /**
     * Do not filter updates sent to the {@link NetworkScoreCallback}].
     */
    public static final int SCORE_FILTER_NONE = 0;

    /**
     * Only send updates to the {@link NetworkScoreCallback} when the network matches the connected
     * network.
     */
    public static final int SCORE_FILTER_CURRENT_NETWORK = 1;

    /**
     * Only send updates to the {@link NetworkScoreCallback} when the network is part of the
     * current scan result set.
     */
    public static final int SCORE_FILTER_SCAN_RESULTS = 2;

    /** @hide */
    @IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF,
            RECOMMENDATIONS_ENABLED_ON})
    @Retention(RetentionPolicy.SOURCE)
    public @interface RecommendationsEnabledSetting {}

    /**
     * Recommendations have been forced off.
     * <p>
     * This value is never set by any of the NetworkScore classes, it must be set via other means.
     * This state is also "sticky" and we won't transition out of this state once entered. To move
     * to a different state this value has to be explicitly set to a different value via
     * other means.
     * @hide
     */
    public static final int RECOMMENDATIONS_ENABLED_FORCED_OFF = -1;

    /**
     * Recommendations are not enabled.
     * <p>
     * This is a transient state that can be entered when the default recommendation app is enabled
     * but no longer valid. This state will transition to RECOMMENDATIONS_ENABLED_ON when a valid
     * recommendation app is enabled.
     * @hide
     */
    public static final int RECOMMENDATIONS_ENABLED_OFF = 0;

    /**
     * Recommendations are enabled.
     * <p>
     * This is a transient state that means a valid recommendation app is active. This state will
     * transition to RECOMMENDATIONS_ENABLED_OFF if the current and default recommendation apps
     * become invalid.
     * @hide
     */
    public static final int RECOMMENDATIONS_ENABLED_ON = 1;

    private final Context mContext;
    private final INetworkScoreService mService;

    /** @hide */
    public NetworkScoreManager(Context context) throws ServiceNotFoundException {
        mContext = context;
        mService = INetworkScoreService.Stub
                .asInterface(ServiceManager.getServiceOrThrow(Context.NETWORK_SCORE_SERVICE));
    }

    /**
     * Obtain the package name of the current active network scorer.
     *
     * <p>At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
     * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to
     * determine the current scorer and offer the user the ability to select a different scorer via
     * the {@link #ACTION_CHANGE_ACTIVE} intent.
     * @return the full package name of the current active scorer, or null if there is no active
     *         scorer.
     * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS}
     *                           or {@link permission#REQUEST_NETWORK_SCORES} permissions.
     */
    @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
            android.Manifest.permission.REQUEST_NETWORK_SCORES})
    public String getActiveScorerPackage() {
        try {
            return mService.getActiveScorerPackage();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns metadata about the active scorer or <code>null</code> if there is no active scorer.
     *
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     * @hide
     */
    @Nullable
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public NetworkScorerAppData getActiveScorer() {
        try {
            return mService.getActiveScorer();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns the list of available scorer apps. The list will be empty if there are
     * no valid scorers.
     *
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public List<NetworkScorerAppData> getAllValidScorers() {
        try {
            return mService.getAllValidScorers();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Update network scores.
     *
     * <p>This may be called at any time to re-score active networks. Scores will generally be
     * updated quickly, but if this method is called too frequently, the scores may be held and
     * applied at a later time.
     *
     * @param networks the networks which have been scored by the scorer.
     * @return whether the update was successful.
     * @throws SecurityException if the caller is not the active scorer.
     */
    @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
    public boolean updateScores(@NonNull ScoredNetwork[] networks) throws SecurityException {
        try {
            return mService.updateScores(networks);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Clear network scores.
     *
     * <p>Should be called when all scores need to be invalidated, i.e. because the scoring
     * algorithm has changed and old scores can no longer be compared to future scores.
     *
     * <p>Note that scores will be cleared automatically when the active scorer changes, as scores
     * from one scorer cannot be compared to those from another scorer.
     *
     * @return whether the clear was successful.
     * @throws SecurityException if the caller is not the active scorer or if the caller doesn't
     *                           hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
     */
    @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
            android.Manifest.permission.REQUEST_NETWORK_SCORES})
    public boolean clearScores() throws SecurityException {
        try {
            return mService.clearScores();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set the active scorer to a new package and clear existing scores.
     *
     * <p>Should never be called directly without obtaining user consent. This can be done by using
     * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity.
     *
     * @return true if the operation succeeded, or false if the new package is not a valid scorer.
     * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS}
     *                           or {@link permission#REQUEST_NETWORK_SCORES} permissions.
     * @hide
     */
    @SystemApi
    @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
            android.Manifest.permission.REQUEST_NETWORK_SCORES})
    public boolean setActiveScorer(String packageName) throws SecurityException {
        try {
            return mService.setActiveScorer(packageName);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Turn off network scoring.
     *
     * <p>May only be called by the current scorer app, or the system.
     *
     * @throws SecurityException if the caller is not the active scorer or if the caller doesn't
     *                           hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
     */
    @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
            android.Manifest.permission.REQUEST_NETWORK_SCORES})
    public void disableScoring() throws SecurityException {
        try {
            mService.disableScoring();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Request scoring for networks.
     *
     * <p>
     * Note: The results (i.e scores) for these networks, when available will be provided via the
     * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor,
     * NetworkScoreCallback)}. The calling module is responsible for registering a callback to
     * receive the results before requesting new scores via this API.
     *
     * @return true if the request was successfully sent, or false if there is no active scorer.
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException {
        try {
            return mService.requestScores(networks);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Request scoring for networks.
     *
     * <p>
     * Note: The results (i.e scores) for these networks, when available will be provided via the
     * callback registered with {@link #registerNetworkScoreCallback(int, int, Executor,
     * NetworkScoreCallback)}. The calling module is responsible for registering a callback to
     * receive the results before requesting new scores via this API.
     *
     * @return true if the request was successfully sent, or false if there is no active scorer.
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     *
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public boolean requestScores(@NonNull Collection<NetworkKey> networks)
            throws SecurityException {
        return requestScores(networks.toArray(new NetworkKey[0]));
    }

    /**
     * Register a network score cache.
     *
     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     * @throws IllegalArgumentException if a score cache is already registered for this type.
     * @deprecated equivalent to registering for cache updates with {@link #SCORE_FILTER_NONE}.
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    @Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int)
    public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
        registerNetworkScoreCache(networkType, scoreCache, SCORE_FILTER_NONE);
    }

    /**
     * Register a network score cache.
     *
     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores
     * @param filterType the {@link ScoreUpdateFilter} to apply
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     * @throws IllegalArgumentException if a score cache is already registered for this type.
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache,
            @ScoreUpdateFilter int filterType) {
        try {
            mService.registerNetworkScoreCache(networkType, scoreCache, filterType);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unregister a network score cache.
     *
     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}.
     * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores.
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     * @throws IllegalArgumentException if a score cache is already registered for this type.
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) {
        try {
            mService.unregisterNetworkScoreCache(networkType, scoreCache);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Base class for network score cache callback. Should be extended by applications and set
     * when calling {@link #registerNetworkScoreCallback(int, int, Executor, NetworkScoreCallback)}.
     *
     * @hide
     */
    @SystemApi
    public abstract static class NetworkScoreCallback {
        /**
         * Called when a new set of network scores are available.
         * This is triggered in response when the client invokes
         * {@link #requestScores(Collection)} to score a new set of networks.
         *
         * @param networks List of {@link ScoredNetwork} containing updated scores.
         */
        public abstract void onScoresUpdated(@NonNull Collection<ScoredNetwork> networks);

        /**
         * Invokes when all the previously provided scores are no longer valid.
         */
        public abstract void onScoresInvalidated();
    }

    /**
     * Callback proxy for {@link NetworkScoreCallback} objects.
     */
    private class NetworkScoreCallbackProxy extends INetworkScoreCache.Stub {
        private final Executor mExecutor;
        private final NetworkScoreCallback mCallback;

        NetworkScoreCallbackProxy(Executor executor, NetworkScoreCallback callback) {
            mExecutor = executor;
            mCallback = callback;
        }

        @Override
        public void updateScores(@NonNull List<ScoredNetwork> networks) {
            final long token = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() -> {
                    mCallback.onScoresUpdated(networks);
                });
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void clearScores() {
            final long token = Binder.clearCallingIdentity();
            try {
                mExecutor.execute(() -> {
                    mCallback.onScoresInvalidated();
                });
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
    }

    /**
     * Register a network score callback.
     *
     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
     * @param filterType the {@link ScoreUpdateFilter} to apply
     * @param callback implementation of {@link NetworkScoreCallback} that will be invoked when the
     *                 scores change.
     * @param executor The executor on which to execute the callbacks.
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     * @throws IllegalArgumentException if a callback is already registered for this type.
     * @hide
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public void registerNetworkScoreCallback(@NetworkKey.NetworkType int networkType,
            @ScoreUpdateFilter int filterType,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull NetworkScoreCallback callback) throws SecurityException {
        if (callback == null || executor == null) {
            throw new IllegalArgumentException("callback / executor cannot be null");
        }
        Log.v(TAG, "registerNetworkScoreCallback: callback=" + callback + ", executor="
                + executor);
        // Use the @hide method.
        registerNetworkScoreCache(
                networkType, new NetworkScoreCallbackProxy(executor, callback), filterType);
    }

    /**
     * Determine whether the application with the given UID is the enabled scorer.
     *
     * @param callingUid the UID to check
     * @return true if the provided UID is the active scorer, false otherwise.
     * @throws SecurityException if the caller does not hold the
     *         {@link permission#REQUEST_NETWORK_SCORES} permission.
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
    public boolean isCallerActiveScorer(int callingUid) {
        try {
            return mService.isCallerActiveScorer(callingUid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}