• 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 android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.ParcelFileDescriptor;
24 import android.os.Parcelable;
25 
26 import java.io.IOException;
27 import java.net.InetAddress;
28 import java.net.InetSocketAddress;
29 import java.net.Socket;
30 import java.net.UnknownHostException;
31 import java.util.Objects;
32 
33 /**
34  * Used in conjunction with
35  * {@link ConnectivityManager#registerQosCallback}
36  * 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}.
38  *
39  * @hide
40  */
41 @SystemApi
42 public 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 
53     @Nullable
54     private final InetSocketAddress mRemoteSocketAddress;
55 
56     /**
57      * The {@link Network} the socket is on.
58      *
59      * @return the registered {@link Network}
60      */
61     @NonNull
getNetwork()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
getParcelFileDescriptor()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
getLocalSocketAddress()84     public InetSocketAddress getLocalSocketAddress() {
85         return mLocalSocketAddress;
86     }
87 
88     /**
89      * 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
getRemoteSocketAddress()96     public InetSocketAddress getRemoteSocketAddress() {
97         return mRemoteSocketAddress;
98     }
99 
100     /**
101      * 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      */
QosSocketInfo(@onNull final Network network, @NonNull final Socket socket)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");
112         mParcelFileDescriptor = ParcelFileDescriptor.fromSocket(socket);
113         mLocalSocketAddress =
114                 new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort());
115 
116         if (socket.isConnected()) {
117             mRemoteSocketAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
118         } else {
119             mRemoteSocketAddress = null;
120         }
121     }
122 
123     /* Parcelable methods */
QosSocketInfo(final Parcel in)124     private QosSocketInfo(final Parcel in) {
125         mNetwork = Objects.requireNonNull(Network.CREATOR.createFromParcel(in));
126         mParcelFileDescriptor = ParcelFileDescriptor.CREATOR.createFromParcel(in);
127 
128         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);
134     }
135 
readSocketAddress(final Parcel in, final int addressLength)136     private @NonNull InetSocketAddress readSocketAddress(final Parcel in, final int addressLength) {
137         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) {
144             /* This can never happen. UnknownHostException will never be thrown
145                since the address provided is numeric and non-null. */
146             throw new RuntimeException("UnknownHostException on numeric address", e);
147         }
148     }
149 
150     @Override
describeContents()151     public int describeContents() {
152         return 0;
153     }
154 
155     @Override
writeToParcel(@onNull final Parcel dest, final int flags)156     public void writeToParcel(@NonNull final Parcel dest, final int flags) {
157         mNetwork.writeToParcel(dest, 0);
158         mParcelFileDescriptor.writeToParcel(dest, 0);
159 
160         final byte[] localAddress = mLocalSocketAddress.getAddress().getAddress();
161         dest.writeInt(localAddress.length);
162         dest.writeByteArray(localAddress);
163         dest.writeInt(mLocalSocketAddress.getPort());
164 
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         }
173     }
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 }
191