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

Commit 9518866c authored by Roshan Pius's avatar Roshan Pius
Browse files

NetworkScoreManager: Add @SystemApi for wifi mainline module

Add formal API's for API's that the wifi mainline module uses:
a) NetworkScoreManager.requestNetworkScores - Request new network scores.
b) NetworkScoreManager.registerNetworkScoreCallback - @SystemApi wrapper
over the existing registerNetworkScoreCache.
c) NetworkKey.createFromScanResult - Create NetworkKey from ScanResult.

Also,
a) Converted the existing WifiNetworkScoreCache callback implementation to
support both the new @SystemApi (used by wifi) and the old @hide API
(used by settings).
b) Stopped invoking dump on all the callbacks from NetworkScoreService.
The dump of each callback should be invoked at their client site (i.e
wifi service should dump state of the callback it registers with the
service).
c) Added a helper method |dumpWithLatestScanResults| to help dump the
state of the WifiNetworkScoreCache from wifi service.

Bug: 144487252
Test: a) Device boots up and connects to wifi network.
b) Manually verified that network scores are being requested & updated
with the new interface.

Change-Id: Id5a66189150e7a088127519373a832f63bdd12ac
Merged-In: Id5a66189150e7a088127519373a832f63bdd12ac
(cherry-picked from c278f80c)
parent 62cec108
Loading
Loading
Loading
Loading
+13 −5
Original line number Diff line number Diff line
@@ -4179,6 +4179,7 @@ package android.net {
  public class NetworkKey implements android.os.Parcelable {
    ctor public NetworkKey(android.net.WifiKey);
    method @Nullable public static android.net.NetworkKey createFromScanResult(@Nullable android.net.wifi.ScanResult);
    method public int describeContents();
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
@@ -4201,16 +4202,23 @@ package android.net {
    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean clearScores() throws java.lang.SecurityException;
    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public void disableScoring() throws java.lang.SecurityException;
    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public String getActiveScorerPackage();
    method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
    method @RequiresPermission("android.permission.REQUEST_NETWORK_SCORES") public boolean requestScores(@NonNull android.net.NetworkKey[]) throws java.lang.SecurityException;
    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, "android.permission.REQUEST_NETWORK_SCORES"}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
    method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(android.net.ScoredNetwork[]) throws java.lang.SecurityException;
    field public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
    method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
    field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
    field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
    field public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
    field public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
    field public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
    field public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
    field @Deprecated public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
    field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
    field public static final String EXTRA_NEW_SCORER = "newScorer";
    field public static final String EXTRA_PACKAGE_NAME = "packageName";
    field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
  }
  public static interface NetworkScoreManager.NetworkScoreCallback {
    method public void clearScores();
    method public void updateScores(@NonNull java.util.List<android.net.ScoredNetwork>);
  }
  public class NetworkStack {
+10 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.net;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -27,6 +28,8 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;

/**
@@ -48,6 +51,13 @@ public class NetworkKey implements Parcelable {
    /** A wifi network, for which {@link #wifiKey} will be populated. */
    public static final int TYPE_WIFI = 1;

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"TYPE_"}, value = {
            TYPE_WIFI
    })
    public @interface NetworkType {}

    /**
     * The type of this network.
     * @see #TYPE_WIFI
@@ -65,7 +75,6 @@ public class NetworkKey implements Parcelable {
     *
     * @return  A new {@link NetworkKey} instance or <code>null</code> if the given
     *          {@link ScanResult} instance is malformed.
     * @hide
     */
    @Nullable
    public static NetworkKey createFromScanResult(@Nullable ScanResult result) {
+108 −3
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
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;
@@ -25,13 +27,16 @@ 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.List;
import java.util.concurrent.Executor;

/**
 * Class that manages communication between network subsystems and a network scorer.
@@ -50,19 +55,25 @@ import java.util.List;
@SystemApi
@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";

    /**
@@ -73,7 +84,9 @@ public class NetworkScoreManager {
     * 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";

@@ -81,7 +94,9 @@ public class NetworkScoreManager {
     * 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";

    /**
@@ -285,7 +300,7 @@ public class NetworkScoreManager {
     * @throws SecurityException if the caller is not the active scorer.
     */
    @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
    public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
    public boolean updateScores(@NonNull ScoredNetwork[] networks) throws SecurityException {
        try {
            return mService.updateScores(networks);
        } catch (RemoteException e) {
@@ -359,13 +374,21 @@ public class NetworkScoreManager {
    /**
     * Request scoring for networks.
     *
     * @return true if the broadcast was sent, or false if there is no active scorer.
     * <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(NetworkKey[] networks) throws SecurityException {
    public boolean requestScores(@NonNull NetworkKey[] networks) throws SecurityException {
        try {
            return mService.requestScores(networks);
        } catch (RemoteException e) {
@@ -430,6 +453,88 @@ public class NetworkScoreManager {
        }
    }

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

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

    /**
     * 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) {
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.updateScores(networks);
            });
        }

        @Override
        public void clearScores() {
            Binder.clearCallingIdentity();
            mExecutor.execute(() -> {
                mCallback.clearScores();
            });
        }
    }

    /**
     * Register a network score callback.
     *
     * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}
     * @param filterType the {@link CacheUpdateFilter} 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,
            @CacheUpdateFilter 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.
     *
+0 −14
Original line number Diff line number Diff line
@@ -60,12 +60,9 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.TransferPipe;
import com.android.internal.telephony.SmsApplication;
import com.android.internal.util.DumpUtils;

import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
@@ -908,17 +905,6 @@ public class NetworkScoreService extends INetworkScoreService.Stub {
            }
            writer.println("Current scorer: " + currentScorer);

            sendCacheUpdateCallback(new BiConsumer<INetworkScoreCache, Object>() {
                @Override
                public void accept(INetworkScoreCache networkScoreCache, Object cookie) {
                    try {
                        TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args);
                    } catch (IOException | RemoteException e) {
                        writer.println("Failed to dump score cache: " + e);
                    }
                }
            }, getScoreCacheLists());

            synchronized (mServiceConnectionLock) {
                if (mServiceConnection != null) {
                    mServiceConnection.dump(fd, writer, args);
+15 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.net.INetworkScoreCache;
import android.net.NetworkKey;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
import android.os.Handler;
import android.os.Process;
@@ -40,7 +41,8 @@ import java.util.List;
 *
 * @hide
 */
public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
public class WifiNetworkScoreCache extends INetworkScoreCache.Stub
        implements NetworkScoreManager.NetworkScoreCallback {
    private static final String TAG = "WifiNetworkScoreCache";
    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);

@@ -246,6 +248,17 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
    }

    @Override protected final void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
        dumpWithLatestScanResults(fd, writer, args, wifiManager.getScanResults());
    }

    /**
     * This is directly invoked from within Wifi-Service (on it's instance of this class), hence
     * avoid making the WifiManager.getScanResults() call to avoid a deadlock.
     */
    public final void dumpWithLatestScanResults(
            FileDescriptor fd, PrintWriter writer, String[] args,
            List<ScanResult> latestScanResults) {
        mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
        String header = String.format("WifiNetworkScoreCache (%s/%d)",
                mContext.getPackageName(), Process.myUid());
@@ -256,8 +269,7 @@ public class WifiNetworkScoreCache extends INetworkScoreCache.Stub {
                writer.println("    " + score);
            }
            writer.println("  Network scores for latest ScanResults:");
            WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
            for (ScanResult scanResult : wifiManager.getScanResults()) {
            for (ScanResult scanResult : latestScanResults) {
                writer.println(
                        "    " + buildNetworkKey(scanResult) + ": " + getNetworkScore(scanResult));
            }