需求:可以控制某个应用访问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. ActivityThread 源码笔记(1)
  2. Android程序入口ActivityThread和Android应用程序启动流程详解
  3. Android生命周期学习笔记
  4. 两分钟彻底让你明白Android中onInterceptTouchEvent与onTouchEve
  5. Android实现页面跳转的几种方式(转贴)
  6. Android(安卓)平台的檔案讀寫方式
  7. 修改Android系统属性SystemProperties.set("sys.powerctl", "shu
  8. Android(安卓)上传图片到后台的一直方式Base64的String形式
  9. 横屏和竖屏切换界面不刷新

随机推荐

  1. adroid app权限实现方式
  2. android 团队开发技巧1 - activity 启动
  3. carLife 车机端集成
  4. Android中使用Handler引发的内存泄露
  5. Mars视频笔记——ExpandableListActivity
  6. 管理Android库项目
  7. android基础-界面代码
  8. Android 中的高效数据结构
  9. Java + TestNG + Appium 实现单机多个And
  10. Android 开发中遇到的 bug(8)