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