NetworkScorerAppManager.java revision 161977998feebf0a855ea56558464470877040cf
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/*
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright (C) 2014 The Android Open Source Project
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * you may not use this file except in compliance with the License.
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * You may obtain a copy of the License at
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * See the License for the specific language governing permissions and
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * limitations under the License
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)package android.net;
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.Manifest;
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.Manifest.permission;
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport android.annotation.Nullable;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.app.AppOpsManager;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.Context;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.Intent;
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.pm.ActivityInfo;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.pm.PackageManager;
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.pm.ResolveInfo;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.UserHandle;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.provider.Settings;
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.text.TextUtils;
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import android.util.Log;
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import java.util.ArrayList;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import java.util.Collection;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import java.util.List;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/**
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * Internal class for managing the primary network scorer application.
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * TODO: Rename this to something more generic.
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * @hide
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) */
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)public final class NetworkScorerAppManager {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final String TAG = "NetworkScorerAppManager";
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final Intent SCORE_INTENT =
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** This class cannot be instantiated. */
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private NetworkScorerAppManager() {}
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static class NetworkScorerAppData {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /** Package name of this scorer app. */
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public final String mPackageName;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /** Name of this scorer app for display. */
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public final CharSequence mScorerName;
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        /**
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         * Optional class name of a configuration activity. Null if none is set.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         *
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         * @see NetworkScoreManager#ACTION_CUSTOM_ENABLE
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         */
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public final String mConfigurationActivityClassName;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public NetworkScorerAppData(String packageName, CharSequence scorerName,
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                @Nullable String configurationActivityClassName) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mScorerName = scorerName;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mPackageName = packageName;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mConfigurationActivityClassName = configurationActivityClassName;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Returns the list of available scorer apps.
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * <p>A network scorer is any application which:
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * <ul>
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * <li>Includes a receiver for {@link NetworkScoreManager#ACTION_SCORE_NETWORKS} guarded by the
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * </ul>
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @return the list of scorers, or the empty list if there are no valid scorers.
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public static Collection<NetworkScorerAppData> getAllValidScorers(Context context) {
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        List<NetworkScorerAppData> scorers = new ArrayList<>();
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        PackageManager pm = context.getPackageManager();
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Only apps installed under the primary user of the device can be scorers.
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        List<ResolveInfo> receivers =
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */, UserHandle.USER_OWNER);
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (ResolveInfo receiver : receivers) {
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            // This field is a misnomer, see android.content.pm.ResolveInfo#activityInfo
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            final ActivityInfo receiverInfo = receiver.activityInfo;
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (receiverInfo == null) {
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                // Should never happen with queryBroadcastReceivers, but invalid nonetheless.
99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                continue;
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            }
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (!permission.BROADCAST_NETWORK_PRIVILEGED.equals(receiverInfo.permission)) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // Receiver doesn't require the BROADCAST_NETWORK_PRIVILEGED permission, which means
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // anyone could trigger network scoring and flood the framework with score requests.
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                continue;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            if (pm.checkPermission(permission.SCORE_NETWORKS, receiverInfo.packageName) !=
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    PackageManager.PERMISSION_GRANTED) {
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // Application doesn't hold the SCORE_NETWORKS permission, so the user never
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // approved it as a network scorer.
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                continue;
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // Optionally, this package may specify a configuration activity.
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            String configurationActivityClassName = null;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Intent intent = new Intent(NetworkScoreManager.ACTION_CUSTOM_ENABLE);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            intent.setPackage(receiverInfo.packageName);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            List<ResolveInfo> configActivities = pm.queryIntentActivities(intent, 0 /* flags */);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (!configActivities.isEmpty()) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                ActivityInfo activityInfo = configActivities.get(0).activityInfo;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (activityInfo != null) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    configurationActivityClassName = activityInfo.name;
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // NOTE: loadLabel will attempt to load the receiver's label and fall back to the app
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // label if none is present.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            scorers.add(new NetworkScorerAppData(receiverInfo.packageName,
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    receiverInfo.loadLabel(pm), configurationActivityClassName));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return scorers;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Get the application to use for scoring networks.
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @return the scorer app info or null if scoring is disabled (including if no scorer was ever
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)     *     it was disabled or uninstalled).
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static NetworkScorerAppData getActiveScorer(Context context) {
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        String scorerPackage = Settings.Global.getString(context.getContentResolver(),
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Settings.Global.NETWORK_SCORER_APP);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return getScorer(context, scorerPackage);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Set the specified package as the default scorer application.
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * <p>The caller must have permission to write to {@link android.provider.Settings.Global}.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param context the context of the calling application
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param packageName the packageName of the new scorer to use. If null, scoring will be
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @return true if the scorer was changed, or false if the package is not a valid scorer.
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static boolean setActiveScorer(Context context, String packageName) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        String oldPackageName = Settings.Global.getString(context.getContentResolver(),
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Settings.Global.NETWORK_SCORER_APP);
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (TextUtils.equals(oldPackageName, packageName)) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            // No change.
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return true;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        if (packageName == null) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Settings.Global.putString(context.getContentResolver(),
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    Settings.Global.NETWORK_SCORER_APP, null);
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return true;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else {
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            // We only make the change if the new package is valid.
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            if (getScorer(context, packageName) != null) {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Settings.Global.putString(context.getContentResolver(),
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        Settings.Global.NETWORK_SCORER_APP, packageName);
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                return true;
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            } else {
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                Log.w(TAG, "Requested network scorer is not valid: " + packageName);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return false;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** Determine whether the application with the given UID is the enabled scorer. */
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static boolean isCallerActiveScorer(Context context, int callingUid) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NetworkScorerAppData defaultApp = getActiveScorer(context);
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (defaultApp == null) {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return false;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AppOpsManager appOpsMgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        try {
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            appOpsMgr.checkPackage(callingUid, defaultApp.mPackageName);
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } catch (SecurityException e) {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return false;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // To be extra safe, ensure the caller holds the SCORE_NETWORKS permission. It always
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // should, since it couldn't become the active scorer otherwise, but this can't hurt.
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return context.checkCallingPermission(Manifest.permission.SCORE_NETWORKS) ==
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                PackageManager.PERMISSION_GRANTED;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /** Returns the {@link NetworkScorerAppData} for the given app, or null if it's not a scorer. */
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static NetworkScorerAppData getScorer(Context context, String packageName) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (TextUtils.isEmpty(packageName)) {
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return null;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Collection<NetworkScorerAppData> applications = getAllValidScorers(context);
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (NetworkScorerAppData app : applications) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (packageName.equals(app.mPackageName)) {
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return app;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return null;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)