• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.shadows;
2 
3 import static android.os.Build.VERSION_CODES.LOLLIPOP;
4 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
5 import static android.os.Build.VERSION_CODES.M;
6 import static android.os.Build.VERSION_CODES.R;
7 
8 import android.net.Network;
9 import com.google.common.base.Preconditions;
10 import java.io.FileDescriptor;
11 import java.net.DatagramSocket;
12 import java.net.Socket;
13 import java.util.HashSet;
14 import java.util.Set;
15 import org.robolectric.RuntimeEnvironment;
16 import org.robolectric.annotation.Implementation;
17 import org.robolectric.annotation.Implements;
18 import org.robolectric.annotation.RealObject;
19 import org.robolectric.shadow.api.Shadow;
20 import org.robolectric.util.ReflectionHelpers;
21 
22 @Implements(value = Network.class, minSdk = LOLLIPOP)
23 public class ShadowNetwork {
24 
25   @RealObject private Network realObject;
26 
27   private final Set<Socket> boundSockets = new HashSet<>();
28   private final Set<DatagramSocket> boundDatagramSockets = new HashSet<>();
29   private final Set<FileDescriptor> boundFileDescriptors = new HashSet<>();
30 
31   /**
32    * Creates new instance of {@link Network}, because its constructor is hidden.
33    *
34    * <p>Requires API 21 (Lollipop) and above.
35    *
36    * @param netId The netId.
37    * @return The Network instance.
38    */
newInstance(int netId)39   public static Network newInstance(int netId) {
40     Preconditions.checkState(
41         RuntimeEnvironment.getApiLevel() >= LOLLIPOP,
42         "android.net.Network requires API 21 (Lollipop) or above");
43     return Shadow.newInstance(Network.class, new Class[] {int.class}, new Object[] {netId});
44   }
45 
46   /** Checks if the {@code socket} was previously bound to this network. */
isSocketBound(Socket socket)47   public boolean isSocketBound(Socket socket) {
48     return boundSockets.contains(socket);
49   }
50 
51   /** Checks if the {@code datagramSocket} was previously bound to this network. */
isSocketBound(DatagramSocket socket)52   public boolean isSocketBound(DatagramSocket socket) {
53     return boundDatagramSockets.contains(socket);
54   }
55 
56   /** Checks if the {@code fileDescriptor} was previously bound to this network. */
isSocketBound(FileDescriptor fd)57   public boolean isSocketBound(FileDescriptor fd) {
58     return boundFileDescriptors.contains(fd);
59   }
60 
61   /** Returns the total number of sockets bound to this network interface. */
boundSocketCount()62   public int boundSocketCount() {
63     return boundSockets.size() + boundDatagramSockets.size() + boundFileDescriptors.size();
64   }
65 
66   /**
67    * Simulates a socket bind. isSocketBound can be called to verify that the socket was bound to
68    * this network interface, and boundSocketCount() will increment for any unique socket.
69    */
70   @Implementation(minSdk = LOLLIPOP_MR1)
bindSocket(DatagramSocket socket)71   protected void bindSocket(DatagramSocket socket) {
72     boundDatagramSockets.add(socket);
73   }
74 
75   /**
76    * Simulates a socket bind. isSocketBound can be called to verify that the socket was bound to
77    * this network interface, and boundSocketCount() will increment for any unique socket.
78    */
79   @Implementation
bindSocket(Socket socket)80   protected void bindSocket(Socket socket) {
81     boundSockets.add(socket);
82   }
83 
84   /**
85    * Simulates a socket bind. isSocketBound can be called to verify that the fd was bound to
86    * this network interface, and boundSocketCount() will increment for any unique socket.
87    */
88   @Implementation(minSdk = M)
bindSocket(FileDescriptor fd)89   protected void bindSocket(FileDescriptor fd) {
90     boundFileDescriptors.add(fd);
91   }
92 
93   /**
94    * Allows to get the stored netId.
95    *
96    * @return The netId.
97    */
98   @Implementation(minSdk = R)
getNetId()99   public int getNetId() {
100     return ReflectionHelpers.getField(realObject, "netId");
101   }
102 }
103