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.text.format.Time.MONTH_DAY;
     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.text.format.Time;
     29 
     30 import com.google.android.collect.Sets;
     31 
     32 import java.io.PrintWriter;
     33 import java.util.HashSet;
     34 
     35 /**
     36  * Manager for creating and modifying network policy rules.
     37  *
     38  * {@hide}
     39  */
     40 public class NetworkPolicyManager {
     41 
     42     /** No specific network policy, use system default. */
     43     public static final int POLICY_NONE = 0x0;
     44     /** Reject network usage on metered networks when application in background. */
     45     public static final int POLICY_REJECT_METERED_BACKGROUND = 0x1;
     46 
     47     /** All network traffic should be allowed. */
     48     public static final int RULE_ALLOW_ALL = 0x0;
     49     /** Reject traffic on metered networks. */
     50     public static final int RULE_REJECT_METERED = 0x1;
     51 
     52     private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
     53 
     54     /**
     55      * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
     56      * applies to.
     57      */
     58     public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
     59 
     60     private INetworkPolicyManager mService;
     61 
     62     public NetworkPolicyManager(INetworkPolicyManager service) {
     63         if (service == null) {
     64             throw new IllegalArgumentException("missing INetworkPolicyManager");
     65         }
     66         mService = service;
     67     }
     68 
     69     public static NetworkPolicyManager getSystemService(Context context) {
     70         return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE);
     71     }
     72 
     73     /** {@hide} */
     74     public void setNetworkPolicies(NetworkPolicy[] policies) {
     75         try {
     76             mService.setNetworkPolicies(policies);
     77         } catch (RemoteException e) {
     78         }
     79     }
     80 
     81     /** {@hide} */
     82     public NetworkPolicy[] getNetworkPolicies() {
     83         try {
     84             return mService.getNetworkPolicies();
     85         } catch (RemoteException e) {
     86             return null;
     87         }
     88     }
     89 
     90     /**
     91      * Set policy flags for specific UID.
     92      *
     93      * @param policy {@link #POLICY_NONE} or combination of flags like
     94      *            {@link #POLICY_REJECT_METERED_BACKGROUND}.
     95      */
     96     public void setUidPolicy(int uid, int policy) {
     97         try {
     98             mService.setUidPolicy(uid, policy);
     99         } catch (RemoteException e) {
    100         }
    101     }
    102 
    103     public int getUidPolicy(int uid) {
    104         try {
    105             return mService.getUidPolicy(uid);
    106         } catch (RemoteException e) {
    107             return POLICY_NONE;
    108         }
    109     }
    110 
    111     public void registerListener(INetworkPolicyListener listener) {
    112         try {
    113             mService.registerListener(listener);
    114         } catch (RemoteException e) {
    115         }
    116     }
    117 
    118     public void unregisterListener(INetworkPolicyListener listener) {
    119         try {
    120             mService.unregisterListener(listener);
    121         } catch (RemoteException e) {
    122         }
    123     }
    124 
    125     /**
    126      * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
    127      * example, if cycle day is 20th, and today is June 15th, it will return May
    128      * 20th. When cycle day doesn't exist in current month, it snaps to the 1st
    129      * of following month.
    130      *
    131      * @hide
    132      */
    133     public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
    134         final Time now = new Time(Time.TIMEZONE_UTC);
    135         now.set(currentTime);
    136 
    137         // first, find cycle boundary for current month
    138         final Time cycle = new Time(now);
    139         cycle.hour = cycle.minute = cycle.second = 0;
    140         snapToCycleDay(cycle, policy.cycleDay);
    141 
    142         if (Time.compare(cycle, now) >= 0) {
    143             // cycle boundary is beyond now, use last cycle boundary; start by
    144             // pushing ourselves squarely into last month.
    145             final Time lastMonth = new Time(now);
    146             lastMonth.hour = lastMonth.minute = lastMonth.second = 0;
    147             lastMonth.monthDay = 1;
    148             lastMonth.month -= 1;
    149             lastMonth.normalize(true);
    150 
    151             cycle.set(lastMonth);
    152             snapToCycleDay(cycle, policy.cycleDay);
    153         }
    154 
    155         return cycle.toMillis(true);
    156     }
    157 
    158     /** {@hide} */
    159     public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
    160         final Time now = new Time(Time.TIMEZONE_UTC);
    161         now.set(currentTime);
    162 
    163         // first, find cycle boundary for current month
    164         final Time cycle = new Time(now);
    165         cycle.hour = cycle.minute = cycle.second = 0;
    166         snapToCycleDay(cycle, policy.cycleDay);
    167 
    168         if (Time.compare(cycle, now) <= 0) {
    169             // cycle boundary is before now, use next cycle boundary; start by
    170             // pushing ourselves squarely into next month.
    171             final Time nextMonth = new Time(now);
    172             nextMonth.hour = nextMonth.minute = nextMonth.second = 0;
    173             nextMonth.monthDay = 1;
    174             nextMonth.month += 1;
    175             nextMonth.normalize(true);
    176 
    177             cycle.set(nextMonth);
    178             snapToCycleDay(cycle, policy.cycleDay);
    179         }
    180 
    181         return cycle.toMillis(true);
    182     }
    183 
    184     /**
    185      * Snap to the cycle day for the current month given; when cycle day doesn't
    186      * exist, it snaps to 1st of following month.
    187      *
    188      * @hide
    189      */
    190     public static void snapToCycleDay(Time time, int cycleDay) {
    191         if (cycleDay > time.getActualMaximum(MONTH_DAY)) {
    192             // cycle day isn't valid this month; snap to last second of month
    193             time.month += 1;
    194             time.monthDay = 1;
    195             time.second = -1;
    196         } else {
    197             time.monthDay = cycleDay;
    198         }
    199         time.normalize(true);
    200     }
    201 
    202     /**
    203      * Check if given UID can have a {@link #setUidPolicy(int, int)} defined,
    204      * usually to protect critical system services.
    205      */
    206     public static boolean isUidValidForPolicy(Context context, int uid) {
    207         // first, quick-reject non-applications
    208         if (uid < android.os.Process.FIRST_APPLICATION_UID
    209                 || uid > android.os.Process.LAST_APPLICATION_UID) {
    210             return false;
    211         }
    212 
    213         if (!ALLOW_PLATFORM_APP_POLICY) {
    214             final PackageManager pm = context.getPackageManager();
    215             final HashSet<Signature> systemSignature;
    216             try {
    217                 systemSignature = Sets.newHashSet(
    218                         pm.getPackageInfo("android", GET_SIGNATURES).signatures);
    219             } catch (NameNotFoundException e) {
    220                 throw new RuntimeException("problem finding system signature", e);
    221             }
    222 
    223             try {
    224                 // reject apps signed with platform cert
    225                 for (String packageName : pm.getPackagesForUid(uid)) {
    226                     final HashSet<Signature> packageSignature = Sets.newHashSet(
    227                             pm.getPackageInfo(packageName, GET_SIGNATURES).signatures);
    228                     if (packageSignature.containsAll(systemSignature)) {
    229                         return false;
    230                     }
    231                 }
    232             } catch (NameNotFoundException e) {
    233             }
    234         }
    235 
    236         // nothing found above; we can apply policy to UID
    237         return true;
    238     }
    239 
    240     /** {@hide} */
    241     public static void dumpPolicy(PrintWriter fout, int policy) {
    242         fout.write("[");
    243         if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
    244             fout.write("REJECT_METERED_BACKGROUND");
    245         }
    246         fout.write("]");
    247     }
    248 
    249     /** {@hide} */
    250     public static void dumpRules(PrintWriter fout, int rules) {
    251         fout.write("[");
    252         if ((rules & RULE_REJECT_METERED) != 0) {
    253             fout.write("REJECT_METERED");
    254         }
    255         fout.write("]");
    256     }
    257 
    258 }
    259