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 import static android.text.format.Time.MONTH_DAY;
     22 
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.content.pm.PackageManager;
     26 import android.content.pm.PackageManager.NameNotFoundException;
     27 import android.content.pm.Signature;
     28 import android.os.RemoteException;
     29 import android.os.UserHandle;
     30 import android.text.format.Time;
     31 
     32 import com.google.android.collect.Sets;
     33 
     34 import java.io.PrintWriter;
     35 import java.util.HashSet;
     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     /* RULE_* are not masks and they must be exclusive */
     53     /** All network traffic should be allowed. */
     54     public static final int RULE_ALLOW_ALL = 0x0;
     55     /** Reject traffic on metered networks. */
     56     public static final int RULE_REJECT_METERED = 0x1;
     57     /** Reject traffic on all networks. */
     58     public static final int RULE_REJECT_ALL = 0x2;
     59 
     60     public static final int FIREWALL_RULE_DEFAULT = 0;
     61     public static final int FIREWALL_RULE_ALLOW = 1;
     62     public static final int FIREWALL_RULE_DENY = 2;
     63 
     64     public static final int FIREWALL_TYPE_WHITELIST = 0;
     65     public static final int FIREWALL_TYPE_BLACKLIST = 1;
     66 
     67     public static final int FIREWALL_CHAIN_NONE = 0;
     68     public static final int FIREWALL_CHAIN_DOZABLE = 1;
     69     public static final int FIREWALL_CHAIN_STANDBY = 2;
     70 
     71     public static final String FIREWALL_CHAIN_NAME_NONE = "none";
     72     public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
     73     public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
     74 
     75     private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
     76 
     77     /**
     78      * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
     79      * applies to.
     80      */
     81     public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
     82 
     83     private final Context mContext;
     84     private INetworkPolicyManager mService;
     85 
     86     public NetworkPolicyManager(Context context, INetworkPolicyManager service) {
     87         if (service == null) {
     88             throw new IllegalArgumentException("missing INetworkPolicyManager");
     89         }
     90         mContext = context;
     91         mService = service;
     92     }
     93 
     94     public static NetworkPolicyManager from(Context context) {
     95         return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE);
     96     }
     97 
     98     /**
     99      * Set policy flags for specific UID.
    100      *
    101      * @param policy {@link #POLICY_NONE} or combination of flags like
    102      * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
    103      */
    104     public void setUidPolicy(int uid, int policy) {
    105         try {
    106             mService.setUidPolicy(uid, policy);
    107         } catch (RemoteException e) {
    108         }
    109     }
    110 
    111     /**
    112      * Add policy flags for specific UID.  The given policy bits will be set for
    113      * the uid.  Policy flags may be either
    114      * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
    115      */
    116     public void addUidPolicy(int uid, int policy) {
    117         try {
    118             mService.addUidPolicy(uid, policy);
    119         } catch (RemoteException e) {
    120         }
    121     }
    122 
    123     /**
    124      * Clear/remove policy flags for specific UID.  The given policy bits will be set for
    125      * the uid.  Policy flags may be either
    126      * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}.
    127      */
    128     public void removeUidPolicy(int uid, int policy) {
    129         try {
    130             mService.removeUidPolicy(uid, policy);
    131         } catch (RemoteException e) {
    132         }
    133     }
    134 
    135     public int getUidPolicy(int uid) {
    136         try {
    137             return mService.getUidPolicy(uid);
    138         } catch (RemoteException e) {
    139             return POLICY_NONE;
    140         }
    141     }
    142 
    143     public int[] getUidsWithPolicy(int policy) {
    144         try {
    145             return mService.getUidsWithPolicy(policy);
    146         } catch (RemoteException e) {
    147             return new int[0];
    148         }
    149     }
    150 
    151     public void registerListener(INetworkPolicyListener listener) {
    152         try {
    153             mService.registerListener(listener);
    154         } catch (RemoteException e) {
    155         }
    156     }
    157 
    158     public void unregisterListener(INetworkPolicyListener listener) {
    159         try {
    160             mService.unregisterListener(listener);
    161         } catch (RemoteException e) {
    162         }
    163     }
    164 
    165     public void setNetworkPolicies(NetworkPolicy[] policies) {
    166         try {
    167             mService.setNetworkPolicies(policies);
    168         } catch (RemoteException e) {
    169         }
    170     }
    171 
    172     public NetworkPolicy[] getNetworkPolicies() {
    173         try {
    174             return mService.getNetworkPolicies(mContext.getOpPackageName());
    175         } catch (RemoteException e) {
    176             return null;
    177         }
    178     }
    179 
    180     public void setRestrictBackground(boolean restrictBackground) {
    181         try {
    182             mService.setRestrictBackground(restrictBackground);
    183         } catch (RemoteException e) {
    184         }
    185     }
    186 
    187     public boolean getRestrictBackground() {
    188         try {
    189             return mService.getRestrictBackground();
    190         } catch (RemoteException e) {
    191             return false;
    192         }
    193     }
    194 
    195     /**
    196      * Resets network policy settings back to factory defaults.
    197      *
    198      * @hide
    199      */
    200     public void factoryReset(String subscriber) {
    201         try {
    202             mService.factoryReset(subscriber);
    203         } catch (RemoteException e) {
    204         }
    205     }
    206 
    207     /**
    208      * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
    209      * example, if cycle day is 20th, and today is June 15th, it will return May
    210      * 20th. When cycle day doesn't exist in current month, it snaps to the 1st
    211      * of following month.
    212      *
    213      * @hide
    214      */
    215     public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
    216         if (policy.cycleDay == CYCLE_NONE) {
    217             throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
    218         }
    219 
    220         final Time now = new Time(policy.cycleTimezone);
    221         now.set(currentTime);
    222 
    223         // first, find cycle boundary for current month
    224         final Time cycle = new Time(now);
    225         cycle.hour = cycle.minute = cycle.second = 0;
    226         snapToCycleDay(cycle, policy.cycleDay);
    227 
    228         if (Time.compare(cycle, now) >= 0) {
    229             // cycle boundary is beyond now, use last cycle boundary; start by
    230             // pushing ourselves squarely into last month.
    231             final Time lastMonth = new Time(now);
    232             lastMonth.hour = lastMonth.minute = lastMonth.second = 0;
    233             lastMonth.monthDay = 1;
    234             lastMonth.month -= 1;
    235             lastMonth.normalize(true);
    236 
    237             cycle.set(lastMonth);
    238             snapToCycleDay(cycle, policy.cycleDay);
    239         }
    240 
    241         return cycle.toMillis(true);
    242     }
    243 
    244     /** {@hide} */
    245     public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
    246         if (policy.cycleDay == CYCLE_NONE) {
    247             throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
    248         }
    249 
    250         final Time now = new Time(policy.cycleTimezone);
    251         now.set(currentTime);
    252 
    253         // first, find cycle boundary for current month
    254         final Time cycle = new Time(now);
    255         cycle.hour = cycle.minute = cycle.second = 0;
    256         snapToCycleDay(cycle, policy.cycleDay);
    257 
    258         if (Time.compare(cycle, now) <= 0) {
    259             // cycle boundary is before now, use next cycle boundary; start by
    260             // pushing ourselves squarely into next month.
    261             final Time nextMonth = new Time(now);
    262             nextMonth.hour = nextMonth.minute = nextMonth.second = 0;
    263             nextMonth.monthDay = 1;
    264             nextMonth.month += 1;
    265             nextMonth.normalize(true);
    266 
    267             cycle.set(nextMonth);
    268             snapToCycleDay(cycle, policy.cycleDay);
    269         }
    270 
    271         return cycle.toMillis(true);
    272     }
    273 
    274     /**
    275      * Snap to the cycle day for the current month given; when cycle day doesn't
    276      * exist, it snaps to last second of current month.
    277      *
    278      * @hide
    279      */
    280     public static void snapToCycleDay(Time time, int cycleDay) {
    281         if (cycleDay > time.getActualMaximum(MONTH_DAY)) {
    282             // cycle day isn't valid this month; snap to last second of month
    283             time.month += 1;
    284             time.monthDay = 1;
    285             time.second = -1;
    286         } else {
    287             time.monthDay = cycleDay;
    288         }
    289         time.normalize(true);
    290     }
    291 
    292     /**
    293      * Check if given UID can have a {@link #setUidPolicy(int, int)} defined,
    294      * usually to protect critical system services.
    295      */
    296     @Deprecated
    297     public static boolean isUidValidForPolicy(Context context, int uid) {
    298         // first, quick-reject non-applications
    299         if (!UserHandle.isApp(uid)) {
    300             return false;
    301         }
    302 
    303         if (!ALLOW_PLATFORM_APP_POLICY) {
    304             final PackageManager pm = context.getPackageManager();
    305             final HashSet<Signature> systemSignature;
    306             try {
    307                 systemSignature = Sets.newHashSet(
    308                         pm.getPackageInfo("android", GET_SIGNATURES).signatures);
    309             } catch (NameNotFoundException e) {
    310                 throw new RuntimeException("problem finding system signature", e);
    311             }
    312 
    313             try {
    314                 // reject apps signed with platform cert
    315                 for (String packageName : pm.getPackagesForUid(uid)) {
    316                     final HashSet<Signature> packageSignature = Sets.newHashSet(
    317                             pm.getPackageInfo(packageName, GET_SIGNATURES).signatures);
    318                     if (packageSignature.containsAll(systemSignature)) {
    319                         return false;
    320                     }
    321                 }
    322             } catch (NameNotFoundException e) {
    323             }
    324         }
    325 
    326         // nothing found above; we can apply policy to UID
    327         return true;
    328     }
    329 
    330     /** {@hide} */
    331     public static void dumpPolicy(PrintWriter fout, int policy) {
    332         fout.write("[");
    333         if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
    334             fout.write("REJECT_METERED_BACKGROUND");
    335         }
    336         fout.write("]");
    337     }
    338 
    339     /** {@hide} */
    340     public static void dumpRules(PrintWriter fout, int rules) {
    341         fout.write("[");
    342         if ((rules & RULE_REJECT_METERED) != 0) {
    343             fout.write("REJECT_METERED");
    344         } else if ((rules & RULE_REJECT_ALL) != 0) {
    345             fout.write("REJECT_ALL");
    346         }
    347         fout.write("]");
    348     }
    349 
    350 }
    351