Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ca3962b authored by Jeff Davidson's avatar Jeff Davidson Committed by Android (Google) Code Review
Browse files

Merge "Initial implementation of NetworkScoreManager's backing service."

parents 3a025393 6a4b220f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ LOCAL_SRC_FILES += \
	core/java/android/net/INetworkManagementEventObserver.aidl \
	core/java/android/net/INetworkPolicyListener.aidl \
	core/java/android/net/INetworkPolicyManager.aidl \
	core/java/android/net/INetworkScoreService.aidl \
	core/java/android/net/INetworkStatsService.aidl \
	core/java/android/net/INetworkStatsSession.aidl \
	core/java/android/net/nsd/INsdManager.aidl \
+49 −0
Original line number Diff line number Diff line
/**
 * 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.net.ScoredNetwork;

/**
 * A service for updating network scores from a network scorer application.
 * @hide
 */
interface INetworkScoreService
{
    /**
     * Update scores.
     * @return whether the update was successful.
     * @throws SecurityException if the caller is not the current active scorer.
     */
    boolean updateScores(in ScoredNetwork[] networks);

    /**
     * Clear all scores.
     * @return whether the clear was successful.
     * @throws SecurityException if the caller is neither the current active scorer nor the scorer
     * manager.
     */
    boolean clearScores();

    /**
     * Set the active scorer and clear existing scores.
     * @param packageName the package name of the new scorer to use.
     * @return true if the operation succeeded, or false if the new package is not a valid scorer.
     * @throws SecurityException if the caller is not the scorer manager.
     */
    boolean setActiveScorer(in String packageName);
}
+23 −0
Original line number Diff line number Diff line
@@ -19,11 +19,19 @@ package android.net;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * Information which identifies a specific network.
 *
 * @hide
 */
// NOTE: Ideally, we would abstract away the details of what identifies a network of a specific
// type, so that all networks appear the same and can be scored without concern to the network type
// itself. However, because no such cross-type identifier currently exists in the Android framework,
// and because systems might obtain information about networks from sources other than Android
// devices, we need to provide identifying details about each specific network type (wifi, cell,
// etc.) so that clients can pull out these details depending on the type of network.
public class NetworkKey implements Parcelable {

    /** A wifi network, for which {@link #wifiKey} will be populated. */
@@ -78,6 +86,21 @@ public class NetworkKey implements Parcelable {
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        NetworkKey that = (NetworkKey) o;

        return type == that.type && Objects.equals(wifiKey, that.wifiKey);
    }

    @Override
    public int hashCode() {
        return Objects.hash(type, wifiKey);
    }

    @Override
    public String toString() {
        switch (type) {
+60 −13
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package android.net;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;

/**
 * Class that manages communication between network subsystems and a network scorer.
@@ -40,7 +43,7 @@ import android.content.Context;
 * <p>The system keeps track of a default scorer application; at any time, only this application
 * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
 * {@link #updateScores}. Applications may determine the current default scorer with
 * {@link #getDefaultScorerPackage()} and request to change the default scorer by sending an
 * {@link #getActiveScorerPackage()} and request to change the default scorer by sending an
 * {@link #ACTION_CHANGE_DEFAULT} broadcast with another scorer.
 *
 * @hide
@@ -81,38 +84,82 @@ public class NetworkScoreManager {
    public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";

    private final Context mContext;
    private final INetworkScoreService mService;

    /** @hide */
    public NetworkScoreManager(Context context) {
        mContext = context;
        IBinder iBinder = ServiceManager.getService(Context.NETWORK_SCORE_SERVICE);
        mService = INetworkScoreService.Stub.asInterface(iBinder);
    }

    /**
     * Obtain the package name of the current default network scorer.
     * Obtain the package name of the current active network scorer.
     *
     * At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
     * <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_DEFAULT} intent.
     * @return the full package name of the current default scorer, or null if there is no active
     * @return the full package name of the current active scorer, or null if there is no active
     *     scorer.
     */
    public String getDefaultScorerPackage() {
        // TODO: Implement.
        return null;
    public String getActiveScorerPackage() {
        return NetworkScorerAppManager.getActiveScorer(mContext);
    }

    /**
     * Update network scores.
     *
     * 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.
     * <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.
     * @throws SecurityException if the caller is not the default scorer.
     * @return whether the update was successful.
     * @throws SecurityException if the caller is not the active scorer.
     */
    public void updateScores(ScoredNetwork[] networks) throws SecurityException {
        // TODO: Implement.
    public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
        try {
            return mService.updateScores(networks);
        } catch (RemoteException e) {
            return false;
        }
    }

    /**
     * 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 privileged.
     */
    public boolean clearScores() throws SecurityException {
        try {
            return mService.clearScores();
        } catch (RemoteException e) {
            return false;
        }
    }

    /**
     * Set the active scorer to a new package and clear existing scores.
     *
     * @return true if the operation succeeded, or false if the new package is not a valid scorer.
     * @throws SecurityException if the caller does not hold the
     *      {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating that
     *      it can manage scorer applications.
     * @hide
     */
    public boolean setActiveScorer(String packageName) throws SecurityException {
        try {
            return mService.setActiveScorer(packageName);
        } catch (RemoteException e) {
            return false;
        }
    }
}
+15 −5
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.Collection;
@@ -36,13 +37,14 @@ import java.util.List;
 *
 * @hide
 */
public final class NetworkScorerApplication {
public final class NetworkScorerAppManager {
    private static final String TAG = "NetworkScorerAppManager";

    private static final Intent SCORE_INTENT =
            new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);

    /** This class cannot be instantiated. */
    private NetworkScorerApplication() {}
    private NetworkScorerAppManager() {}

    /**
     * Returns the list of available scorer app package names.
@@ -111,30 +113,38 @@ public final class NetworkScorerApplication {
     * @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.
     * @return true if the scorer was changed, or false if the package is not a valid scorer.
     */
    public static void setActiveScorer(Context context, String packageName) {
    public static boolean 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;
            return true;
        }

        Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);

        if (packageName == null) {
            Settings.Global.putString(context.getContentResolver(), Global.NETWORK_SCORER_APP,
                    null);
            return true;
        } 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);
                return true;
            } else {
                Log.w(TAG, "Requested network scorer is not valid: " + packageName);
                return false;
            }
        }
    }

    /** Determine whether the application with the given UID is the enabled scorer. */
    public static boolean isCallerDefaultScorer(Context context, int callingUid) {
    public static boolean isCallerActiveScorer(Context context, int callingUid) {
        String defaultApp = getActiveScorer(context);
        if (defaultApp == null) {
            return false;
Loading