1/*
2 * Copyright (C) 2011 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 android.net;
18
19import static android.content.pm.PackageManager.GET_SIGNATURES;
20import static android.net.NetworkPolicy.CYCLE_NONE;
21import static android.text.format.Time.MONTH_DAY;
22
23import android.content.Context;
24import android.content.Intent;
25import android.content.pm.PackageManager;
26import android.content.pm.PackageManager.NameNotFoundException;
27import android.content.pm.Signature;
28import android.os.RemoteException;
29import android.os.UserHandle;
30import android.text.format.Time;
31import android.util.DebugUtils;
32
33import com.google.android.collect.Sets;
34
35import java.util.HashSet;
36
37/**
38 * Manager for creating and modifying network policy rules.
39 *
40 * {@hide}
41 */
42public class NetworkPolicyManager {
43
44    /* POLICY_* are masks and can be ORed */
45    /** No specific network policy, use system default. */
46    public static final int POLICY_NONE = 0x0;
47    /** Reject network usage on metered networks when application in background. */
48    public static final int POLICY_REJECT_METERED_BACKGROUND = 0x1;
49    /** Allow network use (metered or not) in the background in battery save mode. */
50    public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2;
51
52    /*
53     * Rules defining whether an uid has access to a network given its type (metered / non-metered).
54     *
55     * These rules are bits and can be used in bitmask operations; in particular:
56     * - rule & RULE_MASK_METERED: returns the metered-networks status.
57     * - rule & RULE_MASK_ALL: returns the all-networks status.
58     *
59     * The RULE_xxx_ALL rules applies to all networks (metered or non-metered), but on
60     * metered networks, the RULE_xxx_METERED rules should be checked first. For example,
61     * if the device is on Battery Saver Mode and Data Saver Mode simulatenously, and a uid
62     * is whitelisted for the former but not the latter, its status would be
63     * RULE_REJECT_METERED | RULE_ALLOW_ALL, meaning it could have access to non-metered
64     * networks but not to metered networks.
65     *
66     * See network-policy-restrictions.md for more info.
67     */
68    /** No specific rule was set */
69    public static final int RULE_NONE = 0;
70    /** Allow traffic on metered networks. */
71    public static final int RULE_ALLOW_METERED = 1 << 0;
72    /** Temporarily allow traffic on metered networks because app is on foreground. */
73    public static final int RULE_TEMPORARY_ALLOW_METERED = 1 << 1;
74    /** Reject traffic on metered networks. */
75    public static final int RULE_REJECT_METERED = 1 << 2;
76    /** Network traffic should be allowed on all networks (metered or non-metered), although
77     * metered-network restrictions could still apply. */
78    public static final int RULE_ALLOW_ALL = 1 << 5;
79    /** Reject traffic on all networks. */
80    public static final int RULE_REJECT_ALL = 1 << 6;
81    /** Mask used to get the {@code RULE_xxx_METERED} rules */
82    public static final int MASK_METERED_NETWORKS = 0b00001111;
83    /** Mask used to get the {@code RULE_xxx_ALL} rules */
84    public static final int MASK_ALL_NETWORKS     = 0b11110000;
85
86    public static final int FIREWALL_RULE_DEFAULT = 0;
87    public static final int FIREWALL_RULE_ALLOW = 1;
88    public static final int FIREWALL_RULE_DENY = 2;
89
90    public static final int FIREWALL_TYPE_WHITELIST = 0;
91    public static final int FIREWALL_TYPE_BLACKLIST = 1;
92
93    public static final int FIREWALL_CHAIN_NONE = 0;
94    public static final int FIREWALL_CHAIN_DOZABLE = 1;
95    public static final int FIREWALL_CHAIN_STANDBY = 2;
96    public static final int FIREWALL_CHAIN_POWERSAVE = 3;
97
98    public static final String FIREWALL_CHAIN_NAME_NONE = "none";
99    public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
100    public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
101    public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
102
103    private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
104
105    /**
106     * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
107     * applies to.
108     */
109    public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
110
111    private final Context mContext;
112    private INetworkPolicyManager mService;
113
114    public NetworkPolicyManager(Context context, INetworkPolicyManager service) {
115        if (service == null) {
116            throw new IllegalArgumentException("missing INetworkPolicyManager");
117        }
118        mContext = context;
119        mService = service;
120    }
121
122    public static NetworkPolicyManager from(Context context) {
123        return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE);
124    }
125
126    /**
127     * Set policy flags for specific UID.
128     *
129     * @param policy {@link #POLICY_NONE} or combination of flags like
130     * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
131     */
132    public void setUidPolicy(int uid, int policy) {
133        try {
134            mService.setUidPolicy(uid, policy);
135        } catch (RemoteException e) {
136            throw e.rethrowFromSystemServer();
137        }
138    }
139
140    /**
141     * Add policy flags for specific UID.  The given policy bits will be set for
142     * the uid.  Policy flags may be either
143     * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
144     */
145    public void addUidPolicy(int uid, int policy) {
146        try {
147            mService.addUidPolicy(uid, policy);
148        } catch (RemoteException e) {
149            throw e.rethrowFromSystemServer();
150        }
151    }
152
153    /**
154     * Clear/remove policy flags for specific UID.  The given policy bits will be set for
155     * the uid.  Policy flags may be either
156     * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
157     */
158    public void removeUidPolicy(int uid, int policy) {
159        try {
160            mService.removeUidPolicy(uid, policy);
161        } catch (RemoteException e) {
162            throw e.rethrowFromSystemServer();
163        }
164    }
165
166    public int getUidPolicy(int uid) {
167        try {
168            return mService.getUidPolicy(uid);
169        } catch (RemoteException e) {
170            throw e.rethrowFromSystemServer();
171        }
172    }
173
174    public int[] getUidsWithPolicy(int policy) {
175        try {
176            return mService.getUidsWithPolicy(policy);
177        } catch (RemoteException e) {
178            throw e.rethrowFromSystemServer();
179        }
180    }
181
182    public void registerListener(INetworkPolicyListener listener) {
183        try {
184            mService.registerListener(listener);
185        } catch (RemoteException e) {
186            throw e.rethrowFromSystemServer();
187        }
188    }
189
190    public void unregisterListener(INetworkPolicyListener listener) {
191        try {
192            mService.unregisterListener(listener);
193        } catch (RemoteException e) {
194            throw e.rethrowFromSystemServer();
195        }
196    }
197
198    public void setNetworkPolicies(NetworkPolicy[] policies) {
199        try {
200            mService.setNetworkPolicies(policies);
201        } catch (RemoteException e) {
202            throw e.rethrowFromSystemServer();
203        }
204    }
205
206    public NetworkPolicy[] getNetworkPolicies() {
207        try {
208            return mService.getNetworkPolicies(mContext.getOpPackageName());
209        } catch (RemoteException e) {
210            throw e.rethrowFromSystemServer();
211        }
212    }
213
214    public void setRestrictBackground(boolean restrictBackground) {
215        try {
216            mService.setRestrictBackground(restrictBackground);
217        } catch (RemoteException e) {
218            throw e.rethrowFromSystemServer();
219        }
220    }
221
222    public boolean getRestrictBackground() {
223        try {
224            return mService.getRestrictBackground();
225        } catch (RemoteException e) {
226            throw e.rethrowFromSystemServer();
227        }
228    }
229
230    /**
231     * Resets network policy settings back to factory defaults.
232     *
233     * @hide
234     */
235    public void factoryReset(String subscriber) {
236        try {
237            mService.factoryReset(subscriber);
238        } catch (RemoteException e) {
239            throw e.rethrowFromSystemServer();
240        }
241    }
242
243    /**
244     * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
245     * example, if cycle day is 20th, and today is June 15th, it will return May
246     * 20th. When cycle day doesn't exist in current month, it snaps to the 1st
247     * of following month.
248     *
249     * @hide
250     */
251    public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
252        if (policy.cycleDay == CYCLE_NONE) {
253            throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
254        }
255
256        final Time now = new Time(policy.cycleTimezone);
257        now.set(currentTime);
258
259        // first, find cycle boundary for current month
260        final Time cycle = new Time(now);
261        cycle.hour = cycle.minute = cycle.second = 0;
262        snapToCycleDay(cycle, policy.cycleDay);
263
264        if (Time.compare(cycle, now) >= 0) {
265            // cycle boundary is beyond now, use last cycle boundary; start by
266            // pushing ourselves squarely into last month.
267            final Time lastMonth = new Time(now);
268            lastMonth.hour = lastMonth.minute = lastMonth.second = 0;
269            lastMonth.monthDay = 1;
270            lastMonth.month -= 1;
271            lastMonth.normalize(true);
272
273            cycle.set(lastMonth);
274            snapToCycleDay(cycle, policy.cycleDay);
275        }
276
277        return cycle.toMillis(true);
278    }
279
280    /** {@hide} */
281    public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
282        if (policy.cycleDay == CYCLE_NONE) {
283            throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
284        }
285
286        final Time now = new Time(policy.cycleTimezone);
287        now.set(currentTime);
288
289        // first, find cycle boundary for current month
290        final Time cycle = new Time(now);
291        cycle.hour = cycle.minute = cycle.second = 0;
292        snapToCycleDay(cycle, policy.cycleDay);
293
294        if (Time.compare(cycle, now) <= 0) {
295            // cycle boundary is before now, use next cycle boundary; start by
296            // pushing ourselves squarely into next month.
297            final Time nextMonth = new Time(now);
298            nextMonth.hour = nextMonth.minute = nextMonth.second = 0;
299            nextMonth.monthDay = 1;
300            nextMonth.month += 1;
301            nextMonth.normalize(true);
302
303            cycle.set(nextMonth);
304            snapToCycleDay(cycle, policy.cycleDay);
305        }
306
307        return cycle.toMillis(true);
308    }
309
310    /**
311     * Snap to the cycle day for the current month given; when cycle day doesn't
312     * exist, it snaps to last second of current month.
313     *
314     * @hide
315     */
316    public static void snapToCycleDay(Time time, int cycleDay) {
317        if (cycleDay > time.getActualMaximum(MONTH_DAY)) {
318            // cycle day isn't valid this month; snap to last second of month
319            time.month += 1;
320            time.monthDay = 1;
321            time.second = -1;
322        } else {
323            time.monthDay = cycleDay;
324        }
325        time.normalize(true);
326    }
327
328    /**
329     * Check if given UID can have a {@link #setUidPolicy(int, int)} defined,
330     * usually to protect critical system services.
331     */
332    @Deprecated
333    public static boolean isUidValidForPolicy(Context context, int uid) {
334        // first, quick-reject non-applications
335        if (!UserHandle.isApp(uid)) {
336            return false;
337        }
338
339        if (!ALLOW_PLATFORM_APP_POLICY) {
340            final PackageManager pm = context.getPackageManager();
341            final HashSet<Signature> systemSignature;
342            try {
343                systemSignature = Sets.newHashSet(
344                        pm.getPackageInfo("android", GET_SIGNATURES).signatures);
345            } catch (NameNotFoundException e) {
346                throw new RuntimeException("problem finding system signature", e);
347            }
348
349            try {
350                // reject apps signed with platform cert
351                for (String packageName : pm.getPackagesForUid(uid)) {
352                    final HashSet<Signature> packageSignature = Sets.newHashSet(
353                            pm.getPackageInfo(packageName, GET_SIGNATURES).signatures);
354                    if (packageSignature.containsAll(systemSignature)) {
355                        return false;
356                    }
357                }
358            } catch (NameNotFoundException e) {
359            }
360        }
361
362        // nothing found above; we can apply policy to UID
363        return true;
364    }
365
366    /*
367     * @hide
368     */
369    public static String uidRulesToString(int uidRules) {
370        final StringBuilder string = new StringBuilder().append(uidRules).append(" (");
371        if (uidRules == RULE_NONE) {
372            string.append("NONE");
373        } else {
374            string.append(DebugUtils.flagsToString(NetworkPolicyManager.class, "RULE_", uidRules));
375        }
376        string.append(")");
377        return string.toString();
378    }
379}
380