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 
21 import androidx.annotation.NonNull;
22 
23 import java.io.FileDescriptor;
24 import java.net.SocketException;
25 import java.util.Objects;
26 
27 /**
28  * The classes and the methods for tethering utilization.
29  *
30  * {@hide}
31  */
32 public class TetheringUtils {
33     /**
34      *  The object which records offload Tx/Rx forwarded bytes/packets.
35      *  TODO: Replace the inner class ForwardedStats of class OffloadHardwareInterface with
36      *  this class as well.
37      */
38     public static class ForwardedStats {
39         public final long rxBytes;
40         public final long rxPackets;
41         public final long txBytes;
42         public final long txPackets;
43 
ForwardedStats()44         public ForwardedStats() {
45             rxBytes = 0;
46             rxPackets = 0;
47             txBytes = 0;
48             txPackets = 0;
49         }
50 
ForwardedStats(long rxBytes, long txBytes)51         public ForwardedStats(long rxBytes, long txBytes) {
52             this.rxBytes = rxBytes;
53             this.rxPackets = 0;
54             this.txBytes = txBytes;
55             this.txPackets = 0;
56         }
57 
ForwardedStats(long rxBytes, long rxPackets, long txBytes, long txPackets)58         public ForwardedStats(long rxBytes, long rxPackets, long txBytes, long txPackets) {
59             this.rxBytes = rxBytes;
60             this.rxPackets = rxPackets;
61             this.txBytes = txBytes;
62             this.txPackets = txPackets;
63         }
64 
ForwardedStats(@onNull TetherStatsParcel tetherStats)65         public ForwardedStats(@NonNull TetherStatsParcel tetherStats) {
66             rxBytes = tetherStats.rxBytes;
67             rxPackets = tetherStats.rxPackets;
68             txBytes = tetherStats.txBytes;
69             txPackets = tetherStats.txPackets;
70         }
71 
ForwardedStats(@onNull ForwardedStats other)72         public ForwardedStats(@NonNull ForwardedStats other) {
73             rxBytes = other.rxBytes;
74             rxPackets = other.rxPackets;
75             txBytes = other.txBytes;
76             txPackets = other.txPackets;
77         }
78 
79         /** Add Tx/Rx bytes/packets and return the result as a new object. */
80         @NonNull
add(@onNull ForwardedStats other)81         public ForwardedStats add(@NonNull ForwardedStats other) {
82             return new ForwardedStats(rxBytes + other.rxBytes, rxPackets + other.rxPackets,
83                     txBytes + other.txBytes, txPackets + other.txPackets);
84         }
85 
86         /** Subtract Tx/Rx bytes/packets and return the result as a new object. */
87         @NonNull
subtract(@onNull ForwardedStats other)88         public ForwardedStats subtract(@NonNull ForwardedStats other) {
89             // TODO: Perhaps throw an exception if any negative difference value just in case.
90             final long rxBytesDiff = Math.max(rxBytes - other.rxBytes, 0);
91             final long rxPacketsDiff = Math.max(rxPackets - other.rxPackets, 0);
92             final long txBytesDiff = Math.max(txBytes - other.txBytes, 0);
93             final long txPacketsDiff = Math.max(txPackets - other.txPackets, 0);
94             return new ForwardedStats(rxBytesDiff, rxPacketsDiff, txBytesDiff, txPacketsDiff);
95         }
96 
97         /** Returns the string representation of this object. */
98         @NonNull
toString()99         public String toString() {
100             return String.format("ForwardedStats(rxb: %d, rxp: %d, txb: %d, txp: %d)", rxBytes,
101                     rxPackets, txBytes, txPackets);
102         }
103     }
104 
105     /**
106      * Configures a socket for receiving ICMPv6 router solicitations and sending advertisements.
107      * @param fd the socket's {@link FileDescriptor}.
108      * @param ifIndex the interface index.
109      */
setupRaSocket(FileDescriptor fd, int ifIndex)110     public static native void setupRaSocket(FileDescriptor fd, int ifIndex)
111             throws SocketException;
112 
113     /**
114      * Read s as an unsigned 16-bit integer.
115      */
uint16(short s)116     public static int uint16(short s) {
117         return s & 0xffff;
118     }
119 
120     /** Check whether two TetheringRequestParcels are the same. */
isTetheringRequestEquals(final TetheringRequestParcel request, final TetheringRequestParcel otherRequest)121     public static boolean isTetheringRequestEquals(final TetheringRequestParcel request,
122             final TetheringRequestParcel otherRequest) {
123         if (request == otherRequest) return true;
124 
125         return request != null && otherRequest != null
126                 && request.tetheringType == otherRequest.tetheringType
127                 && Objects.equals(request.localIPv4Address, otherRequest.localIPv4Address)
128                 && Objects.equals(request.staticClientAddress, otherRequest.staticClientAddress)
129                 && request.exemptFromEntitlementCheck == otherRequest.exemptFromEntitlementCheck
130                 && request.showProvisioningUi == otherRequest.showProvisioningUi;
131     }
132 }
133