• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_VCN_MANAGED;
21 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
22 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
23 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
24 import static android.net.NetworkCapabilities.TRANSPORT_TEST;
25 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
26 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
27 import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
28 
29 import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
30 
31 import static junit.framework.Assert.assertFalse;
32 import static junit.framework.Assert.assertTrue;
33 
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.fail;
36 
37 import android.annotation.NonNull;
38 import android.content.Context;
39 import android.net.ConnectivityManager;
40 import android.net.LinkProperties;
41 import android.net.Network;
42 import android.net.NetworkAgent;
43 import android.net.NetworkAgentConfig;
44 import android.net.NetworkCapabilities;
45 import android.net.NetworkProvider;
46 import android.net.NetworkScore;
47 import android.net.NetworkSpecifier;
48 import android.net.QosFilter;
49 import android.net.SocketKeepalive;
50 import android.os.ConditionVariable;
51 import android.os.HandlerThread;
52 import android.os.Message;
53 import android.util.Log;
54 import android.util.Range;
55 
56 import com.android.net.module.util.ArrayTrackRecord;
57 import com.android.testutils.HandlerUtils;
58 import com.android.testutils.TestableNetworkCallback;
59 
60 import java.util.List;
61 import java.util.Objects;
62 import java.util.Set;
63 import java.util.concurrent.atomic.AtomicBoolean;
64 
65 public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork {
66     private final NetworkCapabilities mNetworkCapabilities;
67     private final HandlerThread mHandlerThread;
68     private final Context mContext;
69     private final String mLogTag;
70     private final NetworkAgentConfig mNetworkAgentConfig;
71 
72     private final ConditionVariable mDisconnected = new ConditionVariable();
73     private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
74     private final AtomicBoolean mConnected = new AtomicBoolean(false);
75     private NetworkScore mScore;
76     private NetworkAgent mNetworkAgent;
77     private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED;
78     private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
79     // Controls how test network agent is going to wait before responding to keepalive
80     // start/stop. Useful when simulate KeepaliveTracker is waiting for response from modem.
81     private long mKeepaliveResponseDelay = 0L;
82     private Integer mExpectedKeepaliveSlot = null;
83     private final ArrayTrackRecord<CallbackType>.ReadHead mCallbackHistory =
84             new ArrayTrackRecord<CallbackType>().newReadHead();
85 
NetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, Context context)86     public NetworkAgentWrapper(int transport, LinkProperties linkProperties,
87             NetworkCapabilities ncTemplate, Context context) throws Exception {
88         this(transport, linkProperties, ncTemplate, null /* provider */, context);
89     }
90 
NetworkAgentWrapper(int transport, LinkProperties linkProperties, NetworkCapabilities ncTemplate, NetworkProvider provider, Context context)91     public NetworkAgentWrapper(int transport, LinkProperties linkProperties,
92             NetworkCapabilities ncTemplate, NetworkProvider provider,
93             Context context) throws Exception {
94         final int type = transportToLegacyType(transport);
95         final String typeName = ConnectivityManager.getNetworkTypeName(type);
96         mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities();
97         mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
98         mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
99         mNetworkCapabilities.addTransportType(transport);
100         switch (transport) {
101             case TRANSPORT_ETHERNET:
102                 mScore = new NetworkScore.Builder().setLegacyInt(70).build();
103                 break;
104             case TRANSPORT_WIFI:
105                 mScore = new NetworkScore.Builder().setLegacyInt(60).build();
106                 break;
107             case TRANSPORT_CELLULAR:
108                 mScore = new NetworkScore.Builder().setLegacyInt(50).build();
109                 break;
110             case TRANSPORT_WIFI_AWARE:
111                 mScore = new NetworkScore.Builder().setLegacyInt(20).build();
112                 break;
113             case TRANSPORT_TEST:
114                 mScore = new NetworkScore.Builder().build();
115                 break;
116             case TRANSPORT_VPN:
117                 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
118                 // VPNs deduce the SUSPENDED capability from their underlying networks and there
119                 // is no public API to let VPN services set it.
120                 mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
121                 mScore = new NetworkScore.Builder().setLegacyInt(101).build();
122                 break;
123             default:
124                 throw new UnsupportedOperationException("unimplemented network type");
125         }
126         mContext = context;
127         mLogTag = "Mock-" + typeName;
128         mHandlerThread = new HandlerThread(mLogTag);
129         mHandlerThread.start();
130 
131         // extraInfo is set to "" by default in NetworkAgentConfig.
132         final String extraInfo = (transport == TRANSPORT_CELLULAR) ? "internet.apn" : "";
133         mNetworkAgentConfig = new NetworkAgentConfig.Builder()
134                 .setLegacyType(type)
135                 .setLegacyTypeName(typeName)
136                 .setLegacyExtraInfo(extraInfo)
137                 .build();
138         mNetworkAgent = makeNetworkAgent(linkProperties, mNetworkAgentConfig, provider);
139     }
140 
makeNetworkAgent(LinkProperties linkProperties, final NetworkAgentConfig nac, NetworkProvider provider)141     protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties,
142             final NetworkAgentConfig nac, NetworkProvider provider) throws Exception {
143         return new InstrumentedNetworkAgent(this, linkProperties, nac, provider);
144     }
145 
146     public static class InstrumentedNetworkAgent extends NetworkAgent {
147         private final NetworkAgentWrapper mWrapper;
148         private static final String PROVIDER_NAME = "InstrumentedNetworkAgentProvider";
149 
InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, NetworkAgentConfig nac)150         public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
151                 NetworkAgentConfig nac) {
152             this(wrapper, lp, nac, null /* provider */);
153         }
154 
InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, NetworkAgentConfig nac, NetworkProvider provider)155         public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp,
156                 NetworkAgentConfig nac, NetworkProvider provider) {
157             super(wrapper.mContext, wrapper.mHandlerThread.getLooper(), wrapper.mLogTag,
158                     wrapper.mNetworkCapabilities, lp, wrapper.mScore, nac,
159                     null != provider ? provider : new NetworkProvider(wrapper.mContext,
160                             wrapper.mHandlerThread.getLooper(), PROVIDER_NAME));
161             mWrapper = wrapper;
162             register();
163         }
164 
165         @Override
unwanted()166         public void unwanted() {
167             mWrapper.mDisconnected.open();
168         }
169 
170         @Override
startSocketKeepalive(Message msg)171         public void startSocketKeepalive(Message msg) {
172             int slot = msg.arg1;
173             if (mWrapper.mExpectedKeepaliveSlot != null) {
174                 assertEquals((int) mWrapper.mExpectedKeepaliveSlot, slot);
175             }
176             mWrapper.mHandlerThread.getThreadHandler().postDelayed(
177                     () -> onSocketKeepaliveEvent(slot, mWrapper.mStartKeepaliveError),
178                     mWrapper.mKeepaliveResponseDelay);
179         }
180 
181         @Override
stopSocketKeepalive(Message msg)182         public void stopSocketKeepalive(Message msg) {
183             final int slot = msg.arg1;
184             mWrapper.mHandlerThread.getThreadHandler().postDelayed(
185                     () -> onSocketKeepaliveEvent(slot, mWrapper.mStopKeepaliveError),
186                     mWrapper.mKeepaliveResponseDelay);
187         }
188 
189         @Override
onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter)190         public void onQosCallbackRegistered(final int qosCallbackId,
191                 final @NonNull QosFilter filter) {
192             Log.i(mWrapper.mLogTag, "onQosCallbackRegistered");
193             mWrapper.mCallbackHistory.add(
194                     new CallbackType.OnQosCallbackRegister(qosCallbackId, filter));
195         }
196 
197         @Override
onQosCallbackUnregistered(final int qosCallbackId)198         public void onQosCallbackUnregistered(final int qosCallbackId) {
199             Log.i(mWrapper.mLogTag, "onQosCallbackUnregistered");
200             mWrapper.mCallbackHistory.add(new CallbackType.OnQosCallbackUnregister(qosCallbackId));
201         }
202 
203         @Override
preventAutomaticReconnect()204         protected void preventAutomaticReconnect() {
205             mWrapper.mPreventReconnectReceived.open();
206         }
207 
208         @Override
addKeepalivePacketFilter(Message msg)209         protected void addKeepalivePacketFilter(Message msg) {
210             Log.i(mWrapper.mLogTag, "Add keepalive packet filter.");
211         }
212 
213         @Override
removeKeepalivePacketFilter(Message msg)214         protected void removeKeepalivePacketFilter(Message msg) {
215             Log.i(mWrapper.mLogTag, "Remove keepalive packet filter.");
216         }
217     }
218 
setScore(@onNull final NetworkScore score)219     public void setScore(@NonNull final NetworkScore score) {
220         mScore = score;
221         mNetworkAgent.sendNetworkScore(score);
222     }
223 
adjustScore(int change)224     public void adjustScore(int change) {
225         final int newLegacyScore = mScore.getLegacyInt() + change;
226         final NetworkScore.Builder builder = new NetworkScore.Builder()
227                 .setLegacyInt(newLegacyScore);
228         if (mNetworkCapabilities.hasTransport(TRANSPORT_WIFI) && newLegacyScore < 50) {
229             builder.setExiting(true);
230         }
231         mScore = builder.build();
232         mNetworkAgent.sendNetworkScore(mScore);
233     }
234 
getScore()235     public NetworkScore getScore() {
236         return mScore;
237     }
238 
explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated)239     public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
240         mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated);
241     }
242 
addCapability(int capability)243     public void addCapability(int capability) {
244         mNetworkCapabilities.addCapability(capability);
245         mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
246     }
247 
removeCapability(int capability)248     public void removeCapability(int capability) {
249         mNetworkCapabilities.removeCapability(capability);
250         mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
251     }
252 
setUids(Set<Range<Integer>> uids)253     public void setUids(Set<Range<Integer>> uids) {
254         mNetworkCapabilities.setUids(uids);
255         mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
256     }
257 
setSignalStrength(int signalStrength)258     public void setSignalStrength(int signalStrength) {
259         mNetworkCapabilities.setSignalStrength(signalStrength);
260         mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
261     }
262 
setNetworkSpecifier(NetworkSpecifier networkSpecifier)263     public void setNetworkSpecifier(NetworkSpecifier networkSpecifier) {
264         mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
265         mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
266     }
267 
setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService)268     public void setNetworkCapabilities(NetworkCapabilities nc, boolean sendToConnectivityService) {
269         mNetworkCapabilities.set(nc);
270         if (sendToConnectivityService) {
271             mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
272         }
273     }
274 
setUnderlyingNetworks(List<Network> underlyingNetworks)275     public void setUnderlyingNetworks(List<Network> underlyingNetworks) {
276         mNetworkAgent.setUnderlyingNetworks(underlyingNetworks);
277     }
278 
setOwnerUid(int uid)279     public void setOwnerUid(int uid) {
280         mNetworkCapabilities.setOwnerUid(uid);
281         mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
282     }
283 
connect()284     public void connect() {
285         if (!mConnected.compareAndSet(false /* expect */, true /* update */)) {
286             // compareAndSet returns false when the value couldn't be updated because it did not
287             // match the expected value.
288             fail("Test NetworkAgents can only be connected once");
289         }
290         mNetworkAgent.markConnected();
291     }
292 
suspend()293     public void suspend() {
294         removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
295     }
296 
resume()297     public void resume() {
298         addCapability(NET_CAPABILITY_NOT_SUSPENDED);
299     }
300 
disconnect()301     public void disconnect() {
302         mNetworkAgent.unregister();
303     }
304 
305     @Override
getNetwork()306     public Network getNetwork() {
307         return mNetworkAgent.getNetwork();
308     }
309 
expectPreventReconnectReceived(long timeoutMs)310     public void expectPreventReconnectReceived(long timeoutMs) {
311         assertTrue(mPreventReconnectReceived.block(timeoutMs));
312     }
313 
expectDisconnected(long timeoutMs)314     public void expectDisconnected(long timeoutMs) {
315         assertTrue(mDisconnected.block(timeoutMs));
316     }
317 
assertNotDisconnected(long timeoutMs)318     public void assertNotDisconnected(long timeoutMs) {
319         assertFalse(mDisconnected.block(timeoutMs));
320     }
321 
sendLinkProperties(LinkProperties lp)322     public void sendLinkProperties(LinkProperties lp) {
323         mNetworkAgent.sendLinkProperties(lp);
324     }
325 
setStartKeepaliveEvent(int reason)326     public void setStartKeepaliveEvent(int reason) {
327         mStartKeepaliveError = reason;
328     }
329 
setStopKeepaliveEvent(int reason)330     public void setStopKeepaliveEvent(int reason) {
331         mStopKeepaliveError = reason;
332     }
333 
setKeepaliveResponseDelay(long delay)334     public void setKeepaliveResponseDelay(long delay) {
335         mKeepaliveResponseDelay = delay;
336     }
337 
setExpectedKeepaliveSlot(Integer slot)338     public void setExpectedKeepaliveSlot(Integer slot) {
339         mExpectedKeepaliveSlot = slot;
340     }
341 
getNetworkAgent()342     public NetworkAgent getNetworkAgent() {
343         return mNetworkAgent;
344     }
345 
getNetworkAgentConfig()346     public NetworkAgentConfig getNetworkAgentConfig() {
347         return mNetworkAgentConfig;
348     }
349 
getNetworkCapabilities()350     public NetworkCapabilities getNetworkCapabilities() {
351         return mNetworkCapabilities;
352     }
353 
getLegacyType()354     public int getLegacyType() {
355         return mNetworkAgentConfig.getLegacyType();
356     }
357 
getExtraInfo()358     public String getExtraInfo() {
359         return mNetworkAgentConfig.getLegacyExtraInfo();
360     }
361 
getCallbackHistory()362     public @NonNull ArrayTrackRecord<CallbackType>.ReadHead getCallbackHistory() {
363         return mCallbackHistory;
364     }
365 
waitForIdle(long timeoutMs)366     public void waitForIdle(long timeoutMs) {
367         HandlerUtils.waitForIdle(mHandlerThread, timeoutMs);
368     }
369 
370     abstract static class CallbackType {
371         final int mQosCallbackId;
372 
CallbackType(final int qosCallbackId)373         protected CallbackType(final int qosCallbackId) {
374             mQosCallbackId = qosCallbackId;
375         }
376 
377         static class OnQosCallbackRegister extends CallbackType {
378             final QosFilter mFilter;
OnQosCallbackRegister(final int qosCallbackId, final QosFilter filter)379             OnQosCallbackRegister(final int qosCallbackId, final QosFilter filter) {
380                 super(qosCallbackId);
381                 mFilter = filter;
382             }
383 
384             @Override
equals(final Object o)385             public boolean equals(final Object o) {
386                 if (this == o) return true;
387                 if (o == null || getClass() != o.getClass()) return false;
388                 final OnQosCallbackRegister that = (OnQosCallbackRegister) o;
389                 return mQosCallbackId == that.mQosCallbackId
390                         && Objects.equals(mFilter, that.mFilter);
391             }
392 
393             @Override
hashCode()394             public int hashCode() {
395                 return Objects.hash(mQosCallbackId, mFilter);
396             }
397         }
398 
399         static class OnQosCallbackUnregister extends CallbackType {
OnQosCallbackUnregister(final int qosCallbackId)400             OnQosCallbackUnregister(final int qosCallbackId) {
401                 super(qosCallbackId);
402             }
403 
404             @Override
equals(final Object o)405             public boolean equals(final Object o) {
406                 if (this == o) return true;
407                 if (o == null || getClass() != o.getClass()) return false;
408                 final OnQosCallbackUnregister that = (OnQosCallbackUnregister) o;
409                 return mQosCallbackId == that.mQosCallbackId;
410             }
411 
412             @Override
hashCode()413             public int hashCode() {
414                 return Objects.hash(mQosCallbackId);
415             }
416         }
417     }
418 
isBypassableVpn()419     public boolean isBypassableVpn() {
420         return mNetworkAgentConfig.isBypassableVpn();
421     }
422 }
423