blob: da9b356050391974b07756869c399a612397f886 [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 VAN53eb35c2022-04-20 15:59:16 +090076 * @hide
Daniel Brightf9e945b2020-06-15 16:10:01 -070077 */
78 @NonNull
Remi NGUYEN VAN53eb35c2022-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));
sewookseoafc22b02022-03-07 11:03:13 +0000169 final boolean withFd = in.readBoolean();
170 if (withFd) {
171 mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
172 } else {
173 mParcelFileDescriptor = null;
174 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700175
sewookseoafc22b02022-03-07 11:03:13 +0000176 mLocalSocketAddress = readSocketAddress(in);
177 mRemoteSocketAddress = readSocketAddress(in);
sewookseo82657d72022-03-07 06:31:57 +0000178
179 mSocketType = in.readInt();
Daniel Brightf9e945b2020-06-15 16:10:01 -0700180 }
181
sewookseoafc22b02022-03-07 11:03:13 +0000182 private InetSocketAddress readSocketAddress(final Parcel in) {
183 final byte[] addrBytes = in.createByteArray();
184 if (addrBytes == null) {
185 return null;
186 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700187 final int port = in.readInt();
188
189 try {
sewookseoafc22b02022-03-07 11:03:13 +0000190 return new InetSocketAddress(InetAddress.getByAddress(addrBytes), port);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700191 } catch (final UnknownHostException e) {
Remi NGUYEN VANd059f212021-03-11 07:43:37 +0000192 /* This can never happen. UnknownHostException will never be thrown
Daniel Brightf9e945b2020-06-15 16:10:01 -0700193 since the address provided is numeric and non-null. */
Remi NGUYEN VANd059f212021-03-11 07:43:37 +0000194 throw new RuntimeException("UnknownHostException on numeric address", e);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700195 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700196 }
197
198 @Override
199 public int describeContents() {
200 return 0;
201 }
202
203 @Override
204 public void writeToParcel(@NonNull final Parcel dest, final int flags) {
sewookseoafc22b02022-03-07 11:03:13 +0000205 writeToParcelInternal(dest, flags, /*includeFd=*/ true);
206 }
Daniel Brightf9e945b2020-06-15 16:10:01 -0700207
sewookseoafc22b02022-03-07 11:03:13 +0000208 /**
209 * Used when sending QosSocketInfo to telephony, which does not need access to the socket FD.
210 * @hide
211 */
212 public void writeToParcelWithoutFd(@NonNull final Parcel dest, final int flags) {
213 writeToParcelInternal(dest, flags, /*includeFd=*/ false);
214 }
215
216 private void writeToParcelInternal(
217 @NonNull final Parcel dest, final int flags, boolean includeFd) {
218 mNetwork.writeToParcel(dest, 0);
219
220 if (includeFd) {
221 dest.writeBoolean(true);
222 mParcelFileDescriptor.writeToParcel(dest, 0);
223 } else {
224 dest.writeBoolean(false);
225 }
226
227 dest.writeByteArray(mLocalSocketAddress.getAddress().getAddress());
Daniel Brightf9e945b2020-06-15 16:10:01 -0700228 dest.writeInt(mLocalSocketAddress.getPort());
Jayachandran Cb5335502021-04-19 18:21:36 -0700229
230 if (mRemoteSocketAddress == null) {
sewookseoafc22b02022-03-07 11:03:13 +0000231 dest.writeByteArray(null);
Jayachandran Cb5335502021-04-19 18:21:36 -0700232 } else {
sewookseoafc22b02022-03-07 11:03:13 +0000233 dest.writeByteArray(mRemoteSocketAddress.getAddress().getAddress());
Jayachandran Cb5335502021-04-19 18:21:36 -0700234 dest.writeInt(mRemoteSocketAddress.getPort());
235 }
sewookseo82657d72022-03-07 06:31:57 +0000236 dest.writeInt(mSocketType);
Daniel Brightf9e945b2020-06-15 16:10:01 -0700237 }
238
239 @NonNull
240 public static final Parcelable.Creator<QosSocketInfo> CREATOR =
241 new Parcelable.Creator<QosSocketInfo>() {
242 @NonNull
243 @Override
244 public QosSocketInfo createFromParcel(final Parcel in) {
245 return new QosSocketInfo(in);
246 }
247
248 @NonNull
249 @Override
250 public QosSocketInfo[] newArray(final int size) {
251 return new QosSocketInfo[size];
252 }
253 };
254}