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 
NetworkPolicyManager(Context context, INetworkPolicyManager service)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 
from(Context context)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      */
setUidPolicy(int uid, int policy)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      */
addUidPolicy(int uid, int policy)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      */
removeUidPolicy(int uid, int policy)128     public void removeUidPolicy(int uid, int policy) {
129         try {
130             mService.removeUidPolicy(uid, policy);
131         } catch (RemoteException e) {
132         }
133     }
134 
getUidPolicy(int uid)135     public int getUidPolicy(int uid) {
136         try {
137             return mService.getUidPolicy(uid);
138         } catch (RemoteException e) {
139             return POLICY_NONE;
140         }
141     }
142 
getUidsWithPolicy(int policy)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 
registerListener(INetworkPolicyListener listener)151     public void registerListener(INetworkPolicyListener listener) {
152         try {
153             mService.registerListener(listener);
154         } catch (RemoteException e) {
155         }
156     }
157 
unregisterListener(INetworkPolicyListener listener)158     public void unregisterListener(INetworkPolicyListener listener) {
159         try {
160             mService.unregisterListener(listener);
161         } catch (RemoteException e) {
162         }
163     }
164 
setNetworkPolicies(NetworkPolicy[] policies)165     public void setNetworkPolicies(NetworkPolicy[] policies) {
166         try {
167             mService.setNetworkPolicies(policies);
168         } catch (RemoteException e) {
169         }
170     }
171 
getNetworkPolicies()172     public NetworkPolicy[] getNetworkPolicies() {
173         try {
174             return mService.getNetworkPolicies(mContext.getOpPackageName());
175         } catch (RemoteException e) {
176             return null;
177         }
178     }
179 
setRestrictBackground(boolean restrictBackground)180     public void setRestrictBackground(boolean restrictBackground) {
181         try {
182             mService.setRestrictBackground(restrictBackground);
183         } catch (RemoteException e) {
184         }
185     }
186 
getRestrictBackground()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      */
factoryReset(String subscriber)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      */
computeLastCycleBoundary(long currentTime, NetworkPolicy policy)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} */
computeNextCycleBoundary(long currentTime, NetworkPolicy policy)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      */
snapToCycleDay(Time time, int cycleDay)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
isUidValidForPolicy(Context context, int uid)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} */
dumpPolicy(PrintWriter fout, int policy)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} */
dumpRules(PrintWriter fout, int rules)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