Android Wi-Fi StatusBar(状态栏)流量上下行图标显示流程

 

android 8.0

android/base/packages/SystemUI/src/com/android/systemui/

statusbar/SignalClusterView.java

 

android 9.0

statusbar/StatusBarWifiView.java


与手机信号栏的控制一致, 由 

NetworkControllerImpl  和 WifiSignalControll


NetworkControllerImpl.java{
public void onReceive(Context context, Intent intent) {
if (CHATTY) {
        Log.d(TAG, "onReceive: intent=" + intent);
}
final String action = intent.getAction();
    if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
            action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
           updateConnectivity();

      .........

      } else {
          // No sub id, must be for the wifi.
          mWifiSignalController.handleBroadcast(intent);
    }
}

/**
 * Update the Inet conditions and what network we are connected to.
 */
//更新 inet
private void updateConnectivity() {
mConnectedTransports.clear();
mValidatedTransports.clear();

    //获取当前网络功能接口, 得到当前连接的网络类型以及是否有效  ------查看具体api
    for (NetworkCapabilities nc :mConnectivityManager.getDefaultNetworkCapabilitiesForUser(mCurrentUserId)) {
    for (int transportType : nc.getTransportTypes()) {
                 //验证传输是否连接
                 mConnectedTransports.set(transportType);
            if (nc.hasCapability(NET_CAPABILITY_VALIDATED)) {
                    // 验证传输是否有效
                    mValidatedTransports.set(transportType);
            }
        }
    }

if (CHATTY) {
        Log.d(TAG, "updateConnectivity: mConnectedTransports=" + mConnectedTransports);
Log.d(TAG, "updateConnectivity: mValidatedTransports=" + mValidatedTransports);
}
mInetCondition = !mValidatedTransports.isEmpty();
pushConnectivityToSignals();
}


/**
 * Pushes the current connectivity state to all SignalControllers.
 */
private void pushConnectivityToSignals() {
// We want to update all the icons, all at once, for any condition change
    for (int i = 0; i < mMobileSignalControllers.size(); i++) {
         MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
         mobileSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
     }
    mWifiSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
    mEthernetSignalController.updateConnectivity(mConnectedTransports, mValidatedTransports);
   }
}

 

        /frameworks/base/services/core/java/com/android/server/ConnectivityService.java

/**
 * Update the NetworkCapabilities for {@code networkAgent} to {@code networkCapabilities}
 * augmented with any stateful capabilities implied from {@code networkAgent}
 * (e.g., validated status and captive portal status).
 *
 * @param oldScore score of the network before any of the changes that prompted us
 *                 to call this function.
 * @param nai the network having its capabilities updated.
 * @param networkCapabilities the new network capabilities.
 */
private void updateCapabilities(
int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) {
// Once a NetworkAgent is connected, complain if some immutable capabilities are removed.
if (nai.everConnected && !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities(
            networkCapabilities)) {
// TODO: consider not complaining when a network agent degrade its capabilities if this
// does not cause any request (that is not a listen) currently matching that agent to
        // stop being matched by the updated agent.
String diff = nai.networkCapabilities.describeImmutableDifferences(networkCapabilities);
        if (!TextUtils.isEmpty(diff)) {
            Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
}
    }

// Don't modify caller's NetworkCapabilities.
networkCapabilities = new NetworkCapabilities(networkCapabilities);
    if (nai.lastValidated) {
        networkCapabilities.addCapability(NET_CAPABILITY_VALIDATED);
} else {
        networkCapabilities.removeCapability(NET_CAPABILITY_VALIDATED);
}
if (nai.lastCaptivePortalDetected) {
        networkCapabilities.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
} else {
        networkCapabilities.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
}
if (nai.isBackgroundNetwork()) {
        networkCapabilities.removeCapability(NET_CAPABILITY_FOREGROUND);
} else {
        networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
}

if (Objects.equals(nai.networkCapabilities, networkCapabilities)) return;

    final String oldPermission = getNetworkPermission(nai.networkCapabilities);
    final String newPermission = getNetworkPermission(networkCapabilities);
    if (!Objects.equals(oldPermission, newPermission) && nai.created && !nai.isVPN()) {
try {
mNetd.setNetworkPermission(nai.network.netId, newPermission);
} catch (RemoteException e) {
loge("Exception in setNetworkPermission: " + e);
}
    }

final NetworkCapabilities prevNc = nai.networkCapabilities;
    synchronized (nai) {
        nai.networkCapabilities = networkCapabilities;
}
if (nai.getCurrentScore() == oldScore &&
            networkCapabilities.equalRequestableCapabilities(prevNc)) {
// If the requestable capabilities haven't changed, and the score hasn't changed, then
        // the change we're processing can't affect any requests, it can only affect the listens
        // on this network. We might have been called by rematchNetworkAndRequests when a
        // network changed foreground state.
processListenRequests(nai, true);
} else {
// If the requestable capabilities have changed or the score changed, we can't have been
        // called by rematchNetworkAndRequests, so it's safe to start a rematch.
rematchAllNetworksAndRequests(nai, oldScore);
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
}


private void maybeHandleNetworkAgentMessage(Message msg) {
    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
    if (nai == null) {
if (VDBG) {
log(String.format("%s from unknown NetworkAgent", eventName(msg.what)));
}
return;
}

switch (msg.what) {
case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
            if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
                    networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) ||
                    networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
                Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
}
            //调用他的地方
            updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
            break;
}
    .....
    ......
}


private boolean maybeHandleNetworkMonitorMessage(Message msg) {
switch (msg.what) {
default:
return false;
        case NetworkMonitor.EVENT_NETWORK_TESTED: {
final NetworkAgentInfo nai;
            synchronized (mNetworkForNetId) {
                nai = mNetworkForNetId.get(msg.arg2);
}
if (nai != null) {
                //是否 valid 的值是通过参数  NetworkMonitor.NETWORK_TEST_RESULT_VALID     判断的          
               final boolean valid =
                        (msg.arg1 == NetworkMonitor.NETWORK_TEST_RESULT_VALID);
                final boolean wasValidated = nai.lastValidated;
                if (DBG) log(nai.name() + " validation " + (valid ? "passed" : "failed") +
                        (msg.obj == null ? "" : " with redirect to " + (String)msg.obj));
                if (valid != nai.lastValidated) {
final int oldScore = nai.getCurrentScore();
                    //设置  valid
                    nai.lastValidated = valid;
nai.everValidated |= valid;
                    //设置进值
updateCapabilities(oldScore, nai, nai.networkCapabilities);
// If score has changed, rebroadcast to NetworkFactories. b/17726566
if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
}
         ..........
        ...........
}

 

        进入 /frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java

         //这个类也是很重要的, 网络监控类

// Being in the ValidatedState State indicates a Network is:
// - Successfully validated, or
// - Wanted "as is" by the user, or
// - Does not satisfy the default NetworkRequest and so validation has been skipped.
private class ValidatedState extends State {
@Override
public void enter() {
        maybeLogEvaluationResult(
                networkEventType(validationStage(), EvaluationResult.VALIDATED));
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_VALID, mNetId, null));
mValidations++;
}

@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_NETWORK_CONNECTED:
                transitionTo(mValidatedState);
                return HANDLED;
            default:
return NOT_HANDLED;
}
    }
}


通过网络连接,验证网络
// Being in the EvaluatingState State indicates the Network is being evaluated for internet
// connectivity, or that the user has indicated that this network is unwanted.
private class EvaluatingState extends State {
private int mReevaluateDelayMs;
    private int mAttempts;

@Override
public void enter() {
// If we have already started to track time spent in EvaluatingState
        // don't reset the timer due simply to, say, commands or events that
        // cause us to exit and re-enter EvaluatingState.
if (!mEvaluationTimer.isStarted()) {
mEvaluationTimer.start();
}
        sendMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
        if (mUidResponsibleForReeval != INVALID_UID) {
            TrafficStats.setThreadStatsUid(mUidResponsibleForReeval);
mUidResponsibleForReeval = INVALID_UID;
}
mReevaluateDelayMs = INITIAL_REEVALUATE_DELAY_MS;
mAttempts = 0;
}

@Override
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_REEVALUATE:
if (message.arg1 != mReevaluateToken || mUserDoesNotWant)
return HANDLED;
// Don't bother validating networks that don't satisify the default request.
                // This includes:
                //  - VPNs which can be considered explicitly desired by the user and the
                //    user's desire trumps whether the network validates.
                //  - Networks that don't provide internet access.  It's unclear how to
                //    validate such networks.
                //  - Untrusted networks.  It's unsafe to prompt the user to sign-in to
                //    such networks and the user didn't express interest in connecting to
                //    such networks (an app did) so the user may be unhappily surprised when
                //    asked to sign-in to a network they didn't want to connect to in the
                //    first place.  Validation could be done to adjust the network scores
                //    however these networks are app-requested and may not be intended for
                //    general usage, in which case general validation may not be an accurate
                //    measure of the network's quality.  Only the app knows how to evaluate
                //    the network so don't bother validating here.  Furthermore sending HTTP
                //    packets over the network may be undesirable, for example an extremely
                //    expensive metered network, or unwanted leaking of the User Agent string.
if (!mDefaultRequest.networkCapabilities.satisfiedByNetworkCapabilities(
mNetworkAgentInfo.networkCapabilities)) {
                    validationLog("Network would not satisfy default request, not validating");
transitionTo(mValidatedState);
                    return HANDLED;
}
mAttempts++;
// Note: This call to isCaptivePortal() could take up to a minute. Resolving the
                // server's IP addresses could hit the DNS timeout, and attempting connections
                // to each of the server's several IP addresses (currently one IPv4 and one
                // IPv6) could each take SOCKET_TIMEOUT_MS.  During this time this StateMachine
                // will be unresponsive. isCaptivePortal() could be executed on another Thread
                // if this is found to cause problems.

                //从此处判断网络是否是可用的
CaptivePortalProbeResult probeResult = isCaptivePortal();
                if (probeResult.isSuccessful()) {
                    transitionTo(mValidatedState);
} else if (probeResult.isPortal()) {

        @VisibleForTesting
       protected CaptivePortalProbeResult isCaptivePortal() {
          .............
           ........



       }


         

public abstract class SignalController<T extends SignalController.State,
I extends SignalController.IconGroup> {

     public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
mCurrentState.inetCondition = validatedTransports.get(mTransportType) ? 1 : 0;
notifyListenersIfNecessary();
     }
   
    public void notifyListenersIfNecessary() {
if (isDirty()) {
            saveLastState();
            notifyListeners();
}
  }

}

 

、WifiSignalController.java

public class WifiSignalController extends
SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
private final WifiManager mWifiManager;
    private final AsyncChannel mWifiChannel;
    private final boolean mHasMobileData;
    private final WifiStatusTracker mWifiTracker;

    public WifiSignalController(Context context, boolean hasMobileData,
CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
callbackHandler, networkController);
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mWifiTracker = new WifiStatusTracker(mWifiManager);
mHasMobileData = hasMobileData;
Handler handler = new WifiHandler(Looper.getMainLooper());
mWifiChannel = new AsyncChannel();
Messenger wifiMessenger = mWifiManager.getWifiServiceMessenger();
        if (wifiMessenger != null) {
mWifiChannel.connect(context, handler, wifiMessenger);
}
// WiFi only has one state.
mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
"Wi-Fi Icons",
WifiIcons.WIFI_SIGNAL_STRENGTH,
WifiIcons.QS_WIFI_SIGNAL_STRENGTH,
AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH,
WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
WifiIcons.WIFI_NO_NETWORK,
WifiIcons.QS_WIFI_NO_NETWORK,
AccessibilityContentDescriptions.WIFI_NO_CONNECTION
);

}/**

 

 * Handler to receive the data activity on wifi.
 */
private class WifiHandler extends Handler {
WifiHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
mWifiChannel.sendMessage(Message.obtain(this,
AsyncChannel.CMD_CHANNEL_FULL_CONNECTION));
} else {
                    Log.e(mTag, "Failed to connect to wifi");
}
break;
            case WifiManager.DATA_ACTIVITY_NOTIFICATION:
                //得到framework 层发来的消息
                setActivity(msg.arg1);
                break;
            default:
// Ignore
break;
}
    }
}

 

@VisibleForTesting
void setActivity(int wifiActivity) {
mCurrentState.activityIn = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
|| wifiActivity == WifiManager.DATA_ACTIVITY_IN;
mCurrentState.activityOut = wifiActivity == WifiManager.DATA_ACTIVITY_INOUT
|| wifiActivity == WifiManager.DATA_ACTIVITY_OUT;
notifyListenersIfNecessary();
}

}
 

public class AsyncChannel {
 .....

// 看注释便能理解,链接  
srcHandlerdstMessenger
public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connect srcHandler to the dstMessenger  E");

// We are connected
connected(srcContext, srcHandler, dstMessenger);

// Tell source we are half connected
replyHalfConnected(STATUS_SUCCESSFUL);

    if (DBG) log("connect srcHandler to the dstMessenger X");
}



public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
if (DBG) log("connected srcHandler to the dstMessenger  E");
// Initialize source fields
mSrcContext = srcContext;
mSrcHandler = srcHandler;
    //利用 messenegr 进行跨进成通信
mSrcMessenger = new Messenger(mSrcHandler);
// Initialize destination fields
mDstMessenger = dstMessenger;

    //从log 可以看出来是 目的messenger 与  srcHandler 进行数据交互
    if (DBG) log("connected srcHandler to the dstMessenger X");
}


/**
 * Send a message to the destination handler.
 * @param msg
*/
public void sendMessage(Message msg) {
    msg.replyTo = mSrcMessenger;
    try {
mDstMessenger.send(msg);
} catch (RemoteException e) {
        replyDisconnected(STATUS_SEND_UNSUCCESSFUL);
}
}


/**
 * Reply to the src handler that we're half connected.
 * see: CMD_CHANNEL_HALF_CONNECTED for message contents
 *
 * @param status to be stored in msg.arg1
 */
private void replyHalfConnected(int status) {
    Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
msg.arg1 = status;
msg.obj = this;
msg.replyTo = mDstMessenger;
    if (!linkToDeathMonitor()) {
// Override status to indicate failure
msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
}
mSrcHandler.sendMessage(msg);
}
}

 



public class WifiServiceImpl extends IWifiManager.Stub {

/**
 * Handles client connections
 */
private class ClientHandler extends WifiHandler {

ClientHandler(String tag, Looper looper) {
super(tag, looper);
}

@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
        switch (msg.what) {

             //这个msg 是    AsyncChannel 里的 发过来的
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
// We track the clients by the Messenger
                    // since it is expected to be always available

                    //在这里add client
mTrafficPoller.addClient(msg.replyTo);
} else {
                    Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
}
             ......
             .......
             ......
       }

/**
 * Get a reference to handler. This is used by a client to establish
 * an AsyncChannel communication with WifiService
 */
// 上面得到 messenger的对象
@Override
public Messenger getWifiServiceMessenger() {
       enforceAccessPermission();
enforceChangePermission();
       if (mVerboseLoggingEnabled) {
mLog.info("getWifiServiceMessenger uid=%").c(Binder.getCallingUid()).flush();
}
return new Messenger(mClientHandler);
}


}



 

handleMessage中接收的消息又是哪里发出的呢

/frameworks/base/services/java/com/android/server/wifi/WifiTrafficPoller.java

 



public class WifiTrafficPoller {


WifiTrafficPoller(Context context, Looper looper, String iface) {
mInterface = iface;
mTrafficHandler = new TrafficHandler(looper);

IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);

context.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent == null) {
return;
}
if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(
                            intent.getAction())) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
                                WifiManager.EXTRA_NETWORK_INFO);
} else if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
mScreenOn.set(false);
} else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
mScreenOn.set(true);
}
                    //如果监听到广播,则
                    evaluateTrafficStatsPolling();
}
            }, filter);
}


private void evaluateTrafficStatsPolling() {
    Message msg;
    if (mNetworkInfo == null) return;
    if (mNetworkInfo.getDetailedState() == CONNECTED && mScreenOn.get()) {
        msg = Message.obtain(mTrafficHandler,
ENABLE_TRAFFIC_STATS_POLL, 1, 0);
} else {
        msg = Message.obtain(mTrafficHandler,
ENABLE_TRAFFIC_STATS_POLL, 0, 0);
}
   //发送handler消息,最终再调用 notifyOnDataActivity
 msg.sendToTarget();
}



//根据流量的上行还是下行选择出图片并将消息发送出去
private void notifyOnDataActivity() {
long sent, received;

//保存当前的上下行数据包的数量
 long preTxPkts = mTxPkts, preRxPkts = mRxPkts;
    int dataActivity = WifiManager.DATA_ACTIVITY_NONE;


       //通过如下的方法获取当前的上下行的数据包的数量
   mTxPkts = TrafficStats.getTxPackets(mInterface);
mRxPkts = TrafficStats.getRxPackets(mInterface);

    if (DBG) {
        Log.d(TAG, " packet count Tx="
+ Long.toString(mTxPkts)
                + " Rx="
+ Long.toString(mRxPkts));
}

if (preTxPkts > 0 || preRxPkts > 0) {
        sent = mTxPkts - preTxPkts;
received = mRxPkts - preRxPkts;

 //如果是发送数据
 if (sent > 0) {
            dataActivity |= WifiManager.DATA_ACTIVITY_OUT;
}

          //接受数据
if (received > 0) {
            dataActivity |= WifiManager.DATA_ACTIVITY_IN;
}

if (dataActivity != mDataActivity && mScreenOn.get()) {
mDataActivity = dataActivity;
            if (mVerboseLoggingEnabled) {
                Log.e(TAG, "notifying of data activity "
+ Integer.toString(mDataActivity));
}
for (Messenger client : mClients) {
                Message msg = Message.obtain();
msg.what = WifiManager.DATA_ACTIVITY_NOTIFICATION;
msg.arg1 = mDataActivity;
                try {
                    client.send(msg);
} catch (RemoteException e) {
// Failed to reach, skip
                    // Client removal is handled in WifiService
}
            }
        }
    }
}



 

 

/home/lilei/work/WingRom2/android/frameworks/base/core/java/android/net/TrafficStats.java

public class TrafficStats {
/**
     * The return value to indicate that the device does not support the statistic.
     */
public final static int UNSUPPORTED = -1;

/** @hide */
public static final long KB_IN_BYTES = 1024;
/** @hide */
public static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
/** @hide */
public static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
/** @hide */
public static final long TB_IN_BYTES = GB_IN_BYTES * 1024;
/** @hide */
public static final long PB_IN_BYTES = TB_IN_BYTES * 1024;


    //调用 native方法得到数据 
   /** {@hide} */
    public static long getTxPackets(String iface) {
return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);
   }
}

 

LINUX/android/frameworks/base/core/jni/android_net_TrafficStats.cpp文件中

 

其中mInterface是在LINUX/android/frameworks/base//services/java/com

 

/android/server/wifi/WifiService.java中如下的代码实现了接口获取:

mInterfaceName =  SystemProperties.get("wifi.interface","wlan0");

 

mTrafficPoller = newWifiTrafficPoller(mContext, mInterfaceName);

 

那么TrafficStats.getTxPackets具体是怎么获取流量包数据的呢?解释:(4);

 

 

 

4、LINUX/android/frameworks/base/core/java/android/net/TrafficStats.java文件中

 

   //getTxPackets的具体实现是通过nativeGetIfaceStat实现

   public static long getTxPackets(String iface) {

       return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);

    }

//通过全局搜索   nativeGetIfaceStat 

关键字, 找到

LINUX/android/frameworks/base/core/jni/android_net_TrafficStats.cpp文件中

 

// nativeGetIfaceStat是通过 getIfaceStat实现

static JNINativeMethod gMethods[] = {

    {"nativeGetIfaceStat", "(Ljava/lang/String;I)J",(void*) getIfaceStat}

}

 

static jlong getIfaceStat(JNIEnv* env,jclass clazz, jstring iface, jint type) {

   ScopedUtfChars iface8(env, iface);

   if (parseIfaceStats(iface8.c_str(), &stats) == 0)

}

 

LINUX/android/libnativehelper/include/nativehelper/ScopedUtfChars.h中

 const char* c_str() const {

     //utf_chars_的值为wlan0

     return utf_chars_;

  }

 

LINUX/android/frameworks/base/core/jni/android_net_TrafficStats.cpp文件中

 

QTAGUID_IFACE_STATS ="/proc/net/xt_qtaguid/iface_stat_fmt";

 

static int parseIfaceStats(const char* iface, struct Stats* stats) {
    FILE *fp = fopen(QTAGUID_IFACE_STATS, "r");
if (fp == NULL) {
return -1;
}

char buffer[384];
char cur_iface[32];
bool foundTcp = false;
uint64_t rxBytes, rxPackets, txBytes, txPackets, tcpRxPackets, tcpTxPackets;

while (fgets(buffer, sizeof(buffer), fp) != NULL) {
int matched = sscanf(buffer, "%31s %" SCNu64 " %" SCNu64 " %" SCNu64
" %" SCNu64 " " "%*u %" SCNu64 " %*u %*u %*u %*u "
                "%*u %" SCNu64 " %*u %*u %*u %*u", cur_iface, &rxBytes,
&rxPackets, &txBytes, &txPackets, &tcpRxPackets, &tcpTxPackets);
if (matched >= 5) {
if (matched == 7) {
                foundTcp = true;
}
if (!iface || !strcmp(iface, cur_iface)) {
                stats->rxBytes += rxBytes;
stats->rxPackets += rxPackets;
stats->txBytes += txBytes;
stats->txPackets += txPackets;
if (matched == 7) {
                    stats->tcpRxPackets += tcpRxPackets;
stats->tcpTxPackets += tcpTxPackets;
}
            }
        }
    }

if (!foundTcp) {
        stats->tcpRxPackets = UNKNOWN;
stats->tcpTxPackets = UNKNOWN;
}

if (fclose(fp) != 0) {
return -1;
}
return 0;
}

 

 那么iface_stat_fmt又是如何创建的呢?解释:5

 

5、LINUX/android/kernel/net/netfilter/xt_qtaguid.c中

通过如下的方法创建 iface_stat_fmt

static const char*iface_stat_fmt_procfilename = "iface_stat_fmt";

iface_stat_fmt_procfile = proc_create_data(iface_stat_fmt_procfilename,
proc_iface_perms,
parent_procdir,
&proc_iface_stat_fmt_fops,
(void *)2 /* fmt2 */);
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空白的泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值