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