Loading core/api/module-lib-current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -61,12 +61,17 @@ package android.app.usage { method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException; method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long); method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException; method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setStatsProviderWarningAndLimitAsync(@NonNull String, long, long); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setUidForeground(int, boolean); } public abstract static class NetworkStatsManager.UsageCallback { method public void onThresholdReached(@NonNull android.net.NetworkTemplate); } } package android.bluetooth { Loading packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java +92 −53 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; Loading @@ -39,14 +40,11 @@ import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.text.TextUtils; Loading @@ -57,6 +55,7 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; /** * Provides access to network usage history and statistics. Usage data is collected in Loading Loading @@ -723,26 +722,35 @@ public class NetworkStatsManager { } } /** @hide */ public void registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { /** * Registers to receive notifications about data usage on specified networks. * * <p>The callbacks will continue to be called as long as the process is alive or * {@link #unregisterUsageCallback} is called. * * @param template Template used to match networks. See {@link NetworkTemplate}. * @param thresholdBytes Threshold in bytes to be notified on. * @param executor The executor on which callback will be invoked. The provided {@link Executor} * must run callback sequentially, otherwise the order of callbacks cannot be * guaranteed. * @param callback The {@link UsageCallback} that the system will call when data usage * has exceeded the specified threshold. * @hide */ @SystemApi(client = MODULE_LIBRARIES) public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes, @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) { Objects.requireNonNull(template, "NetworkTemplate cannot be null"); Objects.requireNonNull(callback, "UsageCallback cannot be null"); Objects.requireNonNull(executor, "Executor cannot be null"); final Looper looper; if (handler == null) { looper = Looper.myLooper(); } else { looper = handler.getLooper(); } DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, template, thresholdBytes); try { CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, template.getSubscriberId(), callback); final UsageCallbackWrapper callbackWrapper = new UsageCallbackWrapper(executor, callback); callback.request = mService.registerUsageCallback( mContext.getOpPackageName(), request, new Messenger(callbackHandler), new Binder()); mContext.getOpPackageName(), request, callbackWrapper); if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); if (callback.request == null) { Loading Loading @@ -800,7 +808,10 @@ public class NetworkStatsManager { + " thresholdBytes=" + thresholdBytes + " }"); } registerUsageCallback(template, networkType, thresholdBytes, callback, handler); final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r); registerUsageCallback(template, thresholdBytes, executor, callback); } /** Loading @@ -825,6 +836,26 @@ public class NetworkStatsManager { * Base class for usage callbacks. Should be extended by applications wanting notifications. */ public static abstract class UsageCallback { /** * Called when data usage has reached the given threshold. * * Called by {@code NetworkStatsService} when the registered threshold is reached. * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system * will not call {@link #onThresholdReached(int, String)}. * * @param template The {@link NetworkTemplate} that associated with this callback. * @hide */ @SystemApi(client = MODULE_LIBRARIES) public void onThresholdReached(@NonNull NetworkTemplate template) { // Backward compatibility for those who didn't override this function. final int networkType = networkTypeForTemplate(template); if (networkType != ConnectivityManager.TYPE_NONE) { final String subscriberId = template.getSubscriberIds().isEmpty() ? null : template.getSubscriberIds().iterator().next(); onThresholdReached(networkType, subscriberId); } } /** * Called when data usage has reached the given threshold. Loading @@ -835,6 +866,25 @@ public class NetworkStatsManager { * @hide used for internal bookkeeping */ private DataUsageRequest request; /** * Get network type from a template if feasible. * * @param template the target {@link NetworkTemplate}. * @return legacy network type, only supports for the types which is already supported in * {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}. * {@link ConnectivityManager#TYPE_NONE} for other types. */ private static int networkTypeForTemplate(@NonNull NetworkTemplate template) { switch (template.getMatchRule()) { case NetworkTemplate.MATCH_MOBILE: return ConnectivityManager.TYPE_MOBILE; case NetworkTemplate.MATCH_WIFI: return ConnectivityManager.TYPE_WIFI; default: return ConnectivityManager.TYPE_NONE; } } } /** Loading Loading @@ -953,43 +1003,32 @@ public class NetworkStatsManager { } } private static class CallbackHandler extends Handler { private final int mNetworkType; private final String mSubscriberId; private UsageCallback mCallback; private static class UsageCallbackWrapper extends IUsageCallback.Stub { // Null if unregistered. private volatile UsageCallback mCallback; CallbackHandler(Looper looper, int networkType, String subscriberId, UsageCallback callback) { super(looper); mNetworkType = networkType; mSubscriberId = subscriberId; private final Executor mExecutor; UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) { mCallback = callback; mExecutor = executor; } @Override public void handleMessage(Message message) { DataUsageRequest request = (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY); switch (message.what) { case CALLBACK_LIMIT_REACHED: { if (mCallback != null) { mCallback.onThresholdReached(mNetworkType, mSubscriberId); public void onThresholdReached(DataUsageRequest request) { // Copy it to a local variable in case mCallback changed inside the if condition. final UsageCallback callback = mCallback; if (callback != null) { mExecutor.execute(() -> callback.onThresholdReached(request.template)); } else { Log.e(TAG, "limit reached with released callback for " + request); Log.e(TAG, "onThresholdReached with released callback for " + request); } break; } case CALLBACK_RELEASED: { @Override public void onCallbackReleased(DataUsageRequest request) { if (DBG) Log.d(TAG, "callback released for " + request); mCallback = null; break; } } } private static Object getObject(Message msg, String key) { return msg.getData().getParcelable(key); } } Loading packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.os.IBinder; Loading Loading @@ -71,7 +72,7 @@ interface INetworkStatsService { /** Registers a callback on data usage. */ DataUsageRequest registerUsageCallback(String callingPackage, in DataUsageRequest request, in Messenger messenger, in IBinder binder); in DataUsageRequest request, in IUsageCallback callback); /** Unregisters a callback on data usage. */ void unregisterUsageRequest(in DataUsageRequest request); Loading packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl 0 → 100644 +29 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netstats; import android.net.DataUsageRequest; /** * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback. * * @hide */ oneway interface IUsageCallback { void onThresholdReached(in DataUsageRequest request); void onCallbackReleased(in DataUsageRequest request); } packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java +26 −30 Original line number Diff line number Diff line Loading @@ -26,13 +26,12 @@ import android.net.NetworkStatsAccess; import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Bundle; import android.net.netstats.IUsageCallback; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; Loading Loading @@ -75,10 +74,10 @@ class NetworkStatsObservers { * * @return the normalized request wrapped within {@link RequestInfo}. */ public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger, IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) { public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { DataUsageRequest request = buildRequest(inputRequest); RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid, RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid, accessLevel); if (LOGV) Log.v(TAG, "Registering observer for " + request); Loading Loading @@ -206,11 +205,10 @@ class NetworkStatsObservers { request.template, thresholdInBytes); } private RequestInfo buildRequestInfo(DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) { private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { if (accessLevel <= NetworkStatsAccess.Level.USER) { return new UserUsageRequestInfo(this, request, messenger, binder, callingUid, return new UserUsageRequestInfo(this, request, callback, callingUid, accessLevel); } else { // Safety check in case a new access level is added and we forgot to update this Loading @@ -218,7 +216,7 @@ class NetworkStatsObservers { throw new IllegalArgumentException( "accessLevel " + accessLevel + " is less than DEVICESUMMARY."); } return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid, return new NetworkUsageRequestInfo(this, request, callback, callingUid, accessLevel); } } Loading @@ -230,25 +228,23 @@ class NetworkStatsObservers { private abstract static class RequestInfo implements IBinder.DeathRecipient { private final NetworkStatsObservers mStatsObserver; protected final DataUsageRequest mRequest; private final Messenger mMessenger; private final IBinder mBinder; private final IUsageCallback mCallback; protected final int mCallingUid; protected final @NetworkStatsAccess.Level int mAccessLevel; protected NetworkStatsRecorder mRecorder; protected NetworkStatsCollection mCollection; RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { mStatsObserver = statsObserver; mRequest = request; mMessenger = messenger; mBinder = binder; mCallback = callback; mCallingUid = callingUid; mAccessLevel = accessLevel; try { mBinder.linkToDeath(this, 0); mCallback.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } Loading @@ -257,7 +253,7 @@ class NetworkStatsObservers { @Override public void binderDied() { if (LOGV) { Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")"); Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")"); } mStatsObserver.unregister(mRequest, Process.SYSTEM_UID); callCallback(NetworkStatsManager.CALLBACK_RELEASED); Loading @@ -270,9 +266,7 @@ class NetworkStatsObservers { } private void unlinkDeathRecipient() { if (mBinder != null) { mBinder.unlinkToDeath(this, 0); } mCallback.asBinder().unlinkToDeath(this, 0); } /** Loading @@ -294,17 +288,19 @@ class NetworkStatsObservers { } private void callCallback(int callbackType) { Bundle bundle = new Bundle(); bundle.putParcelable(DataUsageRequest.PARCELABLE_KEY, mRequest); Message msg = Message.obtain(); msg.what = callbackType; msg.setData(bundle); try { if (LOGV) { Log.v(TAG, "sending notification " + callbackTypeToName(callbackType) + " for " + mRequest); } mMessenger.send(msg); switch (callbackType) { case NetworkStatsManager.CALLBACK_LIMIT_REACHED: mCallback.onThresholdReached(mRequest); break; case NetworkStatsManager.CALLBACK_RELEASED: mCallback.onCallbackReleased(mRequest); break; } } catch (RemoteException e) { // May occur naturally in the race of binder death. Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest); Loading Loading @@ -334,9 +330,9 @@ class NetworkStatsObservers { private static class NetworkUsageRequestInfo extends RequestInfo { NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { super(statsObserver, request, messenger, binder, callingUid, accessLevel); super(statsObserver, request, callback, callingUid, accessLevel); } @Override Loading Loading @@ -376,9 +372,9 @@ class NetworkStatsObservers { private static class UserUsageRequestInfo extends RequestInfo { UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { super(statsObserver, request, messenger, binder, callingUid, accessLevel); super(statsObserver, request, callback, callingUid, accessLevel); } @Override Loading Loading
core/api/module-lib-current.txt +5 −0 Original line number Diff line number Diff line Loading @@ -61,12 +61,17 @@ package android.app.usage { method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException; method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long); method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException; method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setStatsProviderWarningAndLimitAsync(@NonNull String, long, long); method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setUidForeground(int, boolean); } public abstract static class NetworkStatsManager.UsageCallback { method public void onThresholdReached(@NonNull android.net.NetworkTemplate); } } package android.bluetooth { Loading
packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java +92 −53 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; Loading @@ -39,14 +40,11 @@ import android.net.NetworkStack; import android.net.NetworkStateSnapshot; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.net.netstats.provider.NetworkStatsProvider; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.telephony.TelephonyManager; import android.text.TextUtils; Loading @@ -57,6 +55,7 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; /** * Provides access to network usage history and statistics. Usage data is collected in Loading Loading @@ -723,26 +722,35 @@ public class NetworkStatsManager { } } /** @hide */ public void registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { /** * Registers to receive notifications about data usage on specified networks. * * <p>The callbacks will continue to be called as long as the process is alive or * {@link #unregisterUsageCallback} is called. * * @param template Template used to match networks. See {@link NetworkTemplate}. * @param thresholdBytes Threshold in bytes to be notified on. * @param executor The executor on which callback will be invoked. The provided {@link Executor} * must run callback sequentially, otherwise the order of callbacks cannot be * guaranteed. * @param callback The {@link UsageCallback} that the system will call when data usage * has exceeded the specified threshold. * @hide */ @SystemApi(client = MODULE_LIBRARIES) public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes, @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) { Objects.requireNonNull(template, "NetworkTemplate cannot be null"); Objects.requireNonNull(callback, "UsageCallback cannot be null"); Objects.requireNonNull(executor, "Executor cannot be null"); final Looper looper; if (handler == null) { looper = Looper.myLooper(); } else { looper = handler.getLooper(); } DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET, template, thresholdBytes); try { CallbackHandler callbackHandler = new CallbackHandler(looper, networkType, template.getSubscriberId(), callback); final UsageCallbackWrapper callbackWrapper = new UsageCallbackWrapper(executor, callback); callback.request = mService.registerUsageCallback( mContext.getOpPackageName(), request, new Messenger(callbackHandler), new Binder()); mContext.getOpPackageName(), request, callbackWrapper); if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request); if (callback.request == null) { Loading Loading @@ -800,7 +808,10 @@ public class NetworkStatsManager { + " thresholdBytes=" + thresholdBytes + " }"); } registerUsageCallback(template, networkType, thresholdBytes, callback, handler); final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r); registerUsageCallback(template, thresholdBytes, executor, callback); } /** Loading @@ -825,6 +836,26 @@ public class NetworkStatsManager { * Base class for usage callbacks. Should be extended by applications wanting notifications. */ public static abstract class UsageCallback { /** * Called when data usage has reached the given threshold. * * Called by {@code NetworkStatsService} when the registered threshold is reached. * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system * will not call {@link #onThresholdReached(int, String)}. * * @param template The {@link NetworkTemplate} that associated with this callback. * @hide */ @SystemApi(client = MODULE_LIBRARIES) public void onThresholdReached(@NonNull NetworkTemplate template) { // Backward compatibility for those who didn't override this function. final int networkType = networkTypeForTemplate(template); if (networkType != ConnectivityManager.TYPE_NONE) { final String subscriberId = template.getSubscriberIds().isEmpty() ? null : template.getSubscriberIds().iterator().next(); onThresholdReached(networkType, subscriberId); } } /** * Called when data usage has reached the given threshold. Loading @@ -835,6 +866,25 @@ public class NetworkStatsManager { * @hide used for internal bookkeeping */ private DataUsageRequest request; /** * Get network type from a template if feasible. * * @param template the target {@link NetworkTemplate}. * @return legacy network type, only supports for the types which is already supported in * {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}. * {@link ConnectivityManager#TYPE_NONE} for other types. */ private static int networkTypeForTemplate(@NonNull NetworkTemplate template) { switch (template.getMatchRule()) { case NetworkTemplate.MATCH_MOBILE: return ConnectivityManager.TYPE_MOBILE; case NetworkTemplate.MATCH_WIFI: return ConnectivityManager.TYPE_WIFI; default: return ConnectivityManager.TYPE_NONE; } } } /** Loading Loading @@ -953,43 +1003,32 @@ public class NetworkStatsManager { } } private static class CallbackHandler extends Handler { private final int mNetworkType; private final String mSubscriberId; private UsageCallback mCallback; private static class UsageCallbackWrapper extends IUsageCallback.Stub { // Null if unregistered. private volatile UsageCallback mCallback; CallbackHandler(Looper looper, int networkType, String subscriberId, UsageCallback callback) { super(looper); mNetworkType = networkType; mSubscriberId = subscriberId; private final Executor mExecutor; UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) { mCallback = callback; mExecutor = executor; } @Override public void handleMessage(Message message) { DataUsageRequest request = (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY); switch (message.what) { case CALLBACK_LIMIT_REACHED: { if (mCallback != null) { mCallback.onThresholdReached(mNetworkType, mSubscriberId); public void onThresholdReached(DataUsageRequest request) { // Copy it to a local variable in case mCallback changed inside the if condition. final UsageCallback callback = mCallback; if (callback != null) { mExecutor.execute(() -> callback.onThresholdReached(request.template)); } else { Log.e(TAG, "limit reached with released callback for " + request); Log.e(TAG, "onThresholdReached with released callback for " + request); } break; } case CALLBACK_RELEASED: { @Override public void onCallbackReleased(DataUsageRequest request) { if (DBG) Log.d(TAG, "callback released for " + request); mCallback = null; break; } } } private static Object getObject(Message msg, String key) { return msg.getData().getParcelable(key); } } Loading
packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl +2 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.UnderlyingNetworkInfo; import android.net.netstats.IUsageCallback; import android.net.netstats.provider.INetworkStatsProvider; import android.net.netstats.provider.INetworkStatsProviderCallback; import android.os.IBinder; Loading Loading @@ -71,7 +72,7 @@ interface INetworkStatsService { /** Registers a callback on data usage. */ DataUsageRequest registerUsageCallback(String callingPackage, in DataUsageRequest request, in Messenger messenger, in IBinder binder); in DataUsageRequest request, in IUsageCallback callback); /** Unregisters a callback on data usage. */ void unregisterUsageRequest(in DataUsageRequest request); Loading
packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl 0 → 100644 +29 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.netstats; import android.net.DataUsageRequest; /** * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback. * * @hide */ oneway interface IUsageCallback { void onThresholdReached(in DataUsageRequest request); void onCallbackReleased(in DataUsageRequest request); }
packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java +26 −30 Original line number Diff line number Diff line Loading @@ -26,13 +26,12 @@ import android.net.NetworkStatsAccess; import android.net.NetworkStatsCollection; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Bundle; import android.net.netstats.IUsageCallback; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; Loading Loading @@ -75,10 +74,10 @@ class NetworkStatsObservers { * * @return the normalized request wrapped within {@link RequestInfo}. */ public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger, IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) { public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { DataUsageRequest request = buildRequest(inputRequest); RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid, RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid, accessLevel); if (LOGV) Log.v(TAG, "Registering observer for " + request); Loading Loading @@ -206,11 +205,10 @@ class NetworkStatsObservers { request.template, thresholdInBytes); } private RequestInfo buildRequestInfo(DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) { private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { if (accessLevel <= NetworkStatsAccess.Level.USER) { return new UserUsageRequestInfo(this, request, messenger, binder, callingUid, return new UserUsageRequestInfo(this, request, callback, callingUid, accessLevel); } else { // Safety check in case a new access level is added and we forgot to update this Loading @@ -218,7 +216,7 @@ class NetworkStatsObservers { throw new IllegalArgumentException( "accessLevel " + accessLevel + " is less than DEVICESUMMARY."); } return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid, return new NetworkUsageRequestInfo(this, request, callback, callingUid, accessLevel); } } Loading @@ -230,25 +228,23 @@ class NetworkStatsObservers { private abstract static class RequestInfo implements IBinder.DeathRecipient { private final NetworkStatsObservers mStatsObserver; protected final DataUsageRequest mRequest; private final Messenger mMessenger; private final IBinder mBinder; private final IUsageCallback mCallback; protected final int mCallingUid; protected final @NetworkStatsAccess.Level int mAccessLevel; protected NetworkStatsRecorder mRecorder; protected NetworkStatsCollection mCollection; RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { mStatsObserver = statsObserver; mRequest = request; mMessenger = messenger; mBinder = binder; mCallback = callback; mCallingUid = callingUid; mAccessLevel = accessLevel; try { mBinder.linkToDeath(this, 0); mCallback.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { binderDied(); } Loading @@ -257,7 +253,7 @@ class NetworkStatsObservers { @Override public void binderDied() { if (LOGV) { Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")"); Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")"); } mStatsObserver.unregister(mRequest, Process.SYSTEM_UID); callCallback(NetworkStatsManager.CALLBACK_RELEASED); Loading @@ -270,9 +266,7 @@ class NetworkStatsObservers { } private void unlinkDeathRecipient() { if (mBinder != null) { mBinder.unlinkToDeath(this, 0); } mCallback.asBinder().unlinkToDeath(this, 0); } /** Loading @@ -294,17 +288,19 @@ class NetworkStatsObservers { } private void callCallback(int callbackType) { Bundle bundle = new Bundle(); bundle.putParcelable(DataUsageRequest.PARCELABLE_KEY, mRequest); Message msg = Message.obtain(); msg.what = callbackType; msg.setData(bundle); try { if (LOGV) { Log.v(TAG, "sending notification " + callbackTypeToName(callbackType) + " for " + mRequest); } mMessenger.send(msg); switch (callbackType) { case NetworkStatsManager.CALLBACK_LIMIT_REACHED: mCallback.onThresholdReached(mRequest); break; case NetworkStatsManager.CALLBACK_RELEASED: mCallback.onCallbackReleased(mRequest); break; } } catch (RemoteException e) { // May occur naturally in the race of binder death. Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest); Loading Loading @@ -334,9 +330,9 @@ class NetworkStatsObservers { private static class NetworkUsageRequestInfo extends RequestInfo { NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { super(statsObserver, request, messenger, binder, callingUid, accessLevel); super(statsObserver, request, callback, callingUid, accessLevel); } @Override Loading Loading @@ -376,9 +372,9 @@ class NetworkStatsObservers { private static class UserUsageRequestInfo extends RequestInfo { UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request, Messenger messenger, IBinder binder, int callingUid, IUsageCallback callback, int callingUid, @NetworkStatsAccess.Level int accessLevel) { super(statsObserver, request, messenger, binder, callingUid, accessLevel); super(statsObserver, request, callback, callingUid, accessLevel); } @Override Loading