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