• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 package android.net.util;
17 
18 import android.net.TetherStatsParcel;
19 import android.net.TetheringRequestParcel;
20 import android.util.Log;
21 
22 import androidx.annotation.NonNull;
23 
24 import com.android.networkstack.tethering.TetherStatsValue;
25 
26 import java.io.FileDescriptor;
27 import java.net.Inet6Address;
28 import java.net.SocketException;
29 import java.net.UnknownHostException;
30 import java.util.Arrays;
31 import java.util.Objects;
32 
33 /**
34  * The classes and the methods for tethering utilization.
35  *
36  * {@hide}
37  */
38 public class TetheringUtils {
39     static {
40         System.loadLibrary("tetherutilsjni");
41     }
42 
43     public static final byte[] ALL_NODES = new byte[] {
44         (byte) 0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
45     };
46 
47     /**
48      * Configures a socket for receiving and sending ICMPv6 neighbor advertisments.
49      * @param fd the socket's {@link FileDescriptor}.
50      */
setupNaSocket(FileDescriptor fd)51     public static native void setupNaSocket(FileDescriptor fd)
52             throws SocketException;
53 
54     /**
55      * Configures a socket for receiving and sending ICMPv6 neighbor solicitations.
56      * @param fd the socket's {@link FileDescriptor}.
57      */
setupNsSocket(FileDescriptor fd)58     public static native void setupNsSocket(FileDescriptor fd)
59             throws SocketException;
60 
61     /**
62      *  The object which records offload Tx/Rx forwarded bytes/packets.
63      *  TODO: Replace the inner class ForwardedStats of class OffloadHardwareInterface with
64      *  this class as well.
65      */
66     public static class ForwardedStats {
67         public final long rxBytes;
68         public final long rxPackets;
69         public final long txBytes;
70         public final long txPackets;
71 
ForwardedStats()72         public ForwardedStats() {
73             rxBytes = 0;
74             rxPackets = 0;
75             txBytes = 0;
76             txPackets = 0;
77         }
78 
ForwardedStats(long rxBytes, long txBytes)79         public ForwardedStats(long rxBytes, long txBytes) {
80             this.rxBytes = rxBytes;
81             this.rxPackets = 0;
82             this.txBytes = txBytes;
83             this.txPackets = 0;
84         }
85 
ForwardedStats(long rxBytes, long rxPackets, long txBytes, long txPackets)86         public ForwardedStats(long rxBytes, long rxPackets, long txBytes, long txPackets) {
87             this.rxBytes = rxBytes;
88             this.rxPackets = rxPackets;
89             this.txBytes = txBytes;
90             this.txPackets = txPackets;
91         }
92 
ForwardedStats(@onNull TetherStatsParcel tetherStats)93         public ForwardedStats(@NonNull TetherStatsParcel tetherStats) {
94             rxBytes = tetherStats.rxBytes;
95             rxPackets = tetherStats.rxPackets;
96             txBytes = tetherStats.txBytes;
97             txPackets = tetherStats.txPackets;
98         }
99 
ForwardedStats(@onNull TetherStatsValue tetherStats)100         public ForwardedStats(@NonNull TetherStatsValue tetherStats) {
101             rxBytes = tetherStats.rxBytes;
102             rxPackets = tetherStats.rxPackets;
103             txBytes = tetherStats.txBytes;
104             txPackets = tetherStats.txPackets;
105         }
106 
ForwardedStats(@onNull ForwardedStats other)107         public ForwardedStats(@NonNull ForwardedStats other) {
108             rxBytes = other.rxBytes;
109             rxPackets = other.rxPackets;
110             txBytes = other.txBytes;
111             txPackets = other.txPackets;
112         }
113 
114         /** Add Tx/Rx bytes/packets and return the result as a new object. */
115         @NonNull
add(@onNull ForwardedStats other)116         public ForwardedStats add(@NonNull ForwardedStats other) {
117             return new ForwardedStats(rxBytes + other.rxBytes, rxPackets + other.rxPackets,
118                     txBytes + other.txBytes, txPackets + other.txPackets);
119         }
120 
121         /** Subtract Tx/Rx bytes/packets and return the result as a new object. */
122         @NonNull
subtract(@onNull ForwardedStats other)123         public ForwardedStats subtract(@NonNull ForwardedStats other) {
124             // TODO: Perhaps throw an exception if any negative difference value just in case.
125             final long rxBytesDiff = Math.max(rxBytes - other.rxBytes, 0);
126             final long rxPacketsDiff = Math.max(rxPackets - other.rxPackets, 0);
127             final long txBytesDiff = Math.max(txBytes - other.txBytes, 0);
128             final long txPacketsDiff = Math.max(txPackets - other.txPackets, 0);
129             return new ForwardedStats(rxBytesDiff, rxPacketsDiff, txBytesDiff, txPacketsDiff);
130         }
131 
132         /** Returns the string representation of this object. */
133         @NonNull
toString()134         public String toString() {
135             return String.format("ForwardedStats(rxb: %d, rxp: %d, txb: %d, txp: %d)", rxBytes,
136                     rxPackets, txBytes, txPackets);
137         }
138     }
139 
140     /**
141      * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
142      * @param fd the socket's {@link FileDescriptor}.
143      * @param ifIndex the interface index.
144      */
setupRaSocket(FileDescriptor fd, int ifIndex)145     public static native void setupRaSocket(FileDescriptor fd, int ifIndex)
146             throws SocketException;
147 
148     /**
149      * Read s as an unsigned 16-bit integer.
150      */
uint16(short s)151     public static int uint16(short s) {
152         return s & 0xffff;
153     }
154 
155     /** Check whether two TetheringRequestParcels are the same. */
isTetheringRequestEquals(final TetheringRequestParcel request, final TetheringRequestParcel otherRequest)156     public static boolean isTetheringRequestEquals(final TetheringRequestParcel request,
157             final TetheringRequestParcel otherRequest) {
158         if (request == otherRequest) return true;
159 
160         return request != null && otherRequest != null
161                 && request.tetheringType == otherRequest.tetheringType
162                 && Objects.equals(request.localIPv4Address, otherRequest.localIPv4Address)
163                 && Objects.equals(request.staticClientAddress, otherRequest.staticClientAddress)
164                 && request.exemptFromEntitlementCheck == otherRequest.exemptFromEntitlementCheck
165                 && request.showProvisioningUi == otherRequest.showProvisioningUi
166                 && request.connectivityScope == otherRequest.connectivityScope;
167     }
168 
169     /** Get inet6 address for all nodes given scope ID. */
getAllNodesForScopeId(int scopeId)170     public static Inet6Address getAllNodesForScopeId(int scopeId) {
171         try {
172             return Inet6Address.getByAddress("ff02::1", ALL_NODES, scopeId);
173         } catch (UnknownHostException uhe) {
174             Log.wtf("TetheringUtils", "Failed to construct Inet6Address from "
175                     + Arrays.toString(ALL_NODES) + " and scopedId " + scopeId);
176             return null;
177         }
178     }
179 }
180