1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; 20 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; 21 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; 22 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; 23 import static android.net.NetworkCapabilities.TRANSPORT_VPN; 24 import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 25 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; 26 27 import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType; 28 29 import static junit.framework.Assert.assertTrue; 30 31 import static org.junit.Assert.assertEquals; 32 import static org.junit.Assert.assertNotEquals; 33 34 import android.content.Context; 35 import android.net.ConnectivityManager; 36 import android.net.LinkProperties; 37 import android.net.Network; 38 import android.net.NetworkAgent; 39 import android.net.NetworkAgentConfig; 40 import android.net.NetworkCapabilities; 41 import android.net.NetworkInfo; 42 import android.net.NetworkProvider; 43 import android.net.NetworkSpecifier; 44 import android.net.SocketKeepalive; 45 import android.net.UidRange; 46 import android.os.ConditionVariable; 47 import android.os.HandlerThread; 48 import android.os.Message; 49 import android.util.Log; 50 51 import com.android.server.connectivity.ConnectivityConstants; 52 import com.android.testutils.HandlerUtilsKt; 53 import com.android.testutils.TestableNetworkCallback; 54 55 import java.util.Set; 56 57 public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { 58 private final NetworkInfo mNetworkInfo; 59 private final NetworkCapabilities mNetworkCapabilities; 60 private final HandlerThread mHandlerThread; 61 private final Context mContext; 62 private final String mLogTag; 63 64 private final ConditionVariable mDisconnected = new ConditionVariable(); 65 private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); 66 private int mScore; 67 private NetworkAgent mNetworkAgent; 68 private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED; 69 private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE; 70 private Integer mExpectedKeepaliveSlot = null; 71 NetworkAgentWrapper(int transport, LinkProperties linkProperties, Context context)72 public NetworkAgentWrapper(int transport, LinkProperties linkProperties, Context context) 73 throws Exception { 74 final int type = transportToLegacyType(transport); 75 final String typeName = ConnectivityManager.getNetworkTypeName(type); 76 mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); 77 mNetworkCapabilities = new NetworkCapabilities(); 78 mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED); 79 mNetworkCapabilities.addTransportType(transport); 80 switch (transport) { 81 case TRANSPORT_ETHERNET: 82 mScore = 70; 83 break; 84 case TRANSPORT_WIFI: 85 mScore = 60; 86 break; 87 case TRANSPORT_CELLULAR: 88 mScore = 50; 89 break; 90 case TRANSPORT_WIFI_AWARE: 91 mScore = 20; 92 break; 93 case TRANSPORT_VPN: 94 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN); 95 // VPNs deduce the SUSPENDED capability from their underlying networks and there 96 // is no public API to let VPN services set it. 97 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); 98 mScore = ConnectivityConstants.VPN_DEFAULT_SCORE; 99 break; 100 default: 101 throw new UnsupportedOperationException("unimplemented network type"); 102 } 103 mContext = context; 104 mLogTag = "Mock-" + typeName; 105 mHandlerThread = new HandlerThread(mLogTag); 106 mHandlerThread.start(); 107 108 mNetworkAgent = makeNetworkAgent(linkProperties); 109 } 110 makeNetworkAgent(LinkProperties linkProperties)111 protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties) 112 throws Exception { 113 return new InstrumentedNetworkAgent(this, linkProperties); 114 } 115 116 public static class InstrumentedNetworkAgent extends NetworkAgent { 117 private final NetworkAgentWrapper mWrapper; 118 InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp)119 public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) { 120 super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag, 121 wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore, 122 new NetworkAgentConfig(), NetworkProvider.ID_NONE); 123 mWrapper = wrapper; 124 } 125 126 @Override unwanted()127 public void unwanted() { 128 mWrapper.mDisconnected.open(); 129 } 130 131 @Override startSocketKeepalive(Message msg)132 public void startSocketKeepalive(Message msg) { 133 int slot = msg.arg1; 134 if (mWrapper.mExpectedKeepaliveSlot != null) { 135 assertEquals((int) mWrapper.mExpectedKeepaliveSlot, slot); 136 } 137 onSocketKeepaliveEvent(slot, mWrapper.mStartKeepaliveError); 138 } 139 140 @Override stopSocketKeepalive(Message msg)141 public void stopSocketKeepalive(Message msg) { 142 onSocketKeepaliveEvent(msg.arg1, mWrapper.mStopKeepaliveError); 143 } 144 145 @Override preventAutomaticReconnect()146 protected void preventAutomaticReconnect() { 147 mWrapper.mPreventReconnectReceived.open(); 148 } 149 150 @Override addKeepalivePacketFilter(Message msg)151 protected void addKeepalivePacketFilter(Message msg) { 152 Log.i(mWrapper.mLogTag, "Add keepalive packet filter."); 153 } 154 155 @Override removeKeepalivePacketFilter(Message msg)156 protected void removeKeepalivePacketFilter(Message msg) { 157 Log.i(mWrapper.mLogTag, "Remove keepalive packet filter."); 158 } 159 } 160 adjustScore(int change)161 public void adjustScore(int change) { 162 mScore += change; 163 mNetworkAgent.sendNetworkScore(mScore); 164 } 165 getScore()166 public int getScore() { 167 return mScore; 168 } 169 explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated)170 public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) { 171 mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated); 172 } 173 addCapability(int capability)174 public void addCapability(int capability) { 175 mNetworkCapabilities.addCapability(capability); 176 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 177 } 178 removeCapability(int capability)179 public void removeCapability(int capability) { 180 mNetworkCapabilities.removeCapability(capability); 181 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 182 } 183 setUids(Set<UidRange> uids)184 public void setUids(Set<UidRange> uids) { 185 mNetworkCapabilities.setUids(uids); 186 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 187 } 188 setSignalStrength(int signalStrength)189 public void setSignalStrength(int signalStrength) { 190 mNetworkCapabilities.setSignalStrength(signalStrength); 191 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 192 } 193 setNetworkSpecifier(NetworkSpecifier networkSpecifier)194 public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) { 195 mNetworkCapabilities.setNetworkSpecifier(networkSpecifier); 196 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 197 } 198 setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService)199 public void setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService) { 200 mNetworkCapabilities.set(nc); 201 if (sendToConnectivityService) { 202 mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities); 203 } 204 } 205 connect()206 public void connect() { 207 assertNotEquals("MockNetworkAgents can only be connected once", 208 getNetworkInfo().getDetailedState(), NetworkInfo.DetailedState.CONNECTED); 209 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); 210 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 211 } 212 suspend()213 public void suspend() { 214 removeCapability(NET_CAPABILITY_NOT_SUSPENDED); 215 } 216 resume()217 public void resume() { 218 addCapability(NET_CAPABILITY_NOT_SUSPENDED); 219 } 220 disconnect()221 public void disconnect() { 222 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); 223 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 224 } 225 226 @Override getNetwork()227 public Network getNetwork() { 228 return mNetworkAgent.getNetwork(); 229 } 230 expectPreventReconnectReceived(long timeoutMs)231 public void expectPreventReconnectReceived(long timeoutMs) { 232 assertTrue(mPreventReconnectReceived.block(timeoutMs)); 233 } 234 expectDisconnected(long timeoutMs)235 public void expectDisconnected(long timeoutMs) { 236 assertTrue(mDisconnected.block(timeoutMs)); 237 } 238 sendLinkProperties(LinkProperties lp)239 public void sendLinkProperties(LinkProperties lp) { 240 mNetworkAgent.sendLinkProperties(lp); 241 } 242 setStartKeepaliveEvent(int reason)243 public void setStartKeepaliveEvent(int reason) { 244 mStartKeepaliveError = reason; 245 } 246 setStopKeepaliveEvent(int reason)247 public void setStopKeepaliveEvent(int reason) { 248 mStopKeepaliveError = reason; 249 } 250 setExpectedKeepaliveSlot(Integer slot)251 public void setExpectedKeepaliveSlot(Integer slot) { 252 mExpectedKeepaliveSlot = slot; 253 } 254 getNetworkAgent()255 public NetworkAgent getNetworkAgent() { 256 return mNetworkAgent; 257 } 258 getNetworkInfo()259 public NetworkInfo getNetworkInfo() { 260 return mNetworkInfo; 261 } 262 getNetworkCapabilities()263 public NetworkCapabilities getNetworkCapabilities() { 264 return mNetworkCapabilities; 265 } 266 waitForIdle(long timeoutMs)267 public void waitForIdle(long timeoutMs) { 268 HandlerUtilsKt.waitForIdle(mHandlerThread, timeoutMs); 269 } 270 } 271