NetworkPolicyManager.java revision 16a16899505ec0a9ede5b76650bfb8817b3227c7
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 17package android.net; 18 19import static android.content.pm.PackageManager.GET_SIGNATURES; 20import static android.net.NetworkPolicy.CYCLE_NONE; 21import static android.text.format.Time.MONTH_DAY; 22 23import android.content.Context; 24import android.content.Intent; 25import android.content.pm.PackageManager; 26import android.content.pm.PackageManager.NameNotFoundException; 27import android.content.pm.Signature; 28import android.os.RemoteException; 29import android.os.UserHandle; 30import android.text.format.Time; 31 32import com.google.android.collect.Sets; 33 34import java.io.PrintWriter; 35import java.util.HashSet; 36 37/** 38 * Manager for creating and modifying network policy rules. 39 * 40 * {@hide} 41 */ 42public class NetworkPolicyManager { 43 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; 48 /** Allow network use (metered or not) in the background in battery save mode. */ 49 public static final int POLICY_ALLOW_BACKGROUND_BATTERY_SAVE = 0x2; 50 51 /** All network traffic should be allowed. */ 52 public static final int RULE_ALLOW_ALL = 0x0; 53 /** Reject traffic on metered networks. */ 54 public static final int RULE_REJECT_METERED = 0x1; 55 56 private static final boolean ALLOW_PLATFORM_APP_POLICY = true; 57 58 /** 59 * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it 60 * applies to. 61 */ 62 public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE"; 63 64 private final Context mContext; 65 private INetworkPolicyManager mService; 66 67 public NetworkPolicyManager(Context context, INetworkPolicyManager service) { 68 if (service == null) { 69 throw new IllegalArgumentException("missing INetworkPolicyManager"); 70 } 71 mContext = context; 72 mService = service; 73 } 74 75 public static NetworkPolicyManager from(Context context) { 76 return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE); 77 } 78 79 /** 80 * Set policy flags for specific UID. 81 * 82 * @param policy {@link #POLICY_NONE} or combination of flags like 83 * {@link #POLICY_REJECT_METERED_BACKGROUND}, {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. 84 */ 85 public void setUidPolicy(int uid, int policy) { 86 try { 87 mService.setUidPolicy(uid, policy); 88 } catch (RemoteException e) { 89 } 90 } 91 92 /** 93 * Add policy flags for specific UID. The given policy bits will be set for 94 * the uid. Policy flags may be either 95 * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. 96 */ 97 public void addUidPolicy(int uid, int policy) { 98 try { 99 mService.addUidPolicy(uid, policy); 100 } catch (RemoteException e) { 101 } 102 } 103 104 /** 105 * Clear/remove policy flags for specific UID. The given policy bits will be set for 106 * the uid. Policy flags may be either 107 * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. 108 */ 109 public void removeUidPolicy(int uid, int policy) { 110 try { 111 mService.removeUidPolicy(uid, policy); 112 } catch (RemoteException e) { 113 } 114 } 115 116 public int getUidPolicy(int uid) { 117 try { 118 return mService.getUidPolicy(uid); 119 } catch (RemoteException e) { 120 return POLICY_NONE; 121 } 122 } 123 124 public int[] getUidsWithPolicy(int policy) { 125 try { 126 return mService.getUidsWithPolicy(policy); 127 } catch (RemoteException e) { 128 return new int[0]; 129 } 130 } 131 132 public int[] getPowerSaveAppIdWhitelist() { 133 try { 134 return mService.getPowerSaveAppIdWhitelist(); 135 } catch (RemoteException e) { 136 return new int[0]; 137 } 138 } 139 140 public void registerListener(INetworkPolicyListener listener) { 141 try { 142 mService.registerListener(listener); 143 } catch (RemoteException e) { 144 } 145 } 146 147 public void unregisterListener(INetworkPolicyListener listener) { 148 try { 149 mService.unregisterListener(listener); 150 } catch (RemoteException e) { 151 } 152 } 153 154 public void setNetworkPolicies(NetworkPolicy[] policies) { 155 try { 156 mService.setNetworkPolicies(policies); 157 } catch (RemoteException e) { 158 } 159 } 160 161 public NetworkPolicy[] getNetworkPolicies() { 162 try { 163 return mService.getNetworkPolicies(mContext.getOpPackageName()); 164 } catch (RemoteException e) { 165 return null; 166 } 167 } 168 169 public void setRestrictBackground(boolean restrictBackground) { 170 try { 171 mService.setRestrictBackground(restrictBackground); 172 } catch (RemoteException e) { 173 } 174 } 175 176 public boolean getRestrictBackground() { 177 try { 178 return mService.getRestrictBackground(); 179 } catch (RemoteException e) { 180 return false; 181 } 182 } 183 184 /** 185 * Resets network policy settings back to factory defaults. 186 * 187 * @hide 188 */ 189 public void factoryReset(String subscriber) { 190 // Turn mobile data limit off 191 NetworkPolicy[] policies = getNetworkPolicies(); 192 NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriber); 193 for (NetworkPolicy policy : policies) { 194 if (policy.template.equals(template)) { 195 policy.limitBytes = NetworkPolicy.LIMIT_DISABLED; 196 policy.inferred = false; 197 policy.clearSnooze(); 198 } 199 } 200 setNetworkPolicies(policies); 201 202 // Turn restrict background data off 203 setRestrictBackground(false); 204 205 // Remove app's "restrict background data" flag 206 for (int uid : getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) { 207 setUidPolicy(uid, NetworkPolicyManager.POLICY_NONE); 208 } 209 } 210 211 /** 212 * Compute the last cycle boundary for the given {@link NetworkPolicy}. For 213 * example, if cycle day is 20th, and today is June 15th, it will return May 214 * 20th. When cycle day doesn't exist in current month, it snaps to the 1st 215 * of following month. 216 * 217 * @hide 218 */ 219 public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) { 220 if (policy.cycleDay == CYCLE_NONE) { 221 throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); 222 } 223 224 final Time now = new Time(policy.cycleTimezone); 225 now.set(currentTime); 226 227 // first, find cycle boundary for current month 228 final Time cycle = new Time(now); 229 cycle.hour = cycle.minute = cycle.second = 0; 230 snapToCycleDay(cycle, policy.cycleDay); 231 232 if (Time.compare(cycle, now) >= 0) { 233 // cycle boundary is beyond now, use last cycle boundary; start by 234 // pushing ourselves squarely into last month. 235 final Time lastMonth = new Time(now); 236 lastMonth.hour = lastMonth.minute = lastMonth.second = 0; 237 lastMonth.monthDay = 1; 238 lastMonth.month -= 1; 239 lastMonth.normalize(true); 240 241 cycle.set(lastMonth); 242 snapToCycleDay(cycle, policy.cycleDay); 243 } 244 245 return cycle.toMillis(true); 246 } 247 248 /** {@hide} */ 249 public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) { 250 if (policy.cycleDay == CYCLE_NONE) { 251 throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); 252 } 253 254 final Time now = new Time(policy.cycleTimezone); 255 now.set(currentTime); 256 257 // first, find cycle boundary for current month 258 final Time cycle = new Time(now); 259 cycle.hour = cycle.minute = cycle.second = 0; 260 snapToCycleDay(cycle, policy.cycleDay); 261 262 if (Time.compare(cycle, now) <= 0) { 263 // cycle boundary is before now, use next cycle boundary; start by 264 // pushing ourselves squarely into next month. 265 final Time nextMonth = new Time(now); 266 nextMonth.hour = nextMonth.minute = nextMonth.second = 0; 267 nextMonth.monthDay = 1; 268 nextMonth.month += 1; 269 nextMonth.normalize(true); 270 271 cycle.set(nextMonth); 272 snapToCycleDay(cycle, policy.cycleDay); 273 } 274 275 return cycle.toMillis(true); 276 } 277 278 /** 279 * Snap to the cycle day for the current month given; when cycle day doesn't 280 * exist, it snaps to last second of current month. 281 * 282 * @hide 283 */ 284 public static void snapToCycleDay(Time time, int cycleDay) { 285 if (cycleDay > time.getActualMaximum(MONTH_DAY)) { 286 // cycle day isn't valid this month; snap to last second of month 287 time.month += 1; 288 time.monthDay = 1; 289 time.second = -1; 290 } else { 291 time.monthDay = cycleDay; 292 } 293 time.normalize(true); 294 } 295 296 /** 297 * Check if given UID can have a {@link #setUidPolicy(int, int)} defined, 298 * usually to protect critical system services. 299 */ 300 @Deprecated 301 public static boolean isUidValidForPolicy(Context context, int uid) { 302 // first, quick-reject non-applications 303 if (!UserHandle.isApp(uid)) { 304 return false; 305 } 306 307 if (!ALLOW_PLATFORM_APP_POLICY) { 308 final PackageManager pm = context.getPackageManager(); 309 final HashSet<Signature> systemSignature; 310 try { 311 systemSignature = Sets.newHashSet( 312 pm.getPackageInfo("android", GET_SIGNATURES).signatures); 313 } catch (NameNotFoundException e) { 314 throw new RuntimeException("problem finding system signature", e); 315 } 316 317 try { 318 // reject apps signed with platform cert 319 for (String packageName : pm.getPackagesForUid(uid)) { 320 final HashSet<Signature> packageSignature = Sets.newHashSet( 321 pm.getPackageInfo(packageName, GET_SIGNATURES).signatures); 322 if (packageSignature.containsAll(systemSignature)) { 323 return false; 324 } 325 } 326 } catch (NameNotFoundException e) { 327 } 328 } 329 330 // nothing found above; we can apply policy to UID 331 return true; 332 } 333 334 /** {@hide} */ 335 public static void dumpPolicy(PrintWriter fout, int policy) { 336 fout.write("["); 337 if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 338 fout.write("REJECT_METERED_BACKGROUND"); 339 } 340 fout.write("]"); 341 } 342 343 /** {@hide} */ 344 public static void dumpRules(PrintWriter fout, int rules) { 345 fout.write("["); 346 if ((rules & RULE_REJECT_METERED) != 0) { 347 fout.write("REJECT_METERED"); 348 } 349 fout.write("]"); 350 } 351 352} 353