1 /* 2 * Copyright (C) 2016 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 com.android.server.net; 18 19 import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND; 20 import static android.net.NetworkPolicyManager.POLICY_NONE; 21 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 22 23 import android.content.Context; 24 import android.net.NetworkPolicyManager; 25 import android.net.wifi.WifiConfiguration; 26 import android.net.wifi.WifiManager; 27 import android.os.RemoteException; 28 import android.os.ShellCommand; 29 30 import java.io.PrintWriter; 31 import java.util.List; 32 33 class NetworkPolicyManagerShellCommand extends ShellCommand { 34 35 private final NetworkPolicyManagerService mInterface; 36 private final WifiManager mWifiManager; 37 38 NetworkPolicyManagerShellCommand(Context context, NetworkPolicyManagerService service) { 39 mInterface = service; 40 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 41 } 42 43 @Override 44 public int onCommand(String cmd) { 45 if (cmd == null) { 46 return handleDefaultCommands(cmd); 47 } 48 final PrintWriter pw = getOutPrintWriter(); 49 try { 50 switch(cmd) { 51 case "get": 52 return runGet(); 53 case "set": 54 return runSet(); 55 case "list": 56 return runList(); 57 case "add": 58 return runAdd(); 59 case "remove": 60 return runRemove(); 61 default: 62 return handleDefaultCommands(cmd); 63 } 64 } catch (RemoteException e) { 65 pw.println("Remote exception: " + e); 66 } 67 return -1; 68 } 69 70 @Override 71 public void onHelp() { 72 final PrintWriter pw = getOutPrintWriter(); 73 pw.println("Network policy manager (netpolicy) commands:"); 74 pw.println(" help"); 75 pw.println(" Print this help text."); 76 pw.println(""); 77 pw.println(" add restrict-background-whitelist UID"); 78 pw.println(" Adds a UID to the whitelist for restrict background usage."); 79 pw.println(" add restrict-background-blacklist UID"); 80 pw.println(" Adds a UID to the blacklist for restrict background usage."); 81 pw.println(" get restrict-background"); 82 pw.println(" Gets the global restrict background usage status."); 83 pw.println(" list wifi-networks [true|false]"); 84 pw.println(" Lists all saved wifi networks and whether they are metered or not."); 85 pw.println(" If a boolean argument is passed, filters just the metered (or unmetered)"); 86 pw.println(" networks."); 87 pw.println(" list restrict-background-whitelist"); 88 pw.println(" Lists UIDs that are whitelisted for restrict background usage."); 89 pw.println(" list restrict-background-blacklist"); 90 pw.println(" Lists UIDs that are blacklisted for restrict background usage."); 91 pw.println(" remove restrict-background-whitelist UID"); 92 pw.println(" Removes a UID from the whitelist for restrict background usage."); 93 pw.println(" remove restrict-background-blacklist UID"); 94 pw.println(" Removes a UID from the blacklist for restrict background usage."); 95 pw.println(" set metered-network ID [undefined|true|false]"); 96 pw.println(" Toggles whether the given wi-fi network is metered."); 97 pw.println(" set restrict-background BOOLEAN"); 98 pw.println(" Sets the global restrict background usage status."); 99 pw.println(" set sub-plan-owner subId [packageName]"); 100 pw.println(" Sets the data plan owner package for subId."); 101 } 102 103 private int runGet() throws RemoteException { 104 final PrintWriter pw = getOutPrintWriter(); 105 final String type = getNextArg(); 106 if (type == null) { 107 pw.println("Error: didn't specify type of data to get"); 108 return -1; 109 } 110 switch(type) { 111 case "restrict-background": 112 return getRestrictBackground(); 113 } 114 pw.println("Error: unknown get type '" + type + "'"); 115 return -1; 116 } 117 118 private int runSet() throws RemoteException { 119 final PrintWriter pw = getOutPrintWriter(); 120 final String type = getNextArg(); 121 if (type == null) { 122 pw.println("Error: didn't specify type of data to set"); 123 return -1; 124 } 125 switch(type) { 126 case "metered-network": 127 return setMeteredWifiNetwork(); 128 case "restrict-background": 129 return setRestrictBackground(); 130 case "sub-plan-owner": 131 return setSubPlanOwner(); 132 } 133 pw.println("Error: unknown set type '" + type + "'"); 134 return -1; 135 } 136 137 private int runList() throws RemoteException { 138 final PrintWriter pw = getOutPrintWriter(); 139 final String type = getNextArg(); 140 if (type == null) { 141 pw.println("Error: didn't specify type of data to list"); 142 return -1; 143 } 144 switch(type) { 145 case "wifi-networks": 146 return listWifiNetworks(); 147 case "restrict-background-whitelist": 148 return listRestrictBackgroundWhitelist(); 149 case "restrict-background-blacklist": 150 return listRestrictBackgroundBlacklist(); 151 } 152 pw.println("Error: unknown list type '" + type + "'"); 153 return -1; 154 } 155 156 private int runAdd() throws RemoteException { 157 final PrintWriter pw = getOutPrintWriter(); 158 final String type = getNextArg(); 159 if (type == null) { 160 pw.println("Error: didn't specify type of data to add"); 161 return -1; 162 } 163 switch(type) { 164 case "restrict-background-whitelist": 165 return addRestrictBackgroundWhitelist(); 166 case "restrict-background-blacklist": 167 return addRestrictBackgroundBlacklist(); 168 } 169 pw.println("Error: unknown add type '" + type + "'"); 170 return -1; 171 } 172 173 private int runRemove() throws RemoteException { 174 final PrintWriter pw = getOutPrintWriter(); 175 final String type = getNextArg(); 176 if (type == null) { 177 pw.println("Error: didn't specify type of data to remove"); 178 return -1; 179 } 180 switch(type) { 181 case "restrict-background-whitelist": 182 return removeRestrictBackgroundWhitelist(); 183 case "restrict-background-blacklist": 184 return removeRestrictBackgroundBlacklist(); 185 } 186 pw.println("Error: unknown remove type '" + type + "'"); 187 return -1; 188 } 189 190 private int listUidPolicies(String msg, int policy) throws RemoteException { 191 final PrintWriter pw = getOutPrintWriter(); 192 final int[] uids = mInterface.getUidsWithPolicy(policy); 193 pw.print(msg); pw.print(": "); 194 if (uids.length == 0) { 195 pw.println("none"); 196 } else { 197 for (int i = 0; i < uids.length; i++) { 198 int uid = uids[i]; 199 pw.print(uid); 200 pw.print(' '); 201 } 202 } 203 pw.println(); 204 return 0; 205 } 206 207 private int listRestrictBackgroundWhitelist() throws RemoteException { 208 return listUidPolicies("Restrict background whitelisted UIDs", 209 POLICY_ALLOW_METERED_BACKGROUND); 210 } 211 212 private int listRestrictBackgroundBlacklist() throws RemoteException { 213 return listUidPolicies("Restrict background blacklisted UIDs", 214 POLICY_REJECT_METERED_BACKGROUND); 215 } 216 217 private int getRestrictBackground() throws RemoteException { 218 final PrintWriter pw = getOutPrintWriter(); 219 pw.print("Restrict background status: "); 220 pw.println(mInterface.getRestrictBackground() ? "enabled" : "disabled"); 221 return 0; 222 } 223 224 private int setRestrictBackground() throws RemoteException { 225 final int enabled = getNextBooleanArg(); 226 if (enabled < 0) { 227 return enabled; 228 } 229 mInterface.setRestrictBackground(enabled > 0); 230 return 0; 231 } 232 233 private int setSubPlanOwner() throws RemoteException { 234 final int subId = Integer.parseInt(getNextArgRequired()); 235 final String packageName = getNextArg(); 236 mInterface.setSubscriptionPlansOwner(subId, packageName); 237 return 0; 238 } 239 240 private int setUidPolicy(int policy) throws RemoteException { 241 final int uid = getUidFromNextArg(); 242 if (uid < 0) { 243 return uid; 244 } 245 mInterface.setUidPolicy(uid, policy); 246 return 0; 247 } 248 249 private int resetUidPolicy(String errorMessage, int expectedPolicy) throws RemoteException { 250 final int uid = getUidFromNextArg(); 251 if (uid < 0) { 252 return uid; 253 } 254 int actualPolicy = mInterface.getUidPolicy(uid); 255 if (actualPolicy != expectedPolicy) { 256 final PrintWriter pw = getOutPrintWriter(); 257 pw.print("Error: UID "); pw.print(uid); pw.print(' '); pw.println(errorMessage); 258 return -1; 259 } 260 mInterface.setUidPolicy(uid, POLICY_NONE); 261 return 0; 262 } 263 264 private int addRestrictBackgroundWhitelist() throws RemoteException { 265 return setUidPolicy(POLICY_ALLOW_METERED_BACKGROUND); 266 } 267 268 private int removeRestrictBackgroundWhitelist() throws RemoteException { 269 return resetUidPolicy("not whitelisted", POLICY_ALLOW_METERED_BACKGROUND); 270 } 271 272 private int addRestrictBackgroundBlacklist() throws RemoteException { 273 return setUidPolicy(POLICY_REJECT_METERED_BACKGROUND); 274 } 275 276 private int removeRestrictBackgroundBlacklist() throws RemoteException { 277 return resetUidPolicy("not blacklisted", POLICY_REJECT_METERED_BACKGROUND); 278 } 279 280 private int listWifiNetworks() { 281 final PrintWriter pw = getOutPrintWriter(); 282 final String arg = getNextArg(); 283 final int match; 284 if (arg == null) { 285 match = WifiConfiguration.METERED_OVERRIDE_NONE; 286 } else if (Boolean.parseBoolean(arg)) { 287 match = WifiConfiguration.METERED_OVERRIDE_METERED; 288 } else { 289 match = WifiConfiguration.METERED_OVERRIDE_NOT_METERED; 290 } 291 292 final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks(); 293 for (WifiConfiguration config : configs) { 294 if (arg == null || config.meteredOverride == match) { 295 pw.print(NetworkPolicyManager.resolveNetworkId(config)); 296 pw.print(';'); 297 pw.println(overrideToString(config.meteredOverride)); 298 } 299 } 300 return 0; 301 } 302 303 private int setMeteredWifiNetwork() throws RemoteException { 304 final PrintWriter pw = getOutPrintWriter(); 305 final String networkId = getNextArg(); 306 if (networkId == null) { 307 pw.println("Error: didn't specify networkId"); 308 return -1; 309 } 310 final String arg = getNextArg(); 311 if (arg == null) { 312 pw.println("Error: didn't specify meteredOverride"); 313 return -1; 314 } 315 mInterface.setWifiMeteredOverride(NetworkPolicyManager.resolveNetworkId(networkId), 316 stringToOverride(arg)); 317 return -1; 318 } 319 320 private static String overrideToString(int override) { 321 switch (override) { 322 case WifiConfiguration.METERED_OVERRIDE_METERED: return "true"; 323 case WifiConfiguration.METERED_OVERRIDE_NOT_METERED: return "false"; 324 default: return "none"; 325 } 326 } 327 328 private static int stringToOverride(String override) { 329 switch (override) { 330 case "true": return WifiConfiguration.METERED_OVERRIDE_METERED; 331 case "false": return WifiConfiguration.METERED_OVERRIDE_NOT_METERED; 332 default: return WifiConfiguration.METERED_OVERRIDE_NONE; 333 } 334 } 335 336 private int getNextBooleanArg() { 337 final PrintWriter pw = getOutPrintWriter(); 338 final String arg = getNextArg(); 339 if (arg == null) { 340 pw.println("Error: didn't specify BOOLEAN"); 341 return -1; 342 } 343 return Boolean.valueOf(arg) ? 1 : 0; 344 } 345 346 private int getUidFromNextArg() { 347 final PrintWriter pw = getOutPrintWriter(); 348 final String arg = getNextArg(); 349 if (arg == null) { 350 pw.println("Error: didn't specify UID"); 351 return -1; 352 } 353 try { 354 return Integer.parseInt(arg); 355 } catch (NumberFormatException e) { 356 pw.println("Error: UID (" + arg + ") should be a number"); 357 return -2; 358 } 359 } 360 } 361