blob: 39c2f334d339d875c2b2fa1a0357fc032e882dea [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
76 */
77 @NonNull
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
90 public InetSocketAddress getLocalSocketAddress() {
91 return mLocalSocketAddress;
92 }
93
94 /**
Jayachandran Cb5335502021-04-19 18:21:36 -070095 * 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
102 public InetSocketAddress getRemoteSocketAddress() {
103 return mRemoteSocketAddress;
104 }
105
106 /**
sewookseo82657d72022-03-07 06:31:57 +0000107 * 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 */
112 public int getSocketType() {
113 return mSocketType;
114 }
115
116 /**
Daniel Brightf9e945b2020-06-15 16:10:01 -0700117 * 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 */
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");
Remi NGUYEN VAN0942ad92021-03-09 23:53:55 +0000128 mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700129 mLocalSocketAddress =
130 new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
sewookseo82657d72022-03-07 06:31:57 +0000131 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 */
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;
Jayachandran Cb5335502021-04-19 18:21:36 -0700157
158 if (socket.isConnected()) {
159 mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
160 } else {
161 mRemoteSocketAddress = null;
162 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700163 }
164
165 /* Parcelable methods */
166 private QosSocketInfo(final Parcel in) {
167 mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
168 mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
169
Jayachandran Cb5335502021-04-19 18:21:36 -0700170 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);
sewookseo82657d72022-03-07 06:31:57 +0000176
177 mSocketType = in.readInt();
Daniel Brightf9e945b2020-06-15 16:10:01 -0700178 }
179
Jayachandran Cb5335502021-04-19 18:21:36 -0700180 private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
Daniel Brightf9e945b2020-06-15 16:10:01 -0700181 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) {
Remi NGUYEN VANd059f212021-03-11 07:43:37 +0000188 /* This can never happen. UnknownHostException will never be thrown
Daniel Brightf9e945b2020-06-15 16:10:01 -0700189 since the address provided is numeric and non-null. */
Remi NGUYEN VANd059f212021-03-11 07:43:37 +0000190 throw new RuntimeException("UnknownHostException on numeric address", e);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700191 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700192 }
193
194 @Override
195 public int describeContents() {
196 return 0;
197 }
198
199 @Override
200 public void writeToParcel(@NonNull final Parcel dest, final int flags) {
201 mNetwork.writeToParcel(dest, 0);
202 mParcelFileDescriptor.writeToParcel(dest, 0);
203
Jayachandran Cb5335502021-04-19 18:21:36 -0700204 final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
205 dest.writeInt(localAddress.length);
206 dest.writeByteArray(localAddress);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700207 dest.writeInt(mLocalSocketAddress.getPort());
Jayachandran Cb5335502021-04-19 18:21:36 -0700208
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 }
sewookseo82657d72022-03-07 06:31:57 +0000217 dest.writeInt(mSocketType);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700218 }
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}