Android 8.1 Doze模式分析(二)对网络的限制

在第一篇Android 8.1 Doze模式分析(一)我们知道,进入idle模式后调用NetworkPolicyManagerService.java的setDeviceIdleMode()对网络进行限制,现在我们就开始分析网络限制的流程

    @Override
    public void setDeviceIdleMode(boolean enabled) {
        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setDeviceIdleMode");
        try {
            synchronized (mUidRulesFirstLock) {
                if (mDeviceIdleMode == enabled) {
                    return;
                }
                mDeviceIdleMode = enabled;
                if (mSystemReady) {
                    // Device idle change means we need to rebuild rules for all
                    // known apps, so do a global refresh.
                    updateRulesForRestrictPowerUL();
                }
            }
            if (enabled) {
                EventLogTags.writeDeviceIdleOnPhase("net");
            } else {
                EventLogTags.writeDeviceIdleOffPhase("net");
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

NetworkPolicyManagerService.java-->updateRulesForRestrictPowerUL()

    private void updateRulesForRestrictPowerUL() {
        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL");
        try {
            updateRulesForDeviceIdleUL();
            updateRulesForPowerSaveUL();
            updateRulesForAllAppsUL(TYPE_RESTRICT_POWER);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

首先看下updateRulesForDeviceIdleUL()方法

    void updateRulesForDeviceIdleUL() {
        Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForDeviceIdleUL");
        try {
            updateRulesForWhitelistedPowerSaveUL(mDeviceIdleMode, FIREWALL_CHAIN_DOZABLE,
                    mUidFirewallDozableRules);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

NetworkPolicyManagerService.java-->updateRulesForWhitelistedPowerSaveUL()

    private void updateRulesForWhitelistedPowerSaveUL(boolean enabled, int chain,
            SparseIntArray rules) {
        if (enabled) {
            // Sync the whitelists before enabling the chain.  We don't care about the rules if
            // we are disabling the chain.
            final SparseIntArray uidRules = rules;
            uidRules.clear();
            final List<UserInfo> users = mUserManager.getUsers();
            for (int ui = users.size() - 1; ui >= 0; ui--) {
                UserInfo user = users.get(ui);
                updateRulesForWhitelistedAppIds(uidRules, mPowerSaveTempWhitelistAppIds, user.id);
                updateRulesForWhitelistedAppIds(uidRules, mPowerSaveWhitelistAppIds, user.id);
                if (chain == FIREWALL_CHAIN_POWERSAVE) {
                    updateRulesForWhitelistedAppIds(uidRules,
                            mPowerSaveWhitelistExceptIdleAppIds, user.id);
                }
            }
            for (int i = mUidState.size() - 1; i >= 0; i--) {
                //如果应用在白名单里,这是rule为FIREWALL_RULE_ALLOW
                if (isProcStateAllowedWhileIdleOrPowerSaveMode(mUidState.valueAt(i))
                        // for bug#776330, wechat cannot receive msg in low-power mode
                    || mAbsDeviceIdleController.isInPresetWhiteAppList(mUidState.keyAt(i))) {
                    uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
                }
            }
            setUidFirewallRulesUL(chain, uidRules, CHAIN_TOGGLE_ENABLE);
        } else {
            setUidFirewallRulesUL(chain, null, CHAIN_TOGGLE_DISABLE);
        }
    }

首先分析下三个参数,因为已经进入到了zone模式,所以mDeviceIdleMode未true,FIREWALL_CHAIN_DOZABLE是FIREWALL的CHAIN模式的四种之一

    public static final int FIREWALL_CHAIN_NONE = 0;
    public static final int FIREWALL_CHAIN_DOZABLE = 1;
    public static final int FIREWALL_CHAIN_STANDBY = 2;
    public static final int FIREWALL_CHAIN_POWERSAVE = 3;

我们在看下最后一个参数mUidFirewallDozableRules,是一个SparseIntArray 对象

    @GuardedBy("mUidRulesFirstLock")
    final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();

在setUidFirewallRule中,就应用的uid和rule 存入进去

    /**
     * Add or remove a uid to the firewall blacklist for all network ifaces.
     */
    private void setUidFirewallRule(int chain, int uid, int rule) {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) {
            Trace.traceBegin(Trace.TRACE_TAG_NETWORK,
                    "setUidFirewallRule: " + chain + "/" + uid + "/" + rule);
        }
        try {
            if (chain == FIREWALL_CHAIN_DOZABLE) {
                mUidFirewallDozableRules.put(uid, rule);
            } else if (chain == FIREWALL_CHAIN_STANDBY) {
                mUidFirewallStandbyRules.put(uid, rule);
            } else if (chain == FIREWALL_CHAIN_POWERSAVE) {
                mUidFirewallPowerSaveRules.put(uid, rule);
            }

            try {
                mNetworkManager.setFirewallUidRule(chain, uid, rule);
            } catch (IllegalStateException e) {
                Log.wtf(TAG, "problem setting firewall uid rules", e);
            } catch (RemoteException e) {
                // ignored; service lives in system_server
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
        }
    }

参数分析完后,我们看下setUidFirewallRulesUL()

    private void setUidFirewallRulesUL(int chain, @Nullable SparseIntArray uidRules,
            @ChainToggleType int toggle) {
        if (uidRules != null) {
            setUidFirewallRulesUL(chain, uidRules);
        }
        if (toggle != CHAIN_TOGGLE_NONE) {
            enableFirewallChainUL(chain, toggle == CHAIN_TOGGLE_ENABLE);
        }
    }

setUidFirewallRulesUL()

    private void setUidFirewallRulesUL(int chain, SparseIntArray uidRules) {
        try {
            int size = uidRules.size();
            int[] uids = new int[size];
            int[] rules = new int[size];
            for(int index = size - 1; index >= 0; --index) {
                uids[index] = uidRules.keyAt(index);
                rules[index] = uidRules.valueAt(index);
            }
            mNetworkManager.setFirewallUidRules(chain, uids, rules);
        } catch (IllegalStateException e) {
            Log.wtf(TAG, "problem setting firewall uid rules", e);
        } catch (RemoteException e) {
            // ignored; service lives in system_server
        }
    }

NetworkManagementService.java-->setFirewallUidRules()

@Override
    public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
        enforceSystemUid();
        synchronized (mQuotaLock) {
            synchronized (mRulesLock) {
                SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
                SparseIntArray newRules = new SparseIntArray();
                // apply new set of rules
                for (int index = uids.length - 1; index >= 0; --index) {
                    int uid = uids[index];
                    int rule = rules[index];
                    updateFirewallUidRuleLocked(chain, uid, rule);
                    newRules.put(uid, rule);
                }
                // collect the rules to remove.
                SparseIntArray rulesToRemove = new SparseIntArray();
                for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
                    int uid = uidFirewallRules.keyAt(index);
                    if (newRules.indexOfKey(uid) < 0) {
                        rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
                    }
                }
                // remove dead rules
                for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
                    int uid = rulesToRemove.keyAt(index);
                    updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
                }
            }
            try {
                switch (chain) {
                    case FIREWALL_CHAIN_DOZABLE:
                        mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
                        break;
                    case FIREWALL_CHAIN_STANDBY:
                        mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
                        break;
                    case FIREWALL_CHAIN_POWERSAVE:
                        mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
                        break;
                    case FIREWALL_CHAIN_NONE:
                    default:
                        Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
                }
            } catch (RemoteException e) {
                Slog.w(TAG, "Error flushing firewall chain " + chain, e);
            }
        }
    }

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在Linux上安装防火墙,您可以按照以下步骤进行操作: 1. 确定您的Linux发行版:不同的Linux发行版可能会使用不同的防火墙软件。常见的选择包括iptables(适用于大多数发行版)和firewalld(适用于CentOS 7及更高版本)。 2. 检查防火墙状态:在安装新的防火墙之前,您可以先检查当前系统上是否已经安装了防火墙。使用以下命令来检查iptables是否已经安装和启动: ``` sudo iptables -L ``` 或者检查firewalld的状态: ``` sudo systemctl status firewalld ``` 3. 安装防火墙软件:根据您的Linux发行版,执行相应的命令来安装防火墙软件。例如,对于基于Debian的发行版(如Ubuntu),可以使用以下命令来安装iptables: ``` sudo apt-get install iptables ``` 对于CentOS 7及更高版本,可以使用以下命令来安装firewalld: ``` sudo yum install firewalld ``` 4. 配置防火墙规则:一旦防火墙软件安装完成,您需要配置适合您系统需求的防火墙规则。具体的配置方法取决于所使用的防火墙软件。您可以参考相关文档或教程,以了解如何配置规则。 对于iptables,您可以使用`iptables`命令来添加、删除和修改规则。例如,要允许SSH连接,可以执行以下命令: ``` sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT ``` 对于firewalld,您可以使用`firewall-cmd`命令来管理规则。例如,要允许SSH连接,可以执行以下命令: ``` sudo firewall-cmd --zone=public --add-port=22/tcp --permanent ``` 注意,在这两个例子,规则只是为SSH连接开放了相应的端口。您需要根据您的需求和网络配置添加其他规则。 5. 启用防火墙:最后,您需要启用并启动防火墙软件。使用以下命令启用iptables: ``` sudo systemctl enable iptables sudo systemctl start iptables ``` 使用以下命令启用firewalld: ``` sudo systemctl enable firewalld sudo systemctl start firewalld ``` 确保在系统重启后防火墙能够自动启动。 请注意,配置防火墙时需要小心,确保只开放必要的端口和服务,并始终保持系统的安全性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值