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