1 /* 2 * Copyright (C) 2013 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 com.android.server.wifi; 18 19 import android.content.Context; 20 import android.net.wifi.ITrafficStateCallback; 21 import android.net.wifi.WifiManager; 22 import android.os.RemoteCallbackList; 23 import android.os.RemoteException; 24 import android.util.Log; 25 import android.util.SparseBooleanArray; 26 27 import com.android.wifi.resources.R; 28 29 import java.io.FileDescriptor; 30 import java.io.PrintWriter; 31 32 /** 33 * Polls for traffic stats and notifies the clients 34 */ 35 public class WifiTrafficPoller { 36 private static final String TAG = "WifiTrafficPoller"; 37 38 private long mTxPkts = 0; 39 private long mRxPkts = 0; 40 41 private int mLastActivity = -1; 42 43 private final SparseBooleanArray mCallbackFirstInvocationTracker = new SparseBooleanArray(); 44 private final RemoteCallbackList<ITrafficStateCallback> mRegisteredCallbacks; 45 private final Context mContext; 46 WifiTrafficPoller(Context context)47 public WifiTrafficPoller(Context context) { 48 mContext = context; 49 mRegisteredCallbacks = new RemoteCallbackList<>(); 50 } 51 52 /** 53 * Add a new callback to the traffic poller. 54 */ addCallback(ITrafficStateCallback callback)55 public void addCallback(ITrafficStateCallback callback) { 56 mCallbackFirstInvocationTracker.put(callback.hashCode(), true); 57 if (!mRegisteredCallbacks.register(callback)) { 58 Log.e(TAG, "Failed to add callback"); 59 } 60 } 61 62 /** 63 * Remove an existing callback from the traffic poller. 64 */ removeCallback(ITrafficStateCallback callback)65 public void removeCallback(ITrafficStateCallback callback) { 66 mRegisteredCallbacks.unregister(callback); 67 mCallbackFirstInvocationTracker.delete(callback.hashCode()); 68 } 69 70 /** 71 * Notifies clients of data activity if the activity changed since the last update. 72 */ notifyOnDataActivity(long newTxPkts, long newRxPkts)73 public void notifyOnDataActivity(long newTxPkts, long newRxPkts) { 74 if (newTxPkts <= 0 && newRxPkts <= 0) { 75 return; 76 } 77 78 long sent = newTxPkts - mTxPkts; 79 long received = newRxPkts - mRxPkts; 80 int dataActivity = WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE; 81 int txPacketThreshold = mContext.getResources().getInteger( 82 R.integer.config_wifiTrafficPollerTxPacketThreshold); 83 int rxPacketThreshold = mContext.getResources().getInteger( 84 R.integer.config_wifiTrafficPollerRxPacketThreshold); 85 86 if (sent > txPacketThreshold) { 87 dataActivity |= WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT; 88 } 89 if (received > rxPacketThreshold) { 90 dataActivity |= WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN; 91 } 92 93 int itemCount = mRegisteredCallbacks.beginBroadcast(); 94 for (int i = 0; i < itemCount; i++) { 95 ITrafficStateCallback callback = mRegisteredCallbacks.getBroadcastItem(i); 96 int callbackIdentifier = callback.hashCode(); 97 if (mCallbackFirstInvocationTracker.get(callbackIdentifier) 98 || dataActivity != mLastActivity) { 99 mCallbackFirstInvocationTracker.put(callbackIdentifier, false); 100 try { 101 callback.onStateChanged(dataActivity); 102 } catch (RemoteException e) { 103 // Failed to reach, skip 104 // Client removal is handled in WifiService 105 } 106 } 107 } 108 mRegisteredCallbacks.finishBroadcast(); 109 110 mTxPkts = newTxPkts; 111 mRxPkts = newRxPkts; 112 mLastActivity = dataActivity; 113 } 114 115 /** 116 * Dump method for traffic poller. 117 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)118 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 119 pw.println("mTxPkts " + mTxPkts); 120 pw.println("mRxPkts " + mRxPkts); 121 pw.println("mLastActivity " + mLastActivity); 122 pw.println("mRegisteredCallbacks " + mRegisteredCallbacks.getRegisteredCallbackCount()); 123 } 124 } 125