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