• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 android.net;
18 
19 import static android.system.OsConstants.SOCK_DGRAM;
20 import static android.system.OsConstants.SOCK_STREAM;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.SystemApi;
25 import android.os.Parcel;
26 import android.os.ParcelFileDescriptor;
27 import android.os.Parcelable;
28 
29 import java.io.IOException;
30 import java.net.DatagramSocket;
31 import java.net.InetAddress;
32 import java.net.InetSocketAddress;
33 import java.net.Socket;
34 import java.net.UnknownHostException;
35 import java.util.Objects;
36 
37 /**
38  * Used in conjunction with
39  * {@link ConnectivityManager#registerQosCallback}
40  * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}
41  * and/or remote address and port of a connected {@link Socket}.
42  *
43  * @hide
44  */
45 @SystemApi
46 public final class QosSocketInfo implements Parcelable {
47 
48     @NonNull
49     private final Network mNetwork;
50 
51     @NonNull
52     private final ParcelFileDescriptor mParcelFileDescriptor;
53 
54     @NonNull
55     private final InetSocketAddress mLocalSocketAddress;
56 
57     @Nullable
58     private final InetSocketAddress mRemoteSocketAddress;
59 
60     private final int mSocketType;
61 
62     /**
63      * The {@link Network} the socket is on.
64      *
65      * @return the registered {@link Network}
66      */
67     @NonNull
getNetwork()68     public Network getNetwork() {
69         return mNetwork;
70     }
71 
72     /**
73      * The parcel file descriptor wrapped around the socket's file descriptor.
74      *
75      * @return the parcel file descriptor of the socket
76      */
77     @NonNull
getParcelFileDescriptor()78     ParcelFileDescriptor getParcelFileDescriptor() {
79         return mParcelFileDescriptor;
80     }
81 
82     /**
83      * The local address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
84      * The value does not reflect any changes that occur to the socket after it is first set
85      * in the constructor.
86      *
87      * @return the local address of the socket
88      */
89     @NonNull
getLocalSocketAddress()90     public InetSocketAddress getLocalSocketAddress() {
91         return mLocalSocketAddress;
92     }
93 
94     /**
95      * The remote address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
96      * The value does not reflect any changes that occur to the socket after it is first set
97      * in the constructor.
98      *
99      * @return the remote address of the socket if socket is connected, null otherwise
100      */
101     @Nullable
getRemoteSocketAddress()102     public InetSocketAddress getRemoteSocketAddress() {
103         return mRemoteSocketAddress;
104     }
105 
106     /**
107      * The socket type of the socket passed in when this QosSocketInfo object was constructed.
108      *
109      * @return the socket type of the socket.
110      * @hide
111      */
getSocketType()112     public int getSocketType()  {
113         return mSocketType;
114     }
115 
116     /**
117      * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}.  The
118      * {@link Socket} must remain bound in order to receive {@link QosSession}s.
119      *
120      * @param network the network
121      * @param socket the bound {@link Socket}
122      */
QosSocketInfo(@onNull final Network network, @NonNull final Socket socket)123     public QosSocketInfo(@NonNull final Network network, @NonNull final Socket socket)
124             throws IOException {
125         Objects.requireNonNull(socket, "socket cannot be null");
126 
127         mNetwork = Objects.requireNonNull(network, "network cannot be null");
128         mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket);
129         mLocalSocketAddress =
130                 new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
131         mSocketType = SOCK_STREAM;
132 
133         if (socket.isConnected()) {
134             mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
135         } else {
136             mRemoteSocketAddress = null;
137         }
138     }
139 
140     /**
141      * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link DatagramSocket}. The
142      * {@link DatagramSocket} must remain bound in order to receive {@link QosSession}s.
143      *
144      * @param network the network
145      * @param socket the bound {@link DatagramSocket}
146      * @hide
147      */
QosSocketInfo(@onNull final Network network, @NonNull final DatagramSocket socket)148     public QosSocketInfo(@NonNull final Network network, @NonNull final DatagramSocket socket)
149             throws IOException {
150         Objects.requireNonNull(socket, "socket cannot be null");
151 
152         mNetwork = Objects.requireNonNull(network, "network cannot be null");
153         mParcelFileDescriptor = ParcelFileDescriptor.fromDatagramSocket(socket);
154         mLocalSocketAddress =
155                 new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
156         mSocketType = SOCK_DGRAM;
157 
158         if (socket.isConnected()) {
159             mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
160         } else {
161             mRemoteSocketAddress = null;
162         }
163     }
164 
165     /* Parcelable methods */
QosSocketInfo(final Parcel in)166     private QosSocketInfo(final Parcel in) {
167         mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
168         mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
169 
170         final int localAddressLength = in.readInt();
171         mLocalSocketAddress = readSocketAddress(in, localAddressLength);
172 
173         final int remoteAddressLength = in.readInt();
174         mRemoteSocketAddress = remoteAddressLength == 0 ? null
175                 : readSocketAddress(in, remoteAddressLength);
176 
177         mSocketType = in.readInt();
178     }
179 
readSocketAddress(final Parcel in, final int addressLength)180     private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
181         final byte[] address = new byte[addressLength];
182         in.readByteArray(address);
183         final int port = in.readInt();
184 
185         try {
186             return new InetSocketAddress(InetAddress.getByAddress(address), port);
187         } catch (final UnknownHostException e) {
188             /* This can never happen. UnknownHostException will never be thrown
189                since the address provided is numeric and non-null. */
190             throw new RuntimeException("UnknownHostException on numeric address", e);
191         }
192     }
193 
194     @Override
describeContents()195     public int describeContents() {
196         return 0;
197     }
198 
199     @Override
writeToParcel(@onNull final Parcel dest, final int flags)200     public void writeToParcel(@NonNull final Parcel dest, final int flags) {
201         mNetwork.writeToParcel(dest, 0);
202         mParcelFileDescriptor.writeToParcel(dest, 0);
203 
204         final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
205         dest.writeInt(localAddress.length);
206         dest.writeByteArray(localAddress);
207         dest.writeInt(mLocalSocketAddress.getPort());
208 
209         if (mRemoteSocketAddress == null) {
210             dest.writeInt(0);
211         } else {
212             final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress();
213             dest.writeInt(remoteAddress.length);
214             dest.writeByteArray(remoteAddress);
215             dest.writeInt(mRemoteSocketAddress.getPort());
216         }
217         dest.writeInt(mSocketType);
218     }
219 
220     @NonNull
221     public static final Parcelable.Creator<QosSocketInfo> CREATOR =
222             new Parcelable.Creator<QosSocketInfo>() {
223             @NonNull
224             @Override
225             public QosSocketInfo createFromParcel(final Parcel in) {
226                 return new QosSocketInfo(in);
227             }
228 
229             @NonNull
230             @Override
231             public QosSocketInfo[] newArray(final int size) {
232                 return new QosSocketInfo[size];
233             }
234         };
235 }
236