1/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
20import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
21import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
22import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
23import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
24import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
25import static android.util.DebugUtils.valueToString;
26
27import static org.junit.Assert.assertEquals;
28import static org.junit.Assert.assertFalse;
29import static org.junit.Assert.assertTrue;
30
31import android.net.NetworkPolicyManager;
32import android.support.test.filters.SmallTest;
33import android.support.test.runner.AndroidJUnit4;
34import android.util.ArrayMap;
35
36import org.junit.Before;
37import org.junit.Test;
38import org.junit.runner.RunWith;
39
40import java.util.function.BiFunction;
41
42/**
43 * Test class for {@link NetworkManagementInternal}.
44 *
45 * To run the tests, use
46 *
47 * runtest -c com.android.server.NetworkManagementInternalTest frameworks-services
48 *
49 * or the following steps:
50 *
51 * Build: m FrameworksServicesTests
52 * Install: adb install -r \
53 *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
54 * Run: adb shell am instrument -e class com.android.server.NetworkManagementInternalTest -w \
55 *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
56 */
57@SmallTest
58@RunWith(AndroidJUnit4.class)
59public class NetworkManagementInternalTest {
60    private static final int TEST_UID = 111;
61
62    private NetworkManagementService.Injector mInjector;
63    private NetworkManagementInternal mNmi;
64
65    @Before
66    public void setUp() {
67        final NetworkManagementService service = new NetworkManagementService();
68        mInjector = service.getInjector();
69        mNmi = service.new LocalService();
70    }
71
72    @Test
73    public void testIsNetworkRestrictedForUid() {
74        // No firewall chains enabled
75        assertFalse(mNmi.isNetworkRestrictedForUid(TEST_UID));
76
77        // Restrict usage of mobile data in background
78        mInjector.setUidOnMeteredNetworkList(true, TEST_UID, true);
79        assertTrue("Should be true since mobile data usage is restricted",
80                mNmi.isNetworkRestrictedForUid(TEST_UID));
81        mInjector.reset();
82
83        // Data saver is on and uid is not whitelisted
84        mInjector.setDataSaverMode(true);
85        mInjector.setUidOnMeteredNetworkList(false, TEST_UID, false);
86        assertTrue("Should be true since data saver is on and the uid is not whitelisted",
87                mNmi.isNetworkRestrictedForUid(TEST_UID));
88        mInjector.reset();
89
90        // Data saver is on and uid is whitelisted
91        mInjector.setDataSaverMode(true);
92        mInjector.setUidOnMeteredNetworkList(false, TEST_UID, true);
93        assertFalse("Should be false since data saver is on and the uid is whitelisted",
94                mNmi.isNetworkRestrictedForUid(TEST_UID));
95        mInjector.reset();
96
97        final ArrayMap<Integer, ArrayMap<Integer, Boolean>> expected = new ArrayMap<>();
98        // Dozable chain
99        final ArrayMap<Integer, Boolean> isRestrictedForDozable = new ArrayMap<>();
100        isRestrictedForDozable.put(FIREWALL_RULE_DEFAULT, true);
101        isRestrictedForDozable.put(FIREWALL_RULE_ALLOW, false);
102        isRestrictedForDozable.put(FIREWALL_RULE_DENY, true);
103        expected.put(FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
104        // Powersaver chain
105        final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>();
106        isRestrictedForPowerSave.put(FIREWALL_RULE_DEFAULT, true);
107        isRestrictedForPowerSave.put(FIREWALL_RULE_ALLOW, false);
108        isRestrictedForPowerSave.put(FIREWALL_RULE_DENY, true);
109        expected.put(FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
110        // Standby chain
111        final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>();
112        isRestrictedForStandby.put(FIREWALL_RULE_DEFAULT, false);
113        isRestrictedForStandby.put(FIREWALL_RULE_ALLOW, false);
114        isRestrictedForStandby.put(FIREWALL_RULE_DENY, true);
115        expected.put(FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
116
117        final int[] chains = {
118                FIREWALL_CHAIN_STANDBY,
119                FIREWALL_CHAIN_POWERSAVE,
120                FIREWALL_CHAIN_DOZABLE
121        };
122        final int[] states = {
123                FIREWALL_RULE_ALLOW,
124                FIREWALL_RULE_DENY,
125                FIREWALL_RULE_DEFAULT
126        };
127        BiFunction<Integer, Integer, String> errorMsg = (chain, state) -> {
128            return String.format("Unexpected value for chain: %s and state: %s",
129                    valueToString(NetworkPolicyManager.class, "FIREWALL_CHAIN_", chain),
130                    valueToString(NetworkPolicyManager.class, "FIREWALL_RULE_", state));
131        };
132        for (int chain : chains) {
133            final ArrayMap<Integer, Boolean> expectedValues = expected.get(chain);
134            mInjector.setFirewallChainState(chain, true);
135            for (int state : states) {
136                mInjector.setFirewallRule(chain, TEST_UID, state);
137                assertEquals(errorMsg.apply(chain, state),
138                        expectedValues.get(state), mNmi.isNetworkRestrictedForUid(TEST_UID));
139            }
140            mInjector.reset();
141        }
142    }
143}
144