blob: a45d5075d6c77bf6af984af80a2422bd5a9f1278 [file] [log] [blame]
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +09001/*
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
19import android.annotation.NonNull;
Jayachandran C735e1ce2021-04-19 18:21:36 -070020import android.annotation.Nullable;
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +090021import android.annotation.SystemApi;
22import android.os.Parcel;
23import android.os.ParcelFileDescriptor;
24import android.os.Parcelable;
25
26import java.io.IOException;
27import java.net.InetAddress;
28import java.net.InetSocketAddress;
29import java.net.Socket;
30import java.net.UnknownHostException;
31import java.util.Objects;
32
33/**
34 * Used in conjunction with
35 * {@link ConnectivityManager#registerQosCallback}
Jayachandran C735e1ce2021-04-19 18:21:36 -070036 * in order to receive Qos Sessions related to the local address and port of a bound {@link Socket}
37 * and/or remote address and port of a connected {@link Socket}.
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +090038 *
39 * @hide
40 */
41@SystemApi
42public final class QosSocketInfo implements Parcelable {
43
44 @NonNull
45 private final Network mNetwork;
46
47 @NonNull
48 private final ParcelFileDescriptor mParcelFileDescriptor;
49
50 @NonNull
51 private final InetSocketAddress mLocalSocketAddress;
52
Jayachandran C735e1ce2021-04-19 18:21:36 -070053 @Nullable
54 private final InetSocketAddress mRemoteSocketAddress;
55
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +090056 /**
57 * The {@link Network} the socket is on.
58 *
59 * @return the registered {@link Network}
60 */
61 @NonNull
62 public Network getNetwork() {
63 return mNetwork;
64 }
65
66 /**
67 * The parcel file descriptor wrapped around the socket's file descriptor.
68 *
69 * @return the parcel file descriptor of the socket
70 */
71 @NonNull
72 ParcelFileDescriptor getParcelFileDescriptor() {
73 return mParcelFileDescriptor;
74 }
75
76 /**
77 * The local address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
78 * The value does not reflect any changes that occur to the socket after it is first set
79 * in the constructor.
80 *
81 * @return the local address of the socket
82 */
83 @NonNull
84 public InetSocketAddress getLocalSocketAddress() {
85 return mLocalSocketAddress;
86 }
87
88 /**
Jayachandran C735e1ce2021-04-19 18:21:36 -070089 * The remote address of the socket passed into {@link QosSocketInfo(Network, Socket)}.
90 * The value does not reflect any changes that occur to the socket after it is first set
91 * in the constructor.
92 *
93 * @return the remote address of the socket if socket is connected, null otherwise
94 */
95 @Nullable
96 public InetSocketAddress getRemoteSocketAddress() {
97 return mRemoteSocketAddress;
98 }
99
100 /**
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900101 * Creates a {@link QosSocketInfo} given a {@link Network} and bound {@link Socket}. The
102 * {@link Socket} must remain bound in order to receive {@link QosSession}s.
103 *
104 * @param network the network
105 * @param socket the bound {@link Socket}
106 */
107 public QosSocketInfo(@NonNull final Network network, @NonNull final Socket socket)
108 throws IOException {
109 Objects.requireNonNull(socket, "socket cannot be null");
110
111 mNetwork = Objects.requireNonNull(network, "network cannot be null");
Remi NGUYEN VAN61c0b1a2021-03-09 23:53:55 +0000112 mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket);
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900113 mLocalSocketAddress =
114 new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
Jayachandran C735e1ce2021-04-19 18:21:36 -0700115
116 if (socket.isConnected()) {
117 mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
118 } else {
119 mRemoteSocketAddress = null;
120 }
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900121 }
122
123 /* Parcelable methods */
124 private QosSocketInfo(final Parcel in) {
125 mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
126 mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
127
Jayachandran C735e1ce2021-04-19 18:21:36 -0700128 final int localAddressLength = in.readInt();
129 mLocalSocketAddress = readSocketAddress(in, localAddressLength);
130
131 final int remoteAddressLength = in.readInt();
132 mRemoteSocketAddress = remoteAddressLength == 0 ? null
133 : readSocketAddress(in, remoteAddressLength);
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900134 }
135
Jayachandran C735e1ce2021-04-19 18:21:36 -0700136 private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900137 final byte[] address = new byte[addressLength];
138 in.readByteArray(address);
139 final int port = in.readInt();
140
141 try {
142 return new InetSocketAddress(InetAddress.getByAddress(address), port);
143 } catch (final UnknownHostException e) {
Remi NGUYEN VAN07051bc2021-03-11 07:43:37 +0000144 /* This can never happen. UnknownHostException will never be thrown
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900145 since the address provided is numeric and non-null. */
Remi NGUYEN VAN07051bc2021-03-11 07:43:37 +0000146 throw new RuntimeException("UnknownHostException on numeric address", e);
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900147 }
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900148 }
149
150 @Override
151 public int describeContents() {
152 return 0;
153 }
154
155 @Override
156 public void writeToParcel(@NonNull final Parcel dest, final int flags) {
157 mNetwork.writeToParcel(dest, 0);
158 mParcelFileDescriptor.writeToParcel(dest, 0);
159
Jayachandran C735e1ce2021-04-19 18:21:36 -0700160 final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
161 dest.writeInt(localAddress.length);
162 dest.writeByteArray(localAddress);
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900163 dest.writeInt(mLocalSocketAddress.getPort());
Jayachandran C735e1ce2021-04-19 18:21:36 -0700164
165 if (mRemoteSocketAddress == null) {
166 dest.writeInt(0);
167 } else {
168 final byte[] remoteAddress = mRemoteSocketAddress.getAddress().getAddress();
169 dest.writeInt(remoteAddress.length);
170 dest.writeByteArray(remoteAddress);
171 dest.writeInt(mRemoteSocketAddress.getPort());
172 }
Remi NGUYEN VAN070ff8b2021-03-01 17:53:45 +0900173 }
174
175 @NonNull
176 public static final Parcelable.Creator<QosSocketInfo> CREATOR =
177 new Parcelable.Creator<QosSocketInfo>() {
178 @NonNull
179 @Override
180 public QosSocketInfo createFromParcel(final Parcel in) {
181 return new QosSocketInfo(in);
182 }
183
184 @NonNull
185 @Override
186 public QosSocketInfo[] newArray(final int size) {
187 return new QosSocketInfo[size];
188 }
189 };
190}