diff options
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/net/NetworkScorerApplication.java | 156 | ||||
| -rw-r--r-- | core/java/android/os/Build.java | 5 | ||||
| -rw-r--r-- | core/java/android/provider/Settings.java | 7 |
3 files changed, 168 insertions, 0 deletions
diff --git a/core/java/android/net/NetworkScorerApplication.java b/core/java/android/net/NetworkScorerApplication.java new file mode 100644 index 0000000..b137ad3 --- /dev/null +++ b/core/java/android/net/NetworkScorerApplication.java @@ -0,0 +1,156 @@ +/* + * 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.app.AppOpsManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Internal class for managing the primary network scorer application. + * + * @hide + */ +public final class NetworkScorerApplication { + + private static final Intent SCORE_INTENT = + new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS); + + /** This class cannot be instantiated. */ + private NetworkScorerApplication() {} + + /** + * Returns the list of available scorer app package names. + * + * <p>A network scorer is any application which: + * <ul> + * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission. + * <li>Includes a receiver for {@link NetworkScoreManager#ACTION_SCORE_NETWORKS} guarded by the + * {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission. + * </ul> + * + * @return the list of scorers, or the empty list if there are no valid scorers. + */ + public static Collection<String> getAllValidScorers(Context context) { + List<String> scorers = new ArrayList<>(); + + PackageManager pm = context.getPackageManager(); + List<ResolveInfo> receivers = pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */); + for (ResolveInfo receiver : receivers) { + // This field is a misnomer, see android.content.pm.ResolveInfo#activityInfo + final ActivityInfo receiverInfo = receiver.activityInfo; + if (receiverInfo == null) { + // Should never happen with queryBroadcastReceivers, but invalid nonetheless. + continue; + } + if (!permission.BROADCAST_SCORE_NETWORKS.equals(receiverInfo.permission)) { + // Receiver doesn't require the BROADCAST_SCORE_NETWORKS permission, which means + // anyone could trigger network scoring and flood the framework with score requests. + continue; + } + if (pm.checkPermission(permission.SCORE_NETWORKS, receiverInfo.packageName) != + PackageManager.PERMISSION_GRANTED) { + // Application doesn't hold the SCORE_NETWORKS permission, so the user never + // approved it as a network scorer. + continue; + } + scorers.add(receiverInfo.packageName); + } + + return scorers; + } + + /** + * Get the application package name to use for scoring networks. + * + * @return the scorer package or null if scoring is disabled (including if no scorer was ever + * selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because + * it was disabled or uninstalled). + */ + public static String getActiveScorer(Context context) { + String scorerPackage = Settings.Global.getString(context.getContentResolver(), + Global.NETWORK_SCORER_APP); + Collection<String> applications = getAllValidScorers(context); + if (isPackageValidScorer(applications, scorerPackage)) { + return scorerPackage; + } else { + return null; + } + } + + /** + * Set the specified package as the default scorer application. + * + * <p>The caller must have permission to write to {@link Settings.Global}. + * + * @param context the context of the calling application + * @param packageName the packageName of the new scorer to use. If null, scoring will be + * disabled. Otherwise, the scorer will only be set if it is a valid scorer application. + */ + public static void setActiveScorer(Context context, String packageName) { + String oldPackageName = Settings.Global.getString(context.getContentResolver(), + Settings.Global.NETWORK_SCORER_APP); + if (TextUtils.equals(oldPackageName, packageName)) { + // No change. + return; + } + + if (packageName == null) { + Settings.Global.putString(context.getContentResolver(), Global.NETWORK_SCORER_APP, + null); + } else { + // We only make the change if the new package is valid. + Collection<String> applications = getAllValidScorers(context); + if (isPackageValidScorer(applications, packageName)) { + Settings.Global.putString(context.getContentResolver(), + Settings.Global.NETWORK_SCORER_APP, packageName); + } + } + } + + /** Determine whether the application with the given UID is the enabled scorer. */ + public static boolean isCallerDefaultScorer(Context context, int callingUid) { + String defaultApp = getActiveScorer(context); + if (defaultApp == null) { + return false; + } + AppOpsManager appOpsMgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); + try { + appOpsMgr.checkPackage(callingUid, defaultApp); + return true; + } catch (SecurityException e) { + return false; + } + } + + /** Returns true if the given package is a valid scorer. */ + private static boolean isPackageValidScorer(Collection<String> scorerPackageNames, + String packageName) { + return packageName != null && scorerPackageNames.contains(packageName); + } +} diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 7f1a2e4..63e15a9 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -476,6 +476,11 @@ public class Build { public static final int KITKAT = 19; /** + * Android 4.5: KitKat for watches, snacks on the run. + */ + public static final int KITKAT_WATCH = CUR_DEVELOPMENT; // STOPSHIP: update API level + + /** * L! * * <p>Applications targeting this or a later release will get these diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7062933..1e202ca 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5097,6 +5097,13 @@ public final class Settings { public static final String NETWORK_PREFERENCE = "network_preference"; /** + * Which package name to use for network scoring. If null, or if the package is not a valid + * scorer app, external network scores will neither be requested nor accepted. + * @hide + */ + public static final String NETWORK_SCORER_APP = "network_scorer_app"; + + /** * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been * exceeded. |
