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