• 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.netstats.provider;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.net.NetworkStats;
23 import android.os.RemoteException;
24 
25 /**
26  * A base class that allows external modules to implement a custom network statistics provider.
27  * @hide
28  */
29 @SystemApi
30 public abstract class NetworkStatsProvider {
31     /**
32      * A value used by {@link #onSetLimit}, {@link #onSetAlert} and {@link #onSetWarningAndLimit}
33      * indicates there is no limit.
34      */
35     public static final int QUOTA_UNLIMITED = -1;
36 
37     @NonNull private final INetworkStatsProvider mProviderBinder =
38             new INetworkStatsProvider.Stub() {
39 
40         @Override
41         public void onRequestStatsUpdate(int token) {
42             NetworkStatsProvider.this.onRequestStatsUpdate(token);
43         }
44 
45         @Override
46         public void onSetAlert(long quotaBytes) {
47             NetworkStatsProvider.this.onSetAlert(quotaBytes);
48         }
49 
50         @Override
51         public void onSetWarningAndLimit(String iface, long warningBytes, long limitBytes) {
52             NetworkStatsProvider.this.onSetWarningAndLimit(iface, warningBytes, limitBytes);
53         }
54     };
55 
56     // The binder given by the service when successfully registering. Only null before registering,
57     // never null once non-null.
58     @Nullable
59     private INetworkStatsProviderCallback mProviderCbBinder;
60 
61     /**
62      * Return the binder invoked by the service and redirect function calls to the overridden
63      * methods.
64      * @hide
65      */
66     @NonNull
getProviderBinder()67     public INetworkStatsProvider getProviderBinder() {
68         return mProviderBinder;
69     }
70 
71     /**
72      * Store the binder that was returned by the service when successfully registering. Note that
73      * the provider cannot be re-registered. Hence this method can only be called once per provider.
74      *
75      * @hide
76      */
setProviderCallbackBinder(@onNull INetworkStatsProviderCallback binder)77     public void setProviderCallbackBinder(@NonNull INetworkStatsProviderCallback binder) {
78         if (mProviderCbBinder != null) {
79             throw new IllegalArgumentException("provider is already registered");
80         }
81         mProviderCbBinder = binder;
82     }
83 
84     /**
85      * Get the binder that was returned by the service when successfully registering. Or null if the
86      * provider was never registered.
87      *
88      * @hide
89      */
90     @Nullable
getProviderCallbackBinder()91     public INetworkStatsProviderCallback getProviderCallbackBinder() {
92         return mProviderCbBinder;
93     }
94 
95     /**
96      * Get the binder that was returned by the service when successfully registering. Throw an
97      * {@link IllegalStateException} if the provider is not registered.
98      *
99      * @hide
100      */
101     @NonNull
getProviderCallbackBinderOrThrow()102     public INetworkStatsProviderCallback getProviderCallbackBinderOrThrow() {
103         if (mProviderCbBinder == null) {
104             throw new IllegalStateException("the provider is not registered");
105         }
106         return mProviderCbBinder;
107     }
108 
109     /**
110      * Notify the system of new network statistics.
111      *
112      * Send the network statistics recorded since the last call to {@link #notifyStatsUpdated}. Must
113      * be called as soon as possible after {@link NetworkStatsProvider#onRequestStatsUpdate(int)}
114      * being called. Responding later increases the probability stats will be dropped. The
115      * provider can also call this whenever it wants to reports new stats for any reason.
116      * Note that the system will not necessarily immediately propagate the statistics to
117      * reflect the update.
118      *
119      * @param token the token under which these stats were gathered. Providers can call this method
120      *              with the current token as often as they want, until the token changes.
121      *              {@see NetworkStatsProvider#onRequestStatsUpdate()}
122      * @param ifaceStats the {@link NetworkStats} per interface to be reported.
123      *                   The provider should not include any traffic that is already counted by
124      *                   kernel interface counters.
125      * @param uidStats the same stats as above, but counts {@link NetworkStats}
126      *                 per uid.
127      */
notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats, @NonNull NetworkStats uidStats)128     public void notifyStatsUpdated(int token, @NonNull NetworkStats ifaceStats,
129             @NonNull NetworkStats uidStats) {
130         try {
131             getProviderCallbackBinderOrThrow().notifyStatsUpdated(token, ifaceStats, uidStats);
132         } catch (RemoteException e) {
133             e.rethrowAsRuntimeException();
134         }
135     }
136 
137     /**
138      * Notify system that the quota set by {@code onSetAlert} has been reached.
139      */
notifyAlertReached()140     public void notifyAlertReached() {
141         try {
142             getProviderCallbackBinderOrThrow().notifyAlertReached();
143         } catch (RemoteException e) {
144             e.rethrowAsRuntimeException();
145         }
146     }
147 
148     /**
149      * Notify system that the warning set by {@link #onSetWarningAndLimit} has been reached.
150      */
notifyWarningReached()151     public void notifyWarningReached() {
152         try {
153             // Reuse the code path to notify warning reached with limit reached
154             // since framework handles them in the same way.
155             getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached();
156         } catch (RemoteException e) {
157             e.rethrowAsRuntimeException();
158         }
159     }
160 
161     /**
162      * Notify system that the quota set by {@link #onSetLimit} or limit set by
163      * {@link #onSetWarningAndLimit} has been reached.
164      */
notifyLimitReached()165     public void notifyLimitReached() {
166         try {
167             getProviderCallbackBinderOrThrow().notifyWarningOrLimitReached();
168         } catch (RemoteException e) {
169             e.rethrowAsRuntimeException();
170         }
171     }
172 
173     /**
174      * Called by {@code NetworkStatsService} when it requires to know updated stats.
175      * The provider MUST respond by calling {@link #notifyStatsUpdated} as soon as possible.
176      * Responding later increases the probability stats will be dropped. Memory allowing, the
177      * system will try to take stats into account up to one minute after calling
178      * {@link #onRequestStatsUpdate}.
179      *
180      * @param token a positive number identifying the new state of the system under which
181      *              {@link NetworkStats} have to be gathered from now on. When this is called,
182      *              custom implementations of providers MUST tally and report the latest stats with
183      *              the previous token, under which stats were being gathered so far.
184      */
onRequestStatsUpdate(int token)185     public abstract void onRequestStatsUpdate(int token);
186 
187     /**
188      * Called by {@code NetworkStatsService} when setting the interface quota for the specified
189      * upstream interface. When this is called, the custom implementation should block all egress
190      * packets on the {@code iface} associated with the provider when {@code quotaBytes} bytes have
191      * been reached, and MUST respond to it by calling
192      * {@link NetworkStatsProvider#notifyLimitReached()}.
193      *
194      * @param iface the interface requiring the operation.
195      * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
196      *                   from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
197      */
onSetLimit(@onNull String iface, long quotaBytes)198     public abstract void onSetLimit(@NonNull String iface, long quotaBytes);
199 
200     /**
201      * Called by {@code NetworkStatsService} when setting the interface quotas for the specified
202      * upstream interface. If a provider implements {@link #onSetWarningAndLimit}, the system
203      * will not call {@link #onSetLimit}. When this method is called, the implementation
204      * should behave as follows:
205      *   1. If {@code warningBytes} is reached on {@code iface}, block all further traffic on
206      *      {@code iface} and call {@link NetworkStatsProvider@notifyWarningReached()}.
207      *   2. If {@code limitBytes} is reached on {@code iface}, block all further traffic on
208      *   {@code iface} and call {@link NetworkStatsProvider#notifyLimitReached()}.
209      *
210      * @param iface the interface requiring the operation.
211      * @param warningBytes the warning defined as the number of bytes, starting from zero and
212      *                     counting from now. A value of {@link #QUOTA_UNLIMITED} indicates
213      *                     there is no warning.
214      * @param limitBytes the limit defined as the number of bytes, starting from zero and counting
215      *                   from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no limit.
216      */
onSetWarningAndLimit(@onNull String iface, long warningBytes, long limitBytes)217     public void onSetWarningAndLimit(@NonNull String iface, long warningBytes, long limitBytes) {
218         // Backward compatibility for those who didn't override this function.
219         onSetLimit(iface, limitBytes);
220     }
221 
222     /**
223      * Called by {@code NetworkStatsService} when setting the alert bytes. Custom implementations
224      * MUST call {@link NetworkStatsProvider#notifyAlertReached()} when {@code quotaBytes} bytes
225      * have been reached. Unlike {@link #onSetLimit(String, long)}, the custom implementation should
226      * not block all egress packets.
227      *
228      * @param quotaBytes the quota defined as the number of bytes, starting from zero and counting
229      *                   from now. A value of {@link #QUOTA_UNLIMITED} indicates there is no alert.
230      */
onSetAlert(long quotaBytes)231     public abstract void onSetAlert(long quotaBytes);
232 }
233