2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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;
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;
32 import com.google.android.collect.Sets;
34 import java.io.PrintWriter;
35 import java.util.HashSet;
38 * Manager for creating and modifying network policy rules.
42 public class NetworkPolicyManager {
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;
49 /** All network traffic should be allowed. */
50 public static final int RULE_ALLOW_ALL = 0x0;
51 /** Reject traffic on metered networks. */
52 public static final int RULE_REJECT_METERED = 0x1;
54 private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
57 * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it
60 public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
62 private INetworkPolicyManager mService;
64 public NetworkPolicyManager(INetworkPolicyManager service) {
65 if (service == null) {
66 throw new IllegalArgumentException("missing INetworkPolicyManager");
71 public static NetworkPolicyManager from(Context context) {
72 return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE);
76 * Set policy flags for specific UID.
78 * @param policy {@link #POLICY_NONE} or combination of flags like
79 * {@link #POLICY_REJECT_METERED_BACKGROUND}.
81 public void setUidPolicy(int uid, int policy) {
83 mService.setUidPolicy(uid, policy);
84 } catch (RemoteException e) {
88 public int getUidPolicy(int uid) {
90 return mService.getUidPolicy(uid);
91 } catch (RemoteException e) {
96 public int[] getUidsWithPolicy(int policy) {
98 return mService.getUidsWithPolicy(policy);
99 } catch (RemoteException e) {
104 public void registerListener(INetworkPolicyListener listener) {
106 mService.registerListener(listener);
107 } catch (RemoteException e) {
111 public void unregisterListener(INetworkPolicyListener listener) {
113 mService.unregisterListener(listener);
114 } catch (RemoteException e) {
118 public void setNetworkPolicies(NetworkPolicy[] policies) {
120 mService.setNetworkPolicies(policies);
121 } catch (RemoteException e) {
125 public NetworkPolicy[] getNetworkPolicies() {
127 return mService.getNetworkPolicies();
128 } catch (RemoteException e) {
133 public void setRestrictBackground(boolean restrictBackground) {
135 mService.setRestrictBackground(restrictBackground);
136 } catch (RemoteException e) {
140 public boolean getRestrictBackground() {
142 return mService.getRestrictBackground();
143 } catch (RemoteException e) {
149 * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
150 * example, if cycle day is 20th, and today is June 15th, it will return May
151 * 20th. When cycle day doesn't exist in current month, it snaps to the 1st
152 * of following month.
156 public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
157 if (policy.cycleDay == CYCLE_NONE) {
158 throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
161 final Time now = new Time(policy.cycleTimezone);
162 now.set(currentTime);
164 // first, find cycle boundary for current month
165 final Time cycle = new Time(now);
166 cycle.hour = cycle.minute = cycle.second = 0;
167 snapToCycleDay(cycle, policy.cycleDay);
169 if (Time.compare(cycle, now) >= 0) {
170 // cycle boundary is beyond now, use last cycle boundary; start by
171 // pushing ourselves squarely into last month.
172 final Time lastMonth = new Time(now);
173 lastMonth.hour = lastMonth.minute = lastMonth.second = 0;
174 lastMonth.monthDay = 1;
175 lastMonth.month -= 1;
176 lastMonth.normalize(true);
178 cycle.set(lastMonth);
179 snapToCycleDay(cycle, policy.cycleDay);
182 return cycle.toMillis(true);
186 public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
187 if (policy.cycleDay == CYCLE_NONE) {
188 throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
191 final Time now = new Time(policy.cycleTimezone);
192 now.set(currentTime);
194 // first, find cycle boundary for current month
195 final Time cycle = new Time(now);
196 cycle.hour = cycle.minute = cycle.second = 0;
197 snapToCycleDay(cycle, policy.cycleDay);
199 if (Time.compare(cycle, now) <= 0) {
200 // cycle boundary is before now, use next cycle boundary; start by
201 // pushing ourselves squarely into next month.
202 final Time nextMonth = new Time(now);
203 nextMonth.hour = nextMonth.minute = nextMonth.second = 0;
204 nextMonth.monthDay = 1;
205 nextMonth.month += 1;
206 nextMonth.normalize(true);
208 cycle.set(nextMonth);
209 snapToCycleDay(cycle, policy.cycleDay);
212 return cycle.toMillis(true);
216 * Snap to the cycle day for the current month given; when cycle day doesn't
217 * exist, it snaps to last second of current month.
221 public static void snapToCycleDay(Time time, int cycleDay) {
222 if (cycleDay > time.getActualMaximum(MONTH_DAY)) {
223 // cycle day isn't valid this month; snap to last second of month
228 time.monthDay = cycleDay;
230 time.normalize(true);
234 * Check if given UID can have a {@link #setUidPolicy(int, int)} defined,
235 * usually to protect critical system services.
238 public static boolean isUidValidForPolicy(Context context, int uid) {
239 // first, quick-reject non-applications
240 if (!UserHandle.isApp(uid)) {
244 if (!ALLOW_PLATFORM_APP_POLICY) {
245 final PackageManager pm = context.getPackageManager();
246 final HashSet<Signature> systemSignature;
248 systemSignature = Sets.newHashSet(
249 pm.getPackageInfo("android", GET_SIGNATURES).signatures);
250 } catch (NameNotFoundException e) {
251 throw new RuntimeException("problem finding system signature", e);
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)) {
263 } catch (NameNotFoundException e) {
267 // nothing found above; we can apply policy to UID
272 public static void dumpPolicy(PrintWriter fout, int policy) {
274 if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
275 fout.write("REJECT_METERED_BACKGROUND");
281 public static void dumpRules(PrintWriter fout, int rules) {
283 if ((rules & RULE_REJECT_METERED) != 0) {
284 fout.write("REJECT_METERED");