Home | History | Annotate | Download | only in net
      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