blob: 29900d9bebd9e2bd6799d8311001a8825362fa25 [file] [log] [blame]
markchienf87ebdc2019-12-07 22:02:28 +08001/*
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 */
16package android.net.util;
17
Hungming Chend0216992020-05-08 17:50:53 +080018import android.net.TetherStatsParcel;
markchienf053e4b2020-03-16 21:49:48 +080019import android.net.TetheringRequestParcel;
Tyler Wear90e40632020-03-13 11:38:38 -070020import android.util.Log;
markchienf053e4b2020-03-16 21:49:48 +080021
Hungming Chend0216992020-05-08 17:50:53 +080022import androidx.annotation.NonNull;
23
Hungming Chenb350d752020-12-29 21:15:01 +080024import com.android.networkstack.tethering.TetherStatsValue;
25
markchienf87ebdc2019-12-07 22:02:28 +080026import java.io.FileDescriptor;
Tyler Wear90e40632020-03-13 11:38:38 -070027import java.net.Inet6Address;
markchienf87ebdc2019-12-07 22:02:28 +080028import java.net.SocketException;
Tyler Wear90e40632020-03-13 11:38:38 -070029import java.net.UnknownHostException;
30import java.util.Arrays;
markchienf053e4b2020-03-16 21:49:48 +080031import java.util.Objects;
markchienf87ebdc2019-12-07 22:02:28 +080032
33/**
Hungming Chend0216992020-05-08 17:50:53 +080034 * The classes and the methods for tethering utilization.
markchienf87ebdc2019-12-07 22:02:28 +080035 *
36 * {@hide}
37 */
38public class TetheringUtils {
Lorenzo Colitti68008112021-02-10 15:26:24 +090039 static {
40 System.loadLibrary("tetherutilsjni");
41 }
42
Tyler Wear90e40632020-03-13 11:38:38 -070043 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 */
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 */
58 public static native void setupNsSocket(FileDescriptor fd)
59 throws SocketException;
60
markchienf87ebdc2019-12-07 22:02:28 +080061 /**
Hungming Chend0216992020-05-08 17:50:53 +080062 * 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
72 public ForwardedStats() {
73 rxBytes = 0;
74 rxPackets = 0;
75 txBytes = 0;
76 txPackets = 0;
77 }
78
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
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
93 public ForwardedStats(@NonNull TetherStatsParcel tetherStats) {
94 rxBytes = tetherStats.rxBytes;
95 rxPackets = tetherStats.rxPackets;
96 txBytes = tetherStats.txBytes;
97 txPackets = tetherStats.txPackets;
98 }
99
Hungming Chenb350d752020-12-29 21:15:01 +0800100 public ForwardedStats(@NonNull TetherStatsValue tetherStats) {
101 rxBytes = tetherStats.rxBytes;
102 rxPackets = tetherStats.rxPackets;
103 txBytes = tetherStats.txBytes;
104 txPackets = tetherStats.txPackets;
105 }
106
Hungming Chend0216992020-05-08 17:50:53 +0800107 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
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
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
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 /**
markchienf87ebdc2019-12-07 22:02:28 +0800141 * 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 */
145 public static native void setupRaSocket(FileDescriptor fd, int ifIndex)
146 throws SocketException;
markchien6cf0e552019-12-06 15:24:53 +0800147
148 /**
149 * Read s as an unsigned 16-bit integer.
150 */
151 public static int uint16(short s) {
152 return s & 0xffff;
153 }
markchienf053e4b2020-03-16 21:49:48 +0800154
155 /** Check whether two TetheringRequestParcels are the same. */
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
Lorenzo Colitti8a36c292021-04-13 17:17:44 +0900165 && request.showProvisioningUi == otherRequest.showProvisioningUi
166 && request.connectivityScope == otherRequest.connectivityScope;
markchienf053e4b2020-03-16 21:49:48 +0800167 }
Tyler Wear90e40632020-03-13 11:38:38 -0700168
169 /** Get inet6 address for all nodes given scope ID. */
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 }
markchienf87ebdc2019-12-07 22:02:28 +0800179}