需求:可以控制某个应用访问WIFI或移动网络的功能。

Android自带防火墙原理是:一旦开启防火墙,所有的应用都不能访问网络(包括WIFI和移动网络),所以不能满足需求,故需要在原生基础上新增两个方法来实现该功能,方法声明在frameworks/base/core/java/android/os目录下的INetworkManagementService.aidl中:

interface INetworkManagementService{    . . .        void setMobileDataUidRule(int uid, boolean allow); //根据应用的uid设置是否允许它访问移动网络        void setWifiDataUidRule(int uid, boolean allow); //根据应用的uid设置是否允许它访问WIFI网络    . . .}


方法的实现是在frameworks/base/services/core/java/com/android/server目录下的NetworkManagementService.java中:

public class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor {    . . .    @Override    public void setMobileDataUidRule(int uid, boolean allow) {        enforceSystemUid(); // 校验调用者是否是系统uid        try {            mConnector.execute("firewall", "set_mobile_data_uid_rule", uid, rule);        } catch (NativeDaemonConnectorException e) {            throw e.rethrowAsParcelableException();        }    }    @Override    public void setWifiDataUidRule(int uid, boolean allow) {        enforceSystemUid();        try {            mConnector.execute("firewall", "set_wifi_data_uid_rule", uid, rule);        } catch (NativeDaemonConnectorException e) {            throw e.rethrowAsParcelableException();        }    }    . . .}


下面又通过socket通信方式调用到system/netd层的system/netd/server目录下的CommandListener.cpp中:

CommandListener::CommandListener() : FrameworkListener("netd", true) {    . . .    sFirewallCtrl->initIptableFirewall();// 开机初始化    . . .}int CommandListener::FirewallCmd::runCommand(SocketClient *cli, int argc, char **argv) {    . . .    if (!strcmp(argv[1], "set_mobile_data_uid_rule")) {        if (argc != 4) {            cli->sendMsg(ResponseCode::CommandSyntaxError,                    "Usage: firewall set_mobile_data_uid_rule <1000> ",                    false);            return 0;        }        int uid = atoi(argv[2]);        FirewallRule rule = parseRule(argv[3]);        int res = sFirewallCtrl->setMobileDataUidRule(uid, rule);        return sendGenericOkFail(cli, res);    }    if (!strcmp(argv[1], "set_wifi_data_uid_rule")) {        if (argc != 4) {            cli->sendMsg(ResponseCode::CommandSyntaxError,                    "Usage: firewall set_wifi_data_uid_rule <1000> ",                    false);            return 0;        }        int uid = atoi(argv[2]);        FirewallRule rule = parseRule(argv[3]);        int res = sFirewallCtrl->setWifiDataUidRule(uid, rule);        return sendGenericOkFail(cli, res);    }    . . .}


上面代码又调用到system/netd/server目录下的FirewallController.cpp中:

. . .#include const char* op_3g;const char* op_wifi;. . .int FirewallController::initIptableFirewall(void) {    int res = 0;    char property[PROPERTY_VALUE_MAX];    property_get("ro.hardware", property, "qcom");    if (strncmp("qcom", property, 4) == 0) { // 高通平台        op_3g = "rmnet+";        op_wifi = "wlan0";    } else if (strncmp("mt", property, 2) == 0 || strncmp("MT", property, 2) == 0) {        op_3g = "ccmni+"; // MTK平台        op_wifi = "wlan0";    } else {        op_3g = "rmnet+";        op_wifi = "wlan0";    }    // 新建一个drop_wall链表    res |= execIptables(V4V6, "-w", "-N", "drop_wall", NULL);    // 把新建的drop_wall链表添加到OUTPUT链表目录下    res |= execIptables(V4V6, "-w", "-A", "OUTPUT", "-j", "drop_wall", NULL);}int FirewallController::setMobileDataUidRule(int uid, FirewallRule rule) {    char uidStr[16];    sprintf(uidStr, "%d", uid);    const char* op;    if (rule == ALLOW) {        op = "-D";// 删除链表中的规则    } else {        op = "-A";// 添加规则到链表    }    int res = 0;    res |= execIptables(V4V6, "-w", op, "drop_wall", "-o", op_3g, "-m", "owner",            "--uid-owner", uidStr, "-j", "REJECT", NULL);    return res;}int FirewallController::setWifiDataUidRule(int uid, FirewallRule rule) {    char uidStr[16];    sprintf(uidStr, "%d", uid);    const char* op;    if (rule == ALLOW) {        op = "-D";// 删除链表中的规则    } else {        op = "-A";// 添加规则到链表    }    int res = 0;    res |= execIptables(V4V6, "-w", op, "drop_wall", "-o", op_wifi, "-m", "owner",            "--uid-owner", uidStr, "-j", "REJECT", NULL);    return res;}. . .


方法声明在system/netd/server目录下的FirewallController.h中:

class FirewallController {    public:        . . .        int initIptableFirewall(void);        int setMobileDataUidRule(int, FirewallRule);        int setWifiDataUidRule(int, FirewallRule);        . . .}


到这里方法就添加完毕了,下面看调用,调用者必须是系统uid,要把aidl文件拷贝到android.os包下,由于NetworkManagementService是隐藏的,故需要使用方式的方式调用:

public static void setUidNetworkState(int uid, boolean enabled) {    try {        Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);        IBinder binder = (IBinder) method.invoke(null, new Object[] {"network_management"});        INetworkManagementService service = INetworkManagementService.Stub.asInterface(binder);        if (service != null) {            service.setMobileDataUidRule(uid, enabled);            service.setWifiDataUidRule(uid, enabled);        }    } catch (Exception e) {        e.printStackTrace();    }}


另外,网络端口的查看方式:

adb shellnetcfg


代码实现方式:

ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);Network[] networks = manager.getAllNetworks();for (Network item : networks) {    NetworkInfo info = manager.getNetworkInfo(item);    if (info.getType() == ConnectivityManager.TYPE_WIFI) {        String wifi = manager.getLinkProperties(item)                .getInterfaceName();        System.out.println("zyf wifi:" + wifi);    } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {        String mobile = manager.getLinkProperties(item)                .getInterfaceName();        System.out.println("zyf mobile:" + mobile);    }}


 

更多相关文章

  1. Android开发设置Activity全屏与不全屏的方法
  2. Android实现页面跳转的几种方式(转贴)
  3. Android 平台的檔案讀寫方式
  4. Android 上传图片到后台的一直方式Base64的String形式
  5. Android中监听Home键的4种方法总结
  6. Android的数据存储方式

随机推荐

  1. android使用jenkins进行自动化打包并且上
  2. Android设置窗口的背景图
  3. Android(安卓)自定义动态注册Broadcast框
  4. Android笔记:Android(安卓)使用Intent拨打
  5. Android(安卓)proguard -applymapping 导
  6. Android(安卓)TV 屏幕适配
  7. Android学习笔记(十二)——数据存储(SQLite
  8. Android(安卓)HTTP 服务
  9. android JNI入门 之helloworld
  10. SVN问题之——org.apache.subversion.jav