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

Commit c000664c authored by Lucas Lin's avatar Lucas Lin Committed by Gerrit Code Review
Browse files

Merge "[NS01] Create NetworkScore"

parents 5a844a16 c2bac518
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.net;

import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
@@ -418,7 +419,16 @@ public abstract class NetworkAgent extends Handler {
        if (score < 0) {
            throw new IllegalArgumentException("Score must be >= 0");
        }
        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED,  score, 0);
        final NetworkScore ns = new NetworkScore();
        ns.putIntExtension(NetworkScore.LEGACY_SCORE, score);
        updateScore(ns);
    }

    /**
     * Called by the bearer code when it has a new NetworkScore for this network.
     */
    public void updateScore(@NonNull NetworkScore ns) {
        queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns));
    }

    /**
+157 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * Object representing the quality of a network as perceived by the user.
 *
 * A NetworkScore object represents the characteristics of a network that affects how good the
 * network is considered for a particular use.
 * @hide
 */
public final class NetworkScore implements Parcelable {

    // The key of bundle which is used to get the legacy network score of NetworkAgentInfo.
    // TODO: Remove this when the transition to NetworkScore is over.
    public static final String LEGACY_SCORE = "LEGACY_SCORE";
    @NonNull
    private final Bundle mExtensions;

    public NetworkScore() {
        mExtensions = new Bundle();
    }

    public NetworkScore(@NonNull NetworkScore source) {
        mExtensions = new Bundle(source.mExtensions);
    }

    /**
     * Put the value of parcelable inside the bundle by key.
     */
    public void putExtension(@Nullable String key, @Nullable Parcelable value) {
        mExtensions.putParcelable(key, value);
    }

    /**
     * Put the value of int inside the bundle by key.
     */
    public void putIntExtension(@Nullable String key, int value) {
        mExtensions.putInt(key, value);
    }

    /**
     * Get the value of non primitive type by key.
     */
    public <T extends Parcelable> T getExtension(@Nullable String key) {
        return mExtensions.getParcelable(key);
    }

    /**
     * Get the value of int by key.
     */
    public int getIntExtension(@Nullable String key) {
        return mExtensions.getInt(key);
    }

    /**
     * Remove the entry by given key.
     */
    public void removeExtension(@Nullable String key) {
        mExtensions.remove(key);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        synchronized (this) {
            dest.writeBundle(mExtensions);
        }
    }

    public static final @NonNull Creator<NetworkScore> CREATOR = new Creator<NetworkScore>() {
        @Override
        public NetworkScore createFromParcel(@NonNull Parcel in) {
            return new NetworkScore(in);
        }

        @Override
        public NetworkScore[] newArray(int size) {
            return new NetworkScore[size];
        }
    };

    private NetworkScore(@NonNull Parcel in) {
        mExtensions = in.readBundle();
    }

    // TODO: Modify this method once new fields are added into this class.
    @Override
    public boolean equals(@Nullable Object obj) {
        if (!(obj instanceof NetworkScore)) {
            return false;
        }
        final NetworkScore other = (NetworkScore) obj;
        return bundlesEqual(mExtensions, other.mExtensions);
    }

    @Override
    public int hashCode() {
        int result = 29;
        for (String key : mExtensions.keySet()) {
            final Object value = mExtensions.get(key);
            // The key may be null, so call Objects.hash() is safer.
            result += 31 * value.hashCode() + 37 * Objects.hash(key);
        }
        return result;
    }

    // mExtensions won't be null since the constructor will create it.
    private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) {
        if (bundle1 == bundle2) {
            return true;
        }

        // This is unlikely but it's fine to add this clause here.
        if (null == bundle1 || null == bundle2) {
            return false;
        }

        if (bundle1.size() != bundle2.size()) {
            return false;
        }

        for (String key : bundle1.keySet()) {
            final Object value1 = bundle1.get(key);
            final Object value2 = bundle2.get(key);
            if (!Objects.equals(value1, value2)) {
                return false;
            }
        }
        return true;
    }
}
+9 −4
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkStackClient;
@@ -2643,7 +2644,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
                    break;
                }
                case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
                    updateNetworkScore(nai, msg.arg1);
                    final NetworkScore ns = (NetworkScore) msg.obj;
                    updateNetworkScore(nai, ns);
                    break;
                }
                case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
@@ -5594,9 +5596,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
        // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
        // satisfies mDefaultRequest.
        final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
        final NetworkScore ns = new NetworkScore();
        ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore);
        final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
                new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,
                currentScore, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd,
                ns, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd,
                mDnsResolver, mNMS, factorySerialNumber);
        // Make sure the network capabilities reflect what the agent info says.
        nai.setNetworkCapabilities(mixInCapabilities(nai, nc));
@@ -6729,7 +6733,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }
    }

    private void updateNetworkScore(NetworkAgentInfo nai, int score) {
    private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) {
        int score = ns.getIntExtension(NetworkScore.LEGACY_SCORE);
        if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
        if (score < 0) {
            loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
@@ -6738,7 +6743,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        }

        final int oldScore = nai.getCurrentScore();
        nai.setCurrentScore(score);
        nai.setNetworkScore(ns);

        rematchAllNetworksAndRequests(nai, oldScore);

+16 −8
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.net.NetworkInfo;
import android.net.NetworkMisc;
import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
import android.net.NetworkScore;
import android.net.NetworkState;
import android.os.Handler;
import android.os.INetworkManagementService;
@@ -227,8 +228,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
    // validated).
    private boolean mLingering;

    // This represents the last score received from the NetworkAgent.
    private int currentScore;
    // This represents the characteristics of a network that affects how good the network is
    // considered for a particular use.
    @NonNull
    private NetworkScore mNetworkScore;

    // The list of NetworkRequests being satisfied by this Network.
    private final SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
@@ -257,8 +260,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
    private final Handler mHandler;

    public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
            LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
            NetworkMisc misc, ConnectivityService connService, INetd netd,
            LinkProperties lp, NetworkCapabilities nc, @NonNull NetworkScore ns, Context context,
            Handler handler, NetworkMisc misc, ConnectivityService connService, INetd netd,
            IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) {
        this.messenger = messenger;
        asyncChannel = ac;
@@ -266,7 +269,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
        networkInfo = info;
        linkProperties = lp;
        networkCapabilities = nc;
        currentScore = score;
        mNetworkScore = ns;
        clatd = new Nat464Xlat(this, netd, dnsResolver, nms);
        mConnService = connService;
        mContext = context;
@@ -483,7 +486,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
            return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
        }

        int score = currentScore;
        int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE);
        if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
            score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
        }
@@ -512,8 +515,13 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
        return getCurrentScore(true);
    }

    public void setCurrentScore(int newScore) {
        currentScore = newScore;
    public void setNetworkScore(@NonNull NetworkScore ns) {
        mNetworkScore = ns;
    }

    @NonNull
    public NetworkScore getNetworkScore() {
        return mNetworkScore;
    }

    public NetworkState getNetworkState() {
+104 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.os.Parcelable
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.testutils.assertParcelSane
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith

private const val TEST_SCORE = 80
private const val KEY_DEFAULT_CAPABILITIES = "DEFAULT_CAPABILITIES"

@RunWith(AndroidJUnit4::class)
@SmallTest
class NetworkScoreTest {
    @Test
    fun testParcelNetworkScore() {
        val networkScore = NetworkScore()
        val defaultCap = NetworkCapabilities()
        networkScore.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap)
        assertEquals(defaultCap, networkScore.getExtension(KEY_DEFAULT_CAPABILITIES))
        networkScore.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE)
        assertEquals(TEST_SCORE, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE))
        assertParcelSane(networkScore, 1)
    }

    @Test
    fun testNullKeyAndValue() {
        val networkScore = NetworkScore()
        val defaultCap = NetworkCapabilities()
        networkScore.putIntExtension(null, TEST_SCORE)
        assertEquals(TEST_SCORE, networkScore.getIntExtension(null))
        networkScore.putExtension(null, defaultCap)
        assertEquals(defaultCap, networkScore.getExtension(null))
        networkScore.putExtension(null, null)
        val result: Parcelable? = networkScore.getExtension(null)
        assertEquals(null, result)
    }

    @Test
    fun testRemoveExtension() {
        val networkScore = NetworkScore()
        val defaultCap = NetworkCapabilities()
        networkScore.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap)
        networkScore.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE)
        assertEquals(defaultCap, networkScore.getExtension(KEY_DEFAULT_CAPABILITIES))
        assertEquals(TEST_SCORE, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE))
        networkScore.removeExtension(KEY_DEFAULT_CAPABILITIES)
        networkScore.removeExtension(NetworkScore.LEGACY_SCORE)
        val result: Parcelable? = networkScore.getExtension(KEY_DEFAULT_CAPABILITIES)
        assertEquals(null, result)
        assertEquals(0, networkScore.getIntExtension(NetworkScore.LEGACY_SCORE))
    }

    @Test
    fun testEqualsNetworkScore() {
        val ns1 = NetworkScore()
        val ns2 = NetworkScore()
        assertTrue(ns1.equals(ns2))
        assertEquals(ns1.hashCode(), ns2.hashCode())

        ns1.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE)
        assertFalse(ns1.equals(ns2))
        assertNotEquals(ns1.hashCode(), ns2.hashCode())
        ns2.putIntExtension(NetworkScore.LEGACY_SCORE, TEST_SCORE)
        assertTrue(ns1.equals(ns2))
        assertEquals(ns1.hashCode(), ns2.hashCode())

        val defaultCap = NetworkCapabilities()
        ns1.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap)
        assertFalse(ns1.equals(ns2))
        assertNotEquals(ns1.hashCode(), ns2.hashCode())
        ns2.putExtension(KEY_DEFAULT_CAPABILITIES, defaultCap)
        assertTrue(ns1.equals(ns2))
        assertEquals(ns1.hashCode(), ns2.hashCode())

        ns1.putIntExtension(null, 10)
        assertFalse(ns1.equals(ns2))
        assertNotEquals(ns1.hashCode(), ns2.hashCode())
        ns2.putIntExtension(null, 10)
        assertTrue(ns1.equals(ns2))
        assertEquals(ns1.hashCode(), ns2.hashCode())
    }
}
Loading