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