blob: acb825f65dc416c31e638745749f8a759e12049b [file] [log] [blame]
Daniel Brightf9e945b2020-06-15 16:10:01 -07001/*
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
17package android.net;
18
sewookseo82657d72022-03-07 06:31:57 +000019import static android.system.OsConstants.SOCK_DGRAM;
20import static android.system.OsConstants.SOCK_STREAM;
21
Daniel Brightf9e945b2020-06-15 16:10:01 -070022import android.annotation.NonNull;
Jayachandran Cb5335502021-04-19 18:21:36 -070023import android.annotation.Nullable;
Daniel Brightf9e945b2020-06-15 16:10:01 -070024import android.annotation.SystemApi;
25import android.os.Parcel;
26import android.os.ParcelFileDescriptor;
27import android.os.Parcelable;
28
29import java.io.IOException;
sewookseo82657d72022-03-07 06:31:57 +000030import java.net.DatagramSocket;
Daniel Brightf9e945b2020-06-15 16:10:01 -070031import java.net.InetAddress;
32import java.net.InetSocketAddress;
33import java.net.Socket;
34import java.net.UnknownHostException;
35import java.util.Objects;
36
37/**
38 * Used in conjunction with
39 * {@link ConnectivityManager#registerQosCallback}
Jayachandran Cb5335502021-04-19 18:21:36 -070040 * 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}.
Daniel Brightf9e945b2020-06-15 16:10:01 -070042 *
43 * @hide
44 */
45@SystemApi
46public 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
Jayachandran Cb5335502021-04-19 18:21:36 -070057 @Nullable
58 private final InetSocketAddress mRemoteSocketAddress;
59
sewookseo82657d72022-03-07 06:31:57 +000060 private final int mSocketType;
61
Daniel Brightf9e945b2020-06-15 16:10:01 -070062 /**
63 * The {@link Network} the socket is on.
64 *
65 * @return the registered {@link Network}
66 */
67 @NonNull
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
Remi NGUYEN VAN7b92ff22022-04-20 15:59:16 +090076 * @hide
Daniel Brightf9e945b2020-06-15 16:10:01 -070077 */
78 @NonNull
Remi NGUYEN VAN7b92ff22022-04-20 15:59:16 +090079 public ParcelFileDescriptor getParcelFileDescriptor() {
Daniel Brightf9e945b2020-06-15 16:10:01 -070080 return mParcelFileDescriptor;
81 }
82
83 /**
84 * The local address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
85 * The value does not reflect any changes that occur to the socket after it is first set
86 * in the constructor.
87 *
88 * @return the local address of the socket
89 */
90 @NonNull
91 public InetSocketAddress getLocalSocketAddress() {
92 return mLocalSocketAddress;
93 }
94
95 /**
Jayachandran Cb5335502021-04-19 18:21:36 -070096 * The remote address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
97 * The value does not reflect any changes that occur to the socket after it is first set
98 * in the constructor.
99 *
100 * @return the remote address of the socket if socket is connected, null otherwise
101 */
102 @Nullable
103 public InetSocketAddress getRemoteSocketAddress() {
104 return mRemoteSocketAddress;
105 }
106
107 /**
sewookseo82657d72022-03-07 06:31:57 +0000108 * The socket type of the socket passed in when this QosSocketInfo object was constructed.
109 *
110 * @return the socket type of the socket.
111 * @hide
112 */
113 public int getSocketType() {
114 return mSocketType;
115 }
116
117 /**
Daniel Brightf9e945b2020-06-15 16:10:01 -0700118 * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}. The
119 * {@link Socket} must remain bound in order to receive {@link QosSession}s.
120 *
121 * @param network the network
122 * @param socket the bound {@link Socket}
123 */
124 public QosSocketInfo(@NonNull final Network network, @NonNull final Socket socket)
125 throws IOException {
126 Objects.requireNonNull(socket, "socket cannot be null");
127
128 mNetwork = Objects.requireNonNull(network, "network cannot be null");
Remi NGUYEN VAN0942ad92021-03-09 23:53:55 +0000129 mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700130 mLocalSocketAddress =
131 new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
sewookseo82657d72022-03-07 06:31:57 +0000132 mSocketType = SOCK_STREAM;
133
134 if (socket.isConnected()) {
135 mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
136 } else {
137 mRemoteSocketAddress = null;
138 }
139 }
140
141 /**
142 * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link DatagramSocket}. The
143 * {@link DatagramSocket} must remain bound in order to receive {@link QosSession}s.
144 *
145 * @param network the network
146 * @param socket the bound {@link DatagramSocket}
147 * @hide
148 */
149 public QosSocketInfo(@NonNull final Network network, @NonNull final DatagramSocket socket)
150 throws IOException {
151 Objects.requireNonNull(socket, "socket cannot be null");
152
153 mNetwork = Objects.requireNonNull(network, "network cannot be null");
154 mParcelFileDescriptor = ParcelFileDescriptor.fromDatagramSocket(socket);
155 mLocalSocketAddress =
156 new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
157 mSocketType = SOCK_DGRAM;
Jayachandran Cb5335502021-04-19 18:21:36 -0700158
159 if (socket.isConnected()) {
160 mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
161 } else {
162 mRemoteSocketAddress = null;
163 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700164 }
165
166 /* Parcelable methods */
167 private QosSocketInfo(final Parcel in) {
168 mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
169 mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
170
Jayachandran Cb5335502021-04-19 18:21:36 -0700171 final int localAddressLength = in.readInt();
172 mLocalSocketAddress = readSocketAddress(in, localAddressLength);
173
174 final int remoteAddressLength = in.readInt();
175 mRemoteSocketAddress = remoteAddressLength == 0 ? null
176 : readSocketAddress(in, remoteAddressLength);
sewookseo82657d72022-03-07 06:31:57 +0000177
178 mSocketType = in.readInt();
Daniel Brightf9e945b2020-06-15 16:10:01 -0700179 }
180
Jayachandran Cb5335502021-04-19 18:21:36 -0700181 private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
Daniel Brightf9e945b2020-06-15 16:10:01 -0700182 final byte[] address = new byte[addressLength];
183 in.readByteArray(address);
184 final int port = in.readInt();
185
186 try {
187 return new InetSocketAddress(InetAddress.getByAddress(address), port);
188 } catch (final UnknownHostException e) {
Remi NGUYEN VANd059f212021-03-11 07:43:37 +0000189 /* This can never happen. UnknownHostException will never be thrown
Daniel Brightf9e945b2020-06-15 16:10:01 -0700190 since the address provided is numeric and non-null. */
Remi NGUYEN VANd059f212021-03-11 07:43:37 +0000191 throw new RuntimeException("UnknownHostException on numeric address", e);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700192 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700193 }
194
195 @Override
196 public int describeContents() {
197 return 0;
198 }
199
200 @Override
201 public void writeToParcel(@NonNull final Parcel dest, final int flags) {
202 mNetwork.writeToParcel(dest, 0);
203 mParcelFileDescriptor.writeToParcel(dest, 0);
204
Jayachandran Cb5335502021-04-19 18:21:36 -0700205 final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
206 dest.writeInt(localAddress.length);
207 dest.writeByteArray(localAddress);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700208 dest.writeInt(mLocalSocketAddress.getPort());
Jayachandran Cb5335502021-04-19 18:21:36 -0700209
210 if (mRemoteSocketAddress == null) {
211 dest.writeInt(0);
212 } else {
213 final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress();
214 dest.writeInt(remoteAddress.length);
215 dest.writeByteArray(remoteAddress);
216 dest.writeInt(mRemoteSocketAddress.getPort());
217 }
sewookseo82657d72022-03-07 06:31:57 +0000218 dest.writeInt(mSocketType);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700219 }
220
221 @NonNull
222 public static final Parcelable.Creator<QosSocketInfo> CREATOR =
223 new Parcelable.Creator<QosSocketInfo>() {
224 @NonNull
225 @Override
226 public QosSocketInfo createFromParcel(final Parcel in) {
227 return new QosSocketInfo(in);
228 }
229
230 @NonNull
231 @Override
232 public QosSocketInfo[] newArray(final int size) {
233 return new QosSocketInfo[size];
234 }
235 };
236}