framework層和native層實現聯網控制(iptable方式)

最近工做中,須要開發一個功能----聯網控制,這個功能其實用過root的安卓機應該都知道,禁止某個應用鏈接移動網絡或者wifi。java

root後,經過su去執行iptable的命令就能夠根據uid去控制應用聯網權限網絡

可是因爲公司是作手機系統開發,手機生產出來不容許帶有root權限,因此咱們完成這個功能也是不可使用root權限去實現的。app

因爲第一次作這種功能,剛開始我竟然天真的覺得系統中帶有這種控制權限的接口,而後只有個Internet權限,沒法區分數據流量和wifi。ide

嗯,直接上最終實現的方式。ui

當時發現手機上有個功能是限制應用後臺數據流量,該功能如其所述就是限制應用在後臺狀態下沒法使用流量。經過代碼追溯,找到其調用到的是一個 NetworkManagementService.java 這個Service,方法就是下面這個,裏面的mConnector就是用來封裝發送命令的類。有興趣的能夠本身去看一下 ---> NativeDaemonConnector.javaspa

 

複製代碼

    @Override    public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);        // silently discard when control disabled        // TODO: eventually migrate to be always enabled
        if (!mBandwidthControlEnabled) return;        synchronized (mQuotaLock) {            final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);            if (oldRejectOnQuota == rejectOnQuotaInterfaces) {                // TODO: eventually consider throwing
                return;
            }            try {
                mConnector.execute("bandwidth",
                        rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid);                if (rejectOnQuotaInterfaces) {
                    mUidRejectOnQuota.put(uid, true);
                } else {
                    mUidRejectOnQuota.delete(uid);
                }
            } catch (NativeDaemonConnectorException e) {                throw e.rethrowAsParcelableException();
            }
        }
    }

複製代碼

 

經過搜索addnaughtyapps這個關鍵字,在 CommandListener.cpp 這個類中找到了解析這個命令的地方,code

複製代碼

   if (!strcmp(argv[1], "addnaughtyapps") || !strcmp(argv[1], "ana")) {        if (argc < 3) {
            sendGenericSyntaxError(cli, "addnaughtyapps <appUid> ...");            return 0;
        }        int rc = sBandwidthCtrl->addNaughtyApps(argc - 2, argv + 2);
        sendGenericOkFail(cli, rc);        return 0;
    }

複製代碼

最終在BandwidthController.cpp這個類中執行操做iptable的命令,orm

Ok,既然這個Service擁有直接執行iptable的權限,那麼咱們就直接在裏面添加咱們須要的方法不就OK了嗎。blog

 

所以,接口

1. 在CommandListener.cpp 中加入過濾關鍵字的判斷,

2. 在NetworkManagementService.java中加入接口去發送命令,

3. 最終實如今BandwidthController.cpp 中進行。

第三步主要就是iptable的操做了,如何使用網上不少,不過當時我還真是看了很久才弄懂iptable的操做......用到的主要就是 -I 和 -D 命令。

其實比起這些,我更好奇netd 進程是如何擁有執行root命令的權限的。等有空了必定要研究下。

目前只知道在init.rc中能夠配置以root權限去啓動service。

相關文章
相關標籤/搜索