Android bw_costly_<iface>链

测试时关注到bw_costly_链

因为和iface有关。猜测这个链是动态生成的。

开关数据业务测试,果然关闭数据业务后,bw_OUTPUT中不再会调用bw_costly_rmnet_data3,也没有bw_costly_rmnet_data3这个链了。

再次打开数据业务后出现了bw_costly_rmnet_data2。说明上次上网的rmnet_data3口,这此上网的rmnet_data2。

cpp 复制代码
:/ # iptables -t filter -nvL bw_OUTPUT
Chain bw_OUTPUT (1 references)
 pkts bytes target     prot opt in     out     source               destination
   24  1909 bw_global_alert  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    2   120 bw_costly_rmnet_data3  all  --  *      rmnet_data3  0.0.0.0/0            0.0.0.0/0

是netd模块自己检测上网状态后,自己添加的吗?

查看代码是netd的BandwidthController生成。

cpp 复制代码
int BandwidthController::setInterfaceQuota(const std::string& iface, int64_t maxBytes) {
    const std::string& cost = iface;
....
    /* Insert ingress quota. */
    auto it = mQuotaIfaces.find(iface);

    if (it != mQuotaIfaces.end()) {
        if (int res = updateQuota(cost, maxBytes)) {
            ALOGE("Failed update quota for %s", iface.c_str());
            removeInterfaceQuota(iface);
            return res;
        }
        it->second.quota = maxBytes;
        return 0;
    }

    const std::string chain = "bw_costly_" + iface;
    const int ruleInsertPos = (mGlobalAlertBytes) ? 2 : 1;
    std::vector<std::string> cmds = {
            "*filter",
            StringPrintf(":%s -", chain.c_str()),
            StringPrintf("-A %s -j bw_penalty_box", chain.c_str()),
            StringPrintf("-I bw_INPUT %d -i %s -j %s", ruleInsertPos, iface.c_str(), chain.c_str()),
            StringPrintf("-I bw_OUTPUT %d -o %s -j %s", ruleInsertPos, iface.c_str(),
                         chain.c_str()),
            StringPrintf("-A bw_FORWARD -i %s -j %s", iface.c_str(), chain.c_str()),
            StringPrintf("-A bw_FORWARD -o %s -j %s", iface.c_str(), chain.c_str()),
            StringPrintf("-A %s -m quota2 ! --quota %" PRId64 " --name %s -j REJECT", chain.c_str(),
                         maxBytes, cost.c_str()),
            "COMMIT\n",
    };
    if (iptablesRestoreFunction(V4V6, Join(cmds, "\n"), nullptr) != 0) {
        ALOGE("Failed set quota rule");
        removeInterfaceQuota(iface);
        return -EREMOTEIO;
    }

    mQuotaIfaces[iface] = QuotaInfo{maxBytes, 0};
    return 0;
}

netd 向上提供此接口,内部除了ndc模块通过控制台可以调用,没有自动关注网络状态,调用setInterfaceQuota的地方:

cpp 复制代码
binder::Status NetdNativeService::bandwidthSetInterfaceQuota(const std::string& ifName,
                                                             int64_t bytes) {
    NETD_LOCKING_RPC(gCtls->bandwidthCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
    int res = gCtls->bandwidthCtrl.setInterfaceQuota(ifName, bytes);
    return statusFromErrcode(res);
}

继续在android代码中搜索:

framework的NetworkManagementService.java中调用

mNetdService.bandwidthSetInterfaceQuota

cpp 复制代码
    public void setInterfaceQuota(String iface, long quotaBytes) {
        NetworkStack.checkNetworkStackPermission(mContext);

        synchronized (mQuotaLock) {
            if (mActiveQuotas.containsKey(iface)) {
                throw new IllegalStateException("iface " + iface + " already has quota");
            }

            try {
                // TODO: support quota shared across interfaces
                mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes);

                mActiveQuotas.put(iface, quotaBytes);
            } catch (RemoteException | ServiceSpecificException e) {
                throw new IllegalStateException(e);
            }

            synchronized (mTetheringStatsProviders) {
                for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
                    try {
                        provider.setInterfaceQuota(iface, quotaBytes);
                    } catch (RemoteException e) {
                        Log.e(TAG, "Problem setting tethering data limit on provider " +
                                mTetheringStatsProviders.get(provider) + ": " + e);
                    }
                }
            }
        }
    }

调用序列是:
NatworkManagementService:

NatworkManagementService.systemReady->prepareNativeDaemon()->setInterfaceQuota->mNetdService.bandwidthSetInterfaceQuota

下一步分析数据业务开关后,是什么流程触发NatworkManagementService的setInterfaceQuota和removeInterfaceQuota的调用。

参考链接:

Android系统中iptables的应用(二)BandwidthController https://blog.csdn.net/xiaokeweng/article/details/48810049

相关推荐
Winston Wood2 小时前
Android Parcelable和Serializable的区别与联系
android·序列化
清风徐来辽2 小时前
Android 项目模型配置管理
android
帅得不敢出门2 小时前
Gradle命令编译Android Studio工程项目并签名
android·ide·android studio·gradlew
problc3 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
帅得不敢出门13 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了15 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任17 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山17 小时前
Android“引用们”的底层原理
android·java
迃-幵17 小时前
力扣:225 用队列实现栈
android·javascript·leetcode
大风起兮云飞扬丶17 小时前
Android——从相机/相册获取图片
android