Home | History | Annotate | Download | only in net
      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 
     17 package android.net;
     18 
     19 import static android.content.pm.PackageManager.GET_SIGNATURES;
     20 import static android.net.NetworkPolicy.CYCLE_NONE;
     21 
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.pm.PackageManager;
     25 import android.content.pm.PackageManager.NameNotFoundException;
     26 import android.content.pm.Signature;
     27 import android.os.RemoteException;
     28 import android.os.UserHandle;
     29 import android.util.DebugUtils;
     30 
     31 import com.google.android.collect.Sets;
     32 
     33 import java.util.Calendar;
     34 import java.util.HashSet;
     35 import java.util.TimeZone;
     36 
     37 /**
     38  * Manager for creating and modifying network policy rules.
     39  *
     40  * {@hide}
     41  */
     42 public 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 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(policy.cycleTimezone));
    257         cal.setTimeInMillis(currentTime);
    258         snapToCycleDay(cal, policy.cycleDay);
    259 
    260         if (cal.getTimeInMillis() >= currentTime) {
    261             // Cycle boundary is beyond now, use last cycle boundary
    262             cal.set(Calendar.DAY_OF_MONTH, 1);
    263             cal.add(Calendar.MONTH, -1);
    264             snapToCycleDay(cal, policy.cycleDay);
    265         }
    266 
    267         return cal.getTimeInMillis();
    268     }
    269 
    270     /** {@hide} */
    271     public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
    272         if (policy.cycleDay == CYCLE_NONE) {
    273             throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
    274         }
    275 
    276         final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(policy.cycleTimezone));
    277         cal.setTimeInMillis(currentTime);
    278         snapToCycleDay(cal, policy.cycleDay);
    279 
    280         if (cal.getTimeInMillis() <= currentTime) {
    281             // Cycle boundary is before now, use next cycle boundary
    282             cal.set(Calendar.DAY_OF_MONTH, 1);
    283             cal.add(Calendar.MONTH, 1);
    284             snapToCycleDay(cal, policy.cycleDay);
    285         }
    286 
    287         return cal.getTimeInMillis();
    288     }
    289 
    290     /**
    291      * Snap to the cycle day for the current month given; when cycle day doesn't
    292      * exist, it snaps to last second of current month.
    293      *
    294      * @hide
    295      */
    296     public static void snapToCycleDay(Calendar cal, int cycleDay) {
    297         cal.set(Calendar.HOUR_OF_DAY, 0);
    298         cal.set(Calendar.MINUTE, 0);
    299         cal.set(Calendar.SECOND, 0);
    300         if (cycleDay > cal.getActualMaximum(Calendar.DAY_OF_MONTH)) {
    301             cal.set(Calendar.DAY_OF_MONTH, 1);
    302             cal.add(Calendar.MONTH, 1);
    303             cal.add(Calendar.SECOND, -1);
    304         } else {
    305             cal.set(Calendar.DAY_OF_MONTH, cycleDay);
    306         }
    307     }
    308 
    309     /**
    310      * Check if given UID can have a {@link #setUidPolicy(int, int)} defined,
    311      * usually to protect critical system services.
    312      */
    313     @Deprecated
    314     public static boolean isUidValidForPolicy(Context context, int uid) {
    315         // first, quick-reject non-applications
    316         if (!UserHandle.isApp(uid)) {
    317             return false;
    318         }
    319 
    320         if (!ALLOW_PLATFORM_APP_POLICY) {
    321             final PackageManager pm = context.getPackageManager();
    322             final HashSet<Signature> systemSignature;
    323             try {
    324                 systemSignature = Sets.newHashSet(
    325                         pm.getPackageInfo("android", GET_SIGNATURES).signatures);
    326             } catch (NameNotFoundException e) {
    327                 throw new RuntimeException("problem finding system signature", e);
    328             }
    329 
    330             try {
    331                 // reject apps signed with platform cert
    332                 for (String packageName : pm.getPackagesForUid(uid)) {
    333                     final HashSet<Signature> packageSignature = Sets.newHashSet(
    334                             pm.getPackageInfo(packageName, GET_SIGNATURES).signatures);
    335                     if (packageSignature.containsAll(systemSignature)) {
    336                         return false;
    337                     }
    338                 }
    339             } catch (NameNotFoundException e) {
    340             }
    341         }
    342 
    343         // nothing found above; we can apply policy to UID
    344         return true;
    345     }
    346 
    347     /*
    348      * @hide
    349      */
    350     public static String uidRulesToString(int uidRules) {
    351         final StringBuilder string = new StringBuilder().append(uidRules).append(" (");
    352         if (uidRules == RULE_NONE) {
    353             string.append("NONE");
    354         } else {
    355             string.append(DebugUtils.flagsToString(NetworkPolicyManager.class, "RULE_", uidRules));
    356         }
    357         string.append(")");
    358         return string.toString();
    359     }
    360 }
    361