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 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; 53 54 private static final boolean ALLOW_PLATFORM_APP_POLICY = true; 55 56 /** 57 * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it 58 * applies to. 59 */ 60 public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE"; 61 62 private INetworkPolicyManager mService; 63 64 public NetworkPolicyManager(INetworkPolicyManager service) { 65 if (service == null) { 66 throw new IllegalArgumentException("missing INetworkPolicyManager"); 67 } 68 mService = service; 69 } 70 71 public static NetworkPolicyManager from(Context context) { 72 return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE); 73 } 74 75 /** 76 * Set policy flags for specific UID. 77 * 78 * @param policy {@link #POLICY_NONE} or combination of flags like 79 * {@link #POLICY_REJECT_METERED_BACKGROUND}. 80 */ 81 public void setUidPolicy(int uid, int policy) { 82 try { 83 mService.setUidPolicy(uid, policy); 84 } catch (RemoteException e) { 85 } 86 } 87 88 public int getUidPolicy(int uid) { 89 try { 90 return mService.getUidPolicy(uid); 91 } catch (RemoteException e) { 92 return POLICY_NONE; 93 } 94 } 95 96 public int[] getUidsWithPolicy(int policy) { 97 try { 98 return mService.getUidsWithPolicy(policy); 99 } catch (RemoteException e) { 100 return new int[0]; 101 } 102 } 103 104 public void registerListener(INetworkPolicyListener listener) { 105 try { 106 mService.registerListener(listener); 107 } catch (RemoteException e) { 108 } 109 } 110 111 public void unregisterListener(INetworkPolicyListener listener) { 112 try { 113 mService.unregisterListener(listener); 114 } catch (RemoteException e) { 115 } 116 } 117 118 public void setNetworkPolicies(NetworkPolicy[] policies) { 119 try { 120 mService.setNetworkPolicies(policies); 121 } catch (RemoteException e) { 122 } 123 } 124 125 public NetworkPolicy[] getNetworkPolicies() { 126 try { 127 return mService.getNetworkPolicies(); 128 } catch (RemoteException e) { 129 return null; 130 } 131 } 132 133 public void setRestrictBackground(boolean restrictBackground) { 134 try { 135 mService.setRestrictBackground(restrictBackground); 136 } catch (RemoteException e) { 137 } 138 } 139 140 public boolean getRestrictBackground() { 141 try { 142 return mService.getRestrictBackground(); 143 } catch (RemoteException e) { 144 return false; 145 } 146 } 147 148 /** 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. 153 * 154 * @hide 155 */ 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"); 159 } 160 161 final Time now = new Time(policy.cycleTimezone); 162 now.set(currentTime); 163 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); 168 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); 177 178 cycle.set(lastMonth); 179 snapToCycleDay(cycle, policy.cycleDay); 180 } 181 182 return cycle.toMillis(true); 183 } 184 185 /** {@hide} */ 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"); 189 } 190 191 final Time now = new Time(policy.cycleTimezone); 192 now.set(currentTime); 193 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); 198 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); 207 208 cycle.set(nextMonth); 209 snapToCycleDay(cycle, policy.cycleDay); 210 } 211 212 return cycle.toMillis(true); 213 } 214 215 /** 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. 218 * 219 * @hide 220 */ 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 224 time.month += 1; 225 time.monthDay = 1; 226 time.second = -1; 227 } else { 228 time.monthDay = cycleDay; 229 } 230 time.normalize(true); 231 } 232 233 /** 234 * Check if given UID can have a {@link #setUidPolicy(int, int)} defined, 235 * usually to protect critical system services. 236 */ 237 @Deprecated 238 public static boolean isUidValidForPolicy(Context context, int uid) { 239 // first, quick-reject non-applications 240 if (!UserHandle.isApp(uid)) { 241 return false; 242 } 243 244 if (!ALLOW_PLATFORM_APP_POLICY) { 245 final PackageManager pm = context.getPackageManager(); 246 final HashSet<Signature> systemSignature; 247 try { 248 systemSignature = Sets.newHashSet( 249 pm.getPackageInfo("android", GET_SIGNATURES).signatures); 250 } catch (NameNotFoundException e) { 251 throw new RuntimeException("problem finding system signature", e); 252 } 253 254 try { 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)) { 260 return false; 261 } 262 } 263 } catch (NameNotFoundException e) { 264 } 265 } 266 267 // nothing found above; we can apply policy to UID 268 return true; 269 } 270 271 /** {@hide} */ 272 public static void dumpPolicy(PrintWriter fout, int policy) { 273 fout.write("["); 274 if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 275 fout.write("REJECT_METERED_BACKGROUND"); 276 } 277 fout.write("]"); 278 } 279 280 /** {@hide} */ 281 public static void dumpRules(PrintWriter fout, int rules) { 282 fout.write("["); 283 if ((rules & RULE_REJECT_METERED) != 0) { 284 fout.write("REJECT_METERED"); 285 } 286 fout.write("]"); 287 } 288 289 } 290