NetworkPolicyManager.java revision 8fc27e8b87bd1def854a03d84009143b315d4176
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.text.format.Time; 30 31import com.google.android.collect.Sets; 32 33import java.io.PrintWriter; 34import java.util.HashSet; 35 36/** 37 * Manager for creating and modifying network policy rules. 38 * 39 * {@hide} 40 */ 41public class NetworkPolicyManager { 42 43 /** No specific network policy, use system default. */ 44 public static final int POLICY_NONE = 0x0; 45 /** Reject network usage on metered networks when application in background. */ 46 public static final int POLICY_REJECT_METERED_BACKGROUND = 0x1; 47 48 /** All network traffic should be allowed. */ 49 public static final int RULE_ALLOW_ALL = 0x0; 50 /** Reject traffic on metered networks. */ 51 public static final int RULE_REJECT_METERED = 0x1; 52 53 private static final boolean ALLOW_PLATFORM_APP_POLICY = true; 54 55 /** 56 * {@link Intent} extra that indicates which {@link NetworkTemplate} rule it 57 * applies to. 58 */ 59 public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE"; 60 61 private INetworkPolicyManager mService; 62 63 public NetworkPolicyManager(INetworkPolicyManager service) { 64 if (service == null) { 65 throw new IllegalArgumentException("missing INetworkPolicyManager"); 66 } 67 mService = service; 68 } 69 70 public static NetworkPolicyManager from(Context context) { 71 return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE); 72 } 73 74 /** 75 * Set policy flags for specific application. 76 * 77 * @param policy {@link #POLICY_NONE} or combination of flags like 78 * {@link #POLICY_REJECT_METERED_BACKGROUND}. 79 */ 80 public void setAppPolicy(int appId, int policy) { 81 try { 82 mService.setAppPolicy(appId, policy); 83 } catch (RemoteException e) { 84 } 85 } 86 87 public int getAppPolicy(int appId) { 88 try { 89 return mService.getAppPolicy(appId); 90 } catch (RemoteException e) { 91 return POLICY_NONE; 92 } 93 } 94 95 public void registerListener(INetworkPolicyListener listener) { 96 try { 97 mService.registerListener(listener); 98 } catch (RemoteException e) { 99 } 100 } 101 102 public void unregisterListener(INetworkPolicyListener listener) { 103 try { 104 mService.unregisterListener(listener); 105 } catch (RemoteException e) { 106 } 107 } 108 109 public void setNetworkPolicies(NetworkPolicy[] policies) { 110 try { 111 mService.setNetworkPolicies(policies); 112 } catch (RemoteException e) { 113 } 114 } 115 116 public NetworkPolicy[] getNetworkPolicies() { 117 try { 118 return mService.getNetworkPolicies(); 119 } catch (RemoteException e) { 120 return null; 121 } 122 } 123 124 public void setRestrictBackground(boolean restrictBackground) { 125 try { 126 mService.setRestrictBackground(restrictBackground); 127 } catch (RemoteException e) { 128 } 129 } 130 131 public boolean getRestrictBackground() { 132 try { 133 return mService.getRestrictBackground(); 134 } catch (RemoteException e) { 135 return false; 136 } 137 } 138 139 /** 140 * Compute the last cycle boundary for the given {@link NetworkPolicy}. For 141 * example, if cycle day is 20th, and today is June 15th, it will return May 142 * 20th. When cycle day doesn't exist in current month, it snaps to the 1st 143 * of following month. 144 * 145 * @hide 146 */ 147 public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) { 148 if (policy.cycleDay == CYCLE_NONE) { 149 throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); 150 } 151 152 final Time now = new Time(policy.cycleTimezone); 153 now.set(currentTime); 154 155 // first, find cycle boundary for current month 156 final Time cycle = new Time(now); 157 cycle.hour = cycle.minute = cycle.second = 0; 158 snapToCycleDay(cycle, policy.cycleDay); 159 160 if (Time.compare(cycle, now) >= 0) { 161 // cycle boundary is beyond now, use last cycle boundary; start by 162 // pushing ourselves squarely into last month. 163 final Time lastMonth = new Time(now); 164 lastMonth.hour = lastMonth.minute = lastMonth.second = 0; 165 lastMonth.monthDay = 1; 166 lastMonth.month -= 1; 167 lastMonth.normalize(true); 168 169 cycle.set(lastMonth); 170 snapToCycleDay(cycle, policy.cycleDay); 171 } 172 173 return cycle.toMillis(true); 174 } 175 176 /** {@hide} */ 177 public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) { 178 if (policy.cycleDay == CYCLE_NONE) { 179 throw new IllegalArgumentException("Unable to compute boundary without cycleDay"); 180 } 181 182 final Time now = new Time(policy.cycleTimezone); 183 now.set(currentTime); 184 185 // first, find cycle boundary for current month 186 final Time cycle = new Time(now); 187 cycle.hour = cycle.minute = cycle.second = 0; 188 snapToCycleDay(cycle, policy.cycleDay); 189 190 if (Time.compare(cycle, now) <= 0) { 191 // cycle boundary is before now, use next cycle boundary; start by 192 // pushing ourselves squarely into next month. 193 final Time nextMonth = new Time(now); 194 nextMonth.hour = nextMonth.minute = nextMonth.second = 0; 195 nextMonth.monthDay = 1; 196 nextMonth.month += 1; 197 nextMonth.normalize(true); 198 199 cycle.set(nextMonth); 200 snapToCycleDay(cycle, policy.cycleDay); 201 } 202 203 return cycle.toMillis(true); 204 } 205 206 /** 207 * Snap to the cycle day for the current month given; when cycle day doesn't 208 * exist, it snaps to last second of current month. 209 * 210 * @hide 211 */ 212 public static void snapToCycleDay(Time time, int cycleDay) { 213 if (cycleDay > time.getActualMaximum(MONTH_DAY)) { 214 // cycle day isn't valid this month; snap to last second of month 215 time.month += 1; 216 time.monthDay = 1; 217 time.second = -1; 218 } else { 219 time.monthDay = cycleDay; 220 } 221 time.normalize(true); 222 } 223 224 /** 225 * Check if given UID can have a {@link #setUidPolicy(int, int)} defined, 226 * usually to protect critical system services. 227 */ 228 @Deprecated 229 public static boolean isUidValidForPolicy(Context context, int uid) { 230 // first, quick-reject non-applications 231 if (uid < android.os.Process.FIRST_APPLICATION_UID 232 || uid > android.os.Process.LAST_APPLICATION_UID) { 233 return false; 234 } 235 236 if (!ALLOW_PLATFORM_APP_POLICY) { 237 final PackageManager pm = context.getPackageManager(); 238 final HashSet<Signature> systemSignature; 239 try { 240 systemSignature = Sets.newHashSet( 241 pm.getPackageInfo("android", GET_SIGNATURES).signatures); 242 } catch (NameNotFoundException e) { 243 throw new RuntimeException("problem finding system signature", e); 244 } 245 246 try { 247 // reject apps signed with platform cert 248 for (String packageName : pm.getPackagesForUid(uid)) { 249 final HashSet<Signature> packageSignature = Sets.newHashSet( 250 pm.getPackageInfo(packageName, GET_SIGNATURES).signatures); 251 if (packageSignature.containsAll(systemSignature)) { 252 return false; 253 } 254 } 255 } catch (NameNotFoundException e) { 256 } 257 } 258 259 // nothing found above; we can apply policy to UID 260 return true; 261 } 262 263 /** {@hide} */ 264 public static void dumpPolicy(PrintWriter fout, int policy) { 265 fout.write("["); 266 if ((policy & POLICY_REJECT_METERED_BACKGROUND) != 0) { 267 fout.write("REJECT_METERED_BACKGROUND"); 268 } 269 fout.write("]"); 270 } 271 272 /** {@hide} */ 273 public static void dumpRules(PrintWriter fout, int rules) { 274 fout.write("["); 275 if ((rules & RULE_REJECT_METERED) != 0) { 276 fout.write("REJECT_METERED"); 277 } 278 fout.write("]"); 279 } 280 281} 282