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 /** 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 INetworkPolicyManager mService; 65 66 public NetworkPolicyManager(INetworkPolicyManager service) { 67 if (service == null) { 68 throw new IllegalArgumentException("missing INetworkPolicyManager"); 69 } 70 mService = service; 71 } 72 73 public static NetworkPolicyManager from(Context context) { 74 return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE); 75 } 76 77 /** 78 * Set policy flags for specific UID. 79 * 80 * @param policy {@link #POLICY_NONE} or combination of flags like 81 * {@link #POLICY_REJECT_METERED_BACKGROUND}, {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. 82 */ 83 public void setUidPolicy(int uid, int policy) { 84 try { 85 mService.setUidPolicy(uid, policy); 86 } catch (RemoteException e) { 87 } 88 } 89 90 /** 91 * Add policy flags for specific UID. The given policy bits will be set for 92 * the uid. Policy flags may be either 93 * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. 94 */ 95 public void addUidPolicy(int uid, int policy) { 96 try { 97 mService.addUidPolicy(uid, policy); 98 } catch (RemoteException e) { 99 } 100 } 101 102 /** 103 * Clear/remove policy flags for specific UID. The given policy bits will be set for 104 * the uid. Policy flags may be either 105 * {@link #POLICY_REJECT_METERED_BACKGROUND} or {@link #POLICY_ALLOW_BACKGROUND_BATTERY_SAVE}. 106 */ 107 public void removeUidPolicy(int uid, int policy) { 108 try { 109 mService.removeUidPolicy(uid, policy); 110 } catch (RemoteException e) { 111 } 112 } 113 114 public int getUidPolicy(int uid) { 115 try { 116 return mService.getUidPolicy(uid); 117 } catch (RemoteException e) { 118 return POLICY_NONE; 119 } 120 } 121 122 public int[] getUidsWithPolicy(int policy) { 123 try { 124 return mService.getUidsWithPolicy(policy); 125 } catch (RemoteException e) { 126 return new int[0]; 127 } 128 } 129 130 public int[] getPowerSaveAppIdWhitelist() { 131 try { 132 return mService.getPowerSaveAppIdWhitelist(); 133 } catch (RemoteException e) { 134 return new int[0]; 135 } 136 } 137 138 public void registerListener(INetworkPolicyListener listener) { 139 try { 140 mService.registerListener(listener); 141 } catch (RemoteException e) { 142 } 143 } 144 145 public void unregisterListener(INetworkPolicyListener listener) { 146 try { 147 mService.unregisterListener(listener); 148 } catch (RemoteException e) { 149 } 150 } 151 152 public void setNetworkPolicies(NetworkPolicy[] policies) { 153 try { 154 mService.setNetworkPolicies(policies); 155 } catch (RemoteException e) { 156 } 157 } 158 159 public NetworkPolicy[] getNetworkPolicies() { 160 try { 161 return mService.getNetworkPolicies(); 162 } catch (RemoteException e) { 163 return null; 164 } 165 } 166 167 public void setRestrictBackground(boolean restrictBackground) { 168 try { 169 mService.setRestrictBackground(restrictBackground); 170 } catch (RemoteException e) { 171 } 172 } 173 174 public boolean getRestrictBackground() { 175 try { 176 return mService.getRestrictBackground(); 177 } catch (RemoteException e) { 178 return false; 179 } 180 } 181 182 /** 183 * Compute the last cycle boundary for the given {@link NetworkPolicy}. For 184 * example, if cycle day is 20th, and today is June 15th, it will return May 185 * 20th. When cycle day doesn't exist in current month, it snaps to the 1st 186 * of following month. 187 * 188 * @hide 189 */ 190 public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) { 191 if (policy.cycleDay == CYCLE_NONE) { 192 throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); 193 } 194 195 final Time now = new Time(policy.cycleTimezone); 196 now.set(currentTime); 197 198 // first, find cycle boundary for current month 199 final Time cycle = new Time(now); 200 cycle.hour = cycle.minute = cycle.second = 0; 201 snapToCycleDay(cycle, policy.cycleDay); 202 203 if (Time.compare(cycle, now) >= 0) { 204 // cycle boundary is beyond now, use last cycle boundary; start by 205 // pushing ourselves squarely into last month. 206 final Time lastMonth = new Time(now); 207 lastMonth.hour = lastMonth.minute = lastMonth.second = 0; 208 lastMonth.monthDay = 1; 209 lastMonth.month -= 1; 210 lastMonth.normalize(true); 211 212 cycle.set(lastMonth); 213 snapToCycleDay(cycle, policy.cycleDay); 214 } 215 216 return cycle.toMillis(true); 217 } 218 219 /** {@hide} */ 220 public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) { 221 if (policy.cycleDay == CYCLE_NONE) { 222 throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); 223 } 224 225 final Time now = new Time(policy.cycleTimezone); 226 now.set(currentTime); 227 228 // first, find cycle boundary for current month 229 final Time cycle = new Time(now); 230 cycle.hour = cycle.minute = cycle.second = 0; 231 snapToCycleDay(cycle, policy.cycleDay); 232 233 if (Time.compare(cycle, now) <= 0) { 234 // cycle boundary is before now, use next cycle boundary; start by 235 // pushing ourselves squarely into next month. 236 final Time nextMonth = new Time(now); 237 nextMonth.hour = nextMonth.minute = nextMonth.second = 0; 238 nextMonth.monthDay = 1; 239 nextMonth.month += 1; 240 nextMonth.normalize(true); 241 242 cycle.set(nextMonth); 243 snapToCycleDay(cycle, policy.cycleDay); 244 } 245 246 return cycle.toMillis(true); 247 } 248 249 /** 250 * Snap to the cycle day for the current month given; when cycle day doesn't 251 * exist, it snaps to last second of current month. 252 * 253 * @hide 254 */ 255 public static void snapToCycleDay(Time time, int cycleDay) { 256 if (cycleDay > time.getActualMaximum(MONTH_DAY)) { 257 // cycle day isn't valid this month; snap to last second of month 258 time.month += 1; 259 time.monthDay = 1; 260 time.second = -1; 261 } else { 262 time.monthDay = cycleDay; 263 } 264 time.normalize(true); 265 } 266 267 /** 268 * Check if given UID can have a {@link #setUidPolicy(int, int)} defined, 269 * usually to protect critical system services. 270 */ 271 @Deprecated 272 public static boolean isUidValidForPolicy(Context context, int uid) { 273 // first, quick-reject non-applications 274 if (!UserHandle.isApp(uid)) { 275 return false; 276 } 277 278 if (!ALLOW_PLATFORM_APP_POLICY) { 279 final PackageManager pm = context.getPackageManager(); 280 final HashSet<Signature> systemSignature; 281 try { 282 systemSignature = Sets.newHashSet( 283 pm.getPackageInfo("android", GET_SIGNATURES).signatures); 284 } catch (NameNotFoundException e) { 285 throw new RuntimeException("problem finding system signature", e); 286 } 287 288 try { 289 // reject apps signed with platform cert 290 for (String packageName : pm.getPackagesForUid(uid)) { 291 final HashSet<Signature> packageSignature = Sets.newHashSet( 292 pm.getPackageInfo(packageName, GET_SIGNATURES).signatures); 293 if (packageSignature.containsAll(systemSignature)) { 294 return false; 295 } 296 } 297 } catch (NameNotFoundException e) { 298 } 299 } 300 301 // nothing found above; we can apply policy to UID 302 return true; 303 } 304 305 /** {@hide} */ 306 public static void dumpPolicy(PrintWriter fout, int policy) { 307 fout.write("["); 308 if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 309 fout.write("REJECT_METERED_BACKGROUND"); 310 } 311 fout.write("]"); 312 } 313 314 /** {@hide} */ 315 public static void dumpRules(PrintWriter fout, int rules) { 316 fout.write("["); 317 if ((rules & RULE_REJECT_METERED) != 0) { 318 fout.write("REJECT_METERED"); 319 } 320 fout.write("]"); 321 } 322 323 } 324